]> git.neil.brown.name Git - history.git/commitdiff
- pre2: 2.4.0-test11pre2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:39:52 +0000 (15:39 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:39:52 +0000 (15:39 -0500)
    - Stephen Rothwell: directory notify could return with the lock held
    - Richard Henderson: CLOCKS_PER_SEC on alpha.
    - Jeff Garzik: ramfs and highmem: kmap() the page to clear it
    - Asit Mallick: enable the APIC in the official order
    - Neil Brown: avoid rd deadlock on io_request_lock by using a
      private rd-request function. This also avoids unnecessary
      request merging at this level.
    - Ben LaHaise: vmalloc threadign and overflow fix
    - Randy Dunlap: USB updates (plusb driver). PCI cacheline size.
    - Neil Brown: fix a raid1 on top of lvm bug that crept in in pre1
    - Alan Cox: various (Athlon mmx copy, NULL ptr checks for
      scsi_register etc).
    - Al Viro: fix /proc permission check security hole.
    - Can-Ru Yeou: SiS301 fbcon driver
    - Andrew Morton: NMI oopser and kernel page fault punch through
      both console_lock and timerlist_lock to make sure it prints out..
    - Jeff Garzik: clean up "kmap()" return type (it returns a kernel
      virtual address, ie a "void *").
    - Jeff Garzik: network driver docs, various one-liners.
    - David Miller: add generic "special" flag to page flags, to be
      used by architectures as they see fit. Like keeping track of
      cache coherency issues.
    - David Miller: sparc64 updates, make sparc32 boot again
    - Davdi Millner: spel "synchronous" correctly
    - David Miller: networking - fix some bridge issues, and correct
      IPv6 sysctl entries.
    - Dan Aloni: make fork.c use proper macro rather than doing
      get_exec_domain() by hand.

150 files changed:
CREDITS
Documentation/Configure.help
Documentation/cachetlb.txt
Documentation/networking/bridge.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/netdevices.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/i386/Makefile
arch/i386/kernel/apic.c
arch/i386/kernel/bluesmoke.c
arch/i386/kernel/entry.S
arch/i386/kernel/setup.c
arch/i386/kernel/traps.c
arch/i386/lib/mmx.c
arch/i386/mm/fault.c
arch/mips64/kernel/linux32.c
arch/ppc/mm/init.c
arch/sparc/kernel/ebus.c
arch/sparc/kernel/pcic.c
arch/sparc/mm/init.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc/vmlinux.lds
arch/sparc64/kernel/ebus.c
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/lib/Makefile
arch/sparc64/lib/U3copy_from_user.S [new file with mode: 0644]
arch/sparc64/lib/U3copy_in_user.S [new file with mode: 0644]
arch/sparc64/lib/U3copy_to_user.S [new file with mode: 0644]
arch/sparc64/lib/U3memcpy.S [new file with mode: 0644]
arch/sparc64/lib/VIScopy.S
arch/sparc64/mm/init.c
arch/sparc64/mm/ultra.S
arch/sparc64/vmlinux.lds
drivers/acpi/driver.c
drivers/block/loop.c
drivers/block/rd.c
drivers/i2o/i2o_block.c
drivers/i2o/i2o_core.c
drivers/ide/Makefile
drivers/isdn/act2000/module.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/pcbit/drv.c
drivers/isdn/sc/debug.c
drivers/md/lvm.c
drivers/md/md.c
drivers/md/raid1.c
drivers/net/8139too.c
drivers/net/de4x5.c
drivers/net/fc/iph5526.c
drivers/net/rrunner.c
drivers/net/sis900.c
drivers/net/sis900.h
drivers/pcmcia/cardbus.c
drivers/sbus/char/aurora.c
drivers/sbus/char/bpp.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/envctrl.c
drivers/sbus/char/flash.c
drivers/sbus/char/openprom.c
drivers/sbus/char/uctrl.c
drivers/sbus/sbus.c
drivers/scsi/3w-xxxx.c
drivers/scsi/aha152x.c
drivers/scsi/esp.c
drivers/scsi/ips.c
drivers/scsi/megaraid.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_obsolete.c
drivers/scsi/sr_ioctl.c
drivers/sound/i810_audio.c
drivers/usb/hub.c
drivers/usb/plusb.c
drivers/usb/plusb.h [deleted file]
drivers/usb/usb.c
drivers/video/Makefile
drivers/video/sis/Makefile [new file with mode: 0644]
drivers/video/sis/initdef.h [new file with mode: 0644]
drivers/video/sis/sis.h [new file with mode: 0644]
drivers/video/sis/sis_300.c [new file with mode: 0644]
drivers/video/sis/sis_300.h [new file with mode: 0644]
drivers/video/sis/sis_301.c [new file with mode: 0644]
drivers/video/sis/sis_301.h [new file with mode: 0644]
drivers/video/sis/sis_main.c [new file with mode: 0644]
drivers/video/sisfb.c [deleted file]
fs/Config.in
fs/affs/symlink.c
fs/buffer.c
fs/coda/symlink.c
fs/dnotify.c
fs/efs/symlink.c
fs/exec.c
fs/hpfs/namei.c
fs/isofs/rock.c
fs/namei.c
fs/ncpfs/dir.c
fs/ncpfs/symlink.c
fs/nfs/dir.c
fs/nfs/read.c
fs/nfs/symlink.c
fs/nfs/write.c
fs/proc/base.c
fs/ramfs/inode.c
fs/smbfs/cache.c
fs/udf/file.c
fs/udf/symlink.c
fs/umsdos/dir.c
fs/umsdos/emd.c
include/asm-alpha/param.h
include/asm-i386/highmem.h
include/asm-ppc/highmem.h
include/asm-sparc/bpp.h
include/asm-sparc/highmem.h
include/asm-sparc/openpromio.h
include/asm-sparc/pgtable.h
include/asm-sparc64/bpp.h
include/asm-sparc64/envctrl.h
include/asm-sparc64/module.h
include/asm-sparc64/openpromio.h
include/asm-sparc64/pgalloc.h
include/asm-sparc64/pgtable.h
include/linux/blk.h
include/linux/fb.h
include/linux/highmem.h
include/linux/mm.h
include/linux/pci_ids.h
include/linux/sisfb.h
kernel/fork.c
kernel/ptrace.c
kernel/resource.c
kernel/sched.c
mm/filemap.c
mm/highmem.c
mm/swap_state.c
mm/vmalloc.c
net/Makefile
net/README
net/atm/pvc.c
net/bridge/br_fdb.c
net/bridge/br_if.c
net/bridge/br_ioctl.c
net/core/scm.c
net/ipv6/route.c
net/ipx/Config.in
net/khttpd/datasending.c

diff --git a/CREDITS b/CREDITS
index db47eeb14042e6c067692d09d59df8d6a307ab32..dc9c00be991045b2a9b6341f392fb23732e6978a 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2240,11 +2240,12 @@ S: D-68789 St.Leon-Rot
 S: Germany
 
 N: Stephen Rothwell
-E: sfr@linuxcare.com
+E: sfr@linuxcare.com.au
 W: http://linuxcare.com.au/sfr
 P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
 D: Boot/setup/build work for setup > 2K
 D: Author, APM driver
+D: Directory notification
 S: 66 Maltby Circuit
 S: Wanniassa ACT 2903
 S: Australia
index eace57a6cc30fc6a2ac594bf034853b75cd3ef10..f0da27c5be2f656c9c5d00e2d274e6d707f1e394 100644 (file)
@@ -2052,6 +2052,23 @@ CONFIG_IP_NF_COMPAT_IPFWADM
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt.  If unsure, say `N'.
 
+TCP Explicit Congestion Notification support
+CONFIG_INET_ECN
+  Explicit Congestion Notification (ECN) allows routers to notify
+  clients about network congestion, resulting in fewer dropped packets
+  and increased network performance. This option adds ECN support to the
+  Linux kernel, as well as a sysctl (/proc/sys/net/ipv4/tcp_ecn) which
+  allows ECN support to be disabled at runtime.
+
+  Note that, on the Internet, there are many broken firewalls which
+  refuse connections from ECN-enabled machines, and it may be a while
+  before these firewalls are fixed. Until then, to access a site behind
+  such a firewall (some of which are major sites, at the time of this
+  writing) you will have to disable this option, either by saying N now
+  or by using the sysctl.
+
+  If in doubt, say N.
+
 SYN flood protection
 CONFIG_SYN_COOKIES
   Normal TCP/IP networking is open to an attack known as "SYN
index 952dbc6522357b148a4d5032cf07e5ebe523f911..5201a2f546296b24c0f69c1c142ae879fde6383d 100644 (file)
@@ -305,19 +305,23 @@ Here is the new interface:
        If D-cache aliasing is not an issue, this routine may
        simply be defined as a nop on that architecture.
 
-        TODO: If we set aside a few bits in page->flags as
-             "architecture private", these interfaces could
-             be implemented much more efficiently.  This would
-             allow one to "defer" (perhaps indefinitely) the
-             actual flush if there are currently no user processes
-             mapping this page.
-
-             The idea is, first at flush_dcache_page() time, if
-             page->mapping->i_mmap is an empty list, just mark
-             one of the architecture private page flag bits.
-              Later, in update_mmu_cache(), a check could be made
-             of this flag bit, and if set the flush is done
-             and the flag bit is cleared.
+        There is a bit set aside in page->flags (PG_arch_1) as
+       "architecture private".  The kernel guarentees that,
+       for pagecache pages, it will clear this bit when such
+       a page first enters the pagecache.
+
+       This allows these interfaces to be implemented much more
+       efficiently.  It allows one to "defer" (perhaps indefinitely)
+       the actual flush if there are currently no user processes
+       mapping this page.  See sparc64's flush_dcache_page and
+       update_mmu_cache implementations for an example of how to go
+       about doing this.
+
+       The idea is, first at flush_dcache_page() time, if
+       page->mapping->i_mmap{,_shared} are empty lists, just mark the
+       architecture private page flag bit.  Later, in
+       update_mmu_cache(), a check is made of this flag bit, and if
+       set the flush is done and the flag bit is cleared.
 
 XXX Not documented: flush_icache_page(), need to talk to Paul
                     Mackerras, David Mosberger-Tang, et al.
index 043a14b1650b82a35e7acccd9c0ba61152c06377..66ffb4c1fd253312c958ad6d230c6c8095b7447b 100644 (file)
@@ -1,11 +1,11 @@
 In order to use the ethernet bridging functionality you'll need the
-userspace tools available at ftp://openrock.net/bridge. The tarball
-available there contains extensive documentation, but if you still have
-questions, don't hesitate to post to the mailing list (more info at
-http://openrock.net/mailman/listinfo/bridge). You can also mail me at
-buytenh@openrock.net.
+userspace tools available at http://www.math.leidenuniv.nl/~buytenh/bridge.
+The tarball available there contains extensive documentation, but if you
+still have questions, don't hesitate to post to the mailing list (more info
+at http://www.math.leidenuniv.nl/mailman/listinfo/bridge). You can also
+mail me at buytenh@gnu.org.
 
 
 
 Lennert Buytenhek
-<buytenh@openrock.net>
+<buytenh@gnu.org>
index aade6928cc025ef743ca557df137111a02bea693..41990689115ef0da6cf8b298037244a9c2b29bf8 100644 (file)
@@ -203,7 +203,7 @@ tcp_fack - BOOLEAN
 tcp_dsack - BOOLEAN
        Allows TCP to send "duplicate" SACKs.
 
-tcp_ecn - BOOLEN
+tcp_ecn - BOOLEAN
        Enable Explicit Congestion Notification in TCP.
 
 tcp_reordering - INTEGER
@@ -376,4 +376,4 @@ kuznet@ms2.inr.ac.ru
 Updated by:
 Andi Kleen
 ak@muc.de
-$Id: ip-sysctl.txt,v 1.16 2000/08/13 18:24:11 davem Exp $
+$Id: ip-sysctl.txt,v 1.17 2000/11/06 07:15:36 davem Exp $
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
new file mode 100644 (file)
index 0000000..8769040
--- /dev/null
@@ -0,0 +1,42 @@
+
+Network Devices, the Kernel, and You!
+
+
+Introduction
+============
+The following is a random collection of documentation regarding
+network devices.
+
+
+
+struct net_device synchronization rules
+=======================================
+dev->open:
+       Locking: Inside rtnl_lock() semaphore.
+       Sleeping: OK
+
+dev->stop:
+       Locking: Inside rtnl_lock() semaphore.
+       Sleeping: OK
+
+dev->do_ioctl:
+       Locking: Inside rtnl_lock() semaphore.
+       Sleeping: OK
+
+dev->get_stats:
+       Locking: Inside dev_base_lock spinlock.
+       Sleeping: NO
+
+dev->hard_start_xmit:
+       Locking: Inside dev->xmit_lock spinlock.
+       Sleeping: NO
+
+dev->tx_timeout:
+       Locking: Inside dev->xmit_lock spinlock.
+       Sleeping: NO
+
+dev->set_multicast_list:
+       Locking: Inside dev->xmit_lock spinlock.
+       Sleeping: NO
+
+
index 4682b40e24a3bc65bdba749ed1f1e9f7a62926ce..2b7cfc0a6efb867259c45d36151395402155a788 100644 (file)
@@ -353,6 +353,12 @@ W: http://www.dgii.com/linux,http://lameter.com/digi
 L:     digilnux@dgii.com
 S:     Maintained
 
+DIRECTORY NOTIFICATION
+P:     Stephen Rothwell
+M:     sfr@linuxcare.com.au
+L:     linux-kernel@vger.kernel.org
+S:     Supported
+
 DISK GEOMETRY AND PARTITION HANDLING
 P:     Andries Brouwer
 M:     aeb@veritas.com
@@ -411,9 +417,9 @@ S:  Maintained
 
 ETHERNET BRIDGE
 P:     Lennert Buytenhek
-M:     buytenh@openrock.net
-L:     bridge@openrock.net
-W:     http://openrock.net/bridge
+M:     buytenh@gnu.org
+L:     bridge@math.leidenuniv.nl
+W:     http://www.math.leidenuniv.nl/~buytenh/bridge
 S:     Maintained
 
 ETHERTEAM 16I DRIVER
index ccd736426afb004d0fd1766055dd32770a114a0f..8b4b7d0af9c4d1d0935f1f6f656f7cd8adde9f78 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -356,9 +356,8 @@ endif
 
 clean: archclean
        rm -f kernel/ksyms.lst include/linux/compile.h
-       find . -name '*.[oas]' -type f -print | grep -v lxdialog/ | xargs rm -f
-       rm -f core `find . -type f -name 'core' -print`
-       rm -f core `find . -type f -name '.*.flags' -print`
+       find . \( -name '*.[oas]' -o -name core -o -name '.*.flags' \) -type f -print \
+               | grep -v lxdialog/ | xargs rm -f
        rm -f vmlinux System.map
        rm -f .tmp*
        rm -f drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c
@@ -392,8 +391,7 @@ mrproper: clean archmrproper
        rm -f .menuconfig.log
        rm -f include/asm
        rm -rf include/config
-       rm -f .depend `find . -type f -name .depend -print`
-       rm -f core `find . -type f -size 0 -print`
+       find . \( -size 0 -o -name .depend \) -type f -print | xargs rm -f
        rm -f .hdepend scripts/mkdep scripts/split-include scripts/docproc
        rm -f $(TOPDIR)/include/linux/modversions.h
        rm -rf $(TOPDIR)/include/linux/modules
index 96da8d33be809ff40350b405ce6e8c74fe43d502..0a2d802a34fc545fc977a96cc55444839fc4ada8 100644 (file)
@@ -63,7 +63,7 @@ CFLAGS += $(shell if $(CC) -march=athlon -S -o /dev/null -xc /dev/null >/dev/nul
 endif
 
 ifdef CONFIG_MCRUSOE
-CFLAGS += -march=i586
+CFLAGS += -march=i686 -malign-functions=0 -malign-jumps=0 -malign-loops=0
 endif
 
 ifdef CONFIG_MWINCHIPC6
index 4e5df46812474b24d35afbaa514fdbaf33bc96de..fc54896f8e272b18175f67faba9098858bd89af3 100644 (file)
@@ -219,39 +219,6 @@ void __init setup_local_APIC (void)
        if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
                BUG();
 
-       value = apic_read(APIC_SPIV);
-       value &= ~APIC_VECTOR_MASK;
-       /*
-        * Enable APIC
-        */
-       value |= (1<<8);
-
-       /*
-        * Some unknown Intel IO/APIC (or APIC) errata is biting us with
-        * certain networking cards. If high frequency interrupts are
-        * happening on a particular IOAPIC pin, plus the IOAPIC routing
-        * entry is masked/unmasked at a high rate as well then sooner or
-        * later IOAPIC line gets 'stuck', no more interrupts are received
-        * from the device. If focus CPU is disabled then the hang goes
-        * away, oh well :-(
-        *
-        * [ This bug can be reproduced easily with a level-triggered
-        *   PCI Ne2000 networking cards and PII/PIII processors, dual
-        *   BX chipset. ]
-        */
-#if 0
-       /* Enable focus processor (bit==0) */
-       value &= ~(1<<9);
-#else
-       /* Disable focus processor (bit==1) */
-       value |= (1<<9);
-#endif
-       /*
-        * Set spurious IRQ vector
-        */
-       value |= SPURIOUS_APIC_VECTOR;
-       apic_write_around(APIC_SPIV, value);
-
        /*
         * Set up LVT0, LVT1:
         *
@@ -323,6 +290,42 @@ void __init setup_local_APIC (void)
         * Must be "all ones" explicitly for 82489DX.
         */
        apic_write_around(APIC_DFR, 0xffffffff);
+
+       /*
+        * Now that we are all set up, enable the APIC
+        */
+       value = apic_read(APIC_SPIV);
+       value &= ~APIC_VECTOR_MASK;
+       /*
+        * Enable APIC
+        */
+       value |= (1<<8);
+
+       /*
+        * Some unknown Intel IO/APIC (or APIC) errata is biting us with
+        * certain networking cards. If high frequency interrupts are
+        * happening on a particular IOAPIC pin, plus the IOAPIC routing
+        * entry is masked/unmasked at a high rate as well then sooner or
+        * later IOAPIC line gets 'stuck', no more interrupts are received
+        * from the device. If focus CPU is disabled then the hang goes
+        * away, oh well :-(
+        *
+        * [ This bug can be reproduced easily with a level-triggered
+        *   PCI Ne2000 networking cards and PII/PIII processors, dual
+        *   BX chipset. ]
+        */
+#if 0
+       /* Enable focus processor (bit==0) */
+       value &= ~(1<<9);
+#else
+       /* Disable focus processor (bit==1) */
+       value |= (1<<9);
+#endif
+       /*
+        * Set spurious IRQ vector
+        */
+       value |= SPURIOUS_APIC_VECTOR;
+       apic_write_around(APIC_SPIV, value);
 }
 
 void __init init_apic_mappings(void)
index ee6966d5f599fd7b5740057e0d6f83bdbe00c8b9..79ab9a5ff8713f7205abef432f7a76adbe432964 100644 (file)
@@ -10,7 +10,7 @@
 
 static int banks;
 
-void mcheck_fault(void)
+void do_machine_check(struct pt_regs * regs, long error_code)
 {
        int recover=1;
        u32 alow, ahigh, high, low;
index 4ae0ed2ee4bb9670a978bbb772fb416b3d1e404b..5e3c910190b0e3aeb5343db3e6e1d23962b0b0fa 100644 (file)
@@ -383,11 +383,6 @@ ENTRY(coprocessor_segment_overrun)
        pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
        jmp error_code
 
-ENTRY(reserved)
-       pushl $0
-       pushl $ SYMBOL_NAME(do_reserved)
-       jmp error_code
-
 ENTRY(double_fault)
        pushl $ SYMBOL_NAME(do_double_fault)
        jmp error_code
@@ -418,7 +413,7 @@ ENTRY(page_fault)
 
 ENTRY(machine_check)
        pushl $0
-       pushl $ SYMBOL_NAME(mcheck_fault)
+       pushl $ SYMBOL_NAME(do_machine_check)
        jmp error_code
 
 ENTRY(spurious_interrupt_bug)
index 7ac7fdb366f7ddfa32335207a796b71ce4ce47af..b22adbd47396677bc279aa2f1edb5b3c1ce26e6d 100644 (file)
@@ -971,6 +971,16 @@ static int __init amd_model(struct cpuinfo_x86 *c)
        display_cacheinfo(c);
        return r;
 }
+
+static void __init intel_model(struct cpuinfo_x86 *c)
+{
+       unsigned int *v = (unsigned int *) c->x86_model_id;
+       cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+       cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+       cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+       c->x86_model_id[48] = 0;
+       printk("CPU: %s\n", c->x86_model_id);
+}
                        
 
 /*
@@ -1548,7 +1558,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
 
                        /* Pentium IV. */
                        if (c->x86 == 15) {
-                               get_model_name(c);
+                               intel_model(c);
                                return;
                        }
 
index ae87ded927f5f816f634e297224046c5f77d749d..aa2deb8ae250665c4fa6292a296faece4ebe972f 100644 (file)
@@ -92,7 +92,6 @@ asmlinkage void general_protection(void);
 asmlinkage void page_fault(void);
 asmlinkage void coprocessor_error(void);
 asmlinkage void simd_coprocessor_error(void);
-asmlinkage void reserved(void);
 asmlinkage void alignment_check(void);
 asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
@@ -312,7 +311,6 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
-DO_ERROR(18, SIGSEGV, "reserved", reserved)
 
 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 {
@@ -396,9 +394,20 @@ static int __init setup_nmi_watchdog(char *str)
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-extern spinlock_t console_lock;
+extern spinlock_t console_lock, timerlist_lock;
 static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
 
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out (timerlist_lock is aquired through the
+ * console unblank code)
+ */
+void bust_spinlocks(void)
+{
+       spin_lock_init(&console_lock);
+       spin_lock_init(&timerlist_lock);
+}
+
 inline void nmi_watchdog_tick(struct pt_regs * regs)
 {
        /*
@@ -439,8 +448,7 @@ inline void nmi_watchdog_tick(struct pt_regs * regs)
                         * We are in trouble anyway, lets at least try
                         * to get a message out.
                         */
-                       spin_trylock(&console_lock);
-                       spin_unlock(&console_lock);
+                       bust_spinlocks();
                        printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
                        show_registers(regs);
                        printk("console shuts up ...\n");
index 0314041f93f665a1f41a1b4b5a085cef563e80e1..4aca07e72f8969356080b3742cb269f8c2d0edf6 100644 (file)
@@ -16,6 +16,9 @@
  *     Add *user handling. Checksums are not a win with MMX on any CPU
  *     tested so far for any MMX solution figured.
  *
+ *     22/09/2000 - Arjan van de Ven 
+ *             Improved for non-egineering-sample Athlons 
+ *
  */
  
 void *_mmx_memcpy(void *to, const void *from, size_t len)
@@ -104,28 +107,26 @@ static void fast_clear_page(void *page)
                "  pxor %%mm0, %%mm0\n" : :
        );
 
-       for(i=0;i<4096/128;i++)
+       for(i=0;i<4096/64;i++)
        {
                __asm__ __volatile__ (
-               "  movq %%mm0, (%0)\n"
-               "  movq %%mm0, 8(%0)\n"
-               "  movq %%mm0, 16(%0)\n"
-               "  movq %%mm0, 24(%0)\n"
-               "  movq %%mm0, 32(%0)\n"
-               "  movq %%mm0, 40(%0)\n"
-               "  movq %%mm0, 48(%0)\n"
-               "  movq %%mm0, 56(%0)\n"
-               "  movq %%mm0, 64(%0)\n"
-               "  movq %%mm0, 72(%0)\n"
-               "  movq %%mm0, 80(%0)\n"
-               "  movq %%mm0, 88(%0)\n"
-               "  movq %%mm0, 96(%0)\n"
-               "  movq %%mm0, 104(%0)\n"
-               "  movq %%mm0, 112(%0)\n"
-               "  movq %%mm0, 120(%0)\n"
+               "  movntq %%mm0, (%0)\n"
+               "  movntq %%mm0, 8(%0)\n"
+               "  movntq %%mm0, 16(%0)\n"
+               "  movntq %%mm0, 24(%0)\n"
+               "  movntq %%mm0, 32(%0)\n"
+               "  movntq %%mm0, 40(%0)\n"
+               "  movntq %%mm0, 48(%0)\n"
+               "  movntq %%mm0, 56(%0)\n"
                : : "r" (page) : "memory");
-               page+=128;
+               page+=64;
        }
+       /* since movntq is weakly-ordered, a "sfence" is needed to become
+        * ordered again.
+        */
+       __asm__ __volatile__ (
+               "  sfence \n" : :
+       );
        stts();
 }
 
@@ -140,6 +141,9 @@ static void fast_copy_page(void *to, void *from)
                current->flags &= ~PF_USEDFPU;
        }
 
+       /* maybe the prefetch stuff can go before the expensive fnsave...
+        * but that is for later. -AV
+        */
        __asm__ __volatile__ (
                "1: prefetch (%0)\n"
                "   prefetch 64(%0)\n"
@@ -162,21 +166,21 @@ static void fast_copy_page(void *to, void *from)
                __asm__ __volatile__ (
                "1: prefetch 320(%0)\n"
                "2: movq (%0), %%mm0\n"
+               "   movntq %%mm0, (%1)\n"
                "   movq 8(%0), %%mm1\n"
+               "   movntq %%mm1, 8(%1)\n"
                "   movq 16(%0), %%mm2\n"
+               "   movntq %%mm2, 16(%1)\n"
                "   movq 24(%0), %%mm3\n"
-               "   movq %%mm0, (%1)\n"
-               "   movq %%mm1, 8(%1)\n"
-               "   movq %%mm2, 16(%1)\n"
-               "   movq %%mm3, 24(%1)\n"
-               "   movq 32(%0), %%mm0\n"
-               "   movq 40(%0), %%mm1\n"
-               "   movq 48(%0), %%mm2\n"
-               "   movq 56(%0), %%mm3\n"
-               "   movq %%mm0, 32(%1)\n"
-               "   movq %%mm1, 40(%1)\n"
-               "   movq %%mm2, 48(%1)\n"
-               "   movq %%mm3, 56(%1)\n"
+               "   movntq %%mm3, 24(%1)\n"
+               "   movq 32(%0), %%mm4\n"
+               "   movntq %%mm4, 32(%1)\n"
+               "   movq 40(%0), %%mm5\n"
+               "   movntq %%mm5, 40(%1)\n"
+               "   movq 48(%0), %%mm6\n"
+               "   movntq %%mm6, 48(%1)\n"
+               "   movq 56(%0), %%mm7\n"
+               "   movntq %%mm7, 56(%1)\n"
                ".section .fixup, \"ax\"\n"
                "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
                "   jmp 2b\n"
@@ -189,6 +193,12 @@ static void fast_copy_page(void *to, void *from)
                from+=64;
                to+=64;
        }
+       /* since movntq is weakly-ordered, a "sfence" is needed to become
+        * ordered again.
+        */
+       __asm__ __volatile__ (
+               "  sfence \n" : :
+       );
        stts();
 }
 
index 946d1f40ae1aa75d265a2cfbc77a32e64cdeb566..96b67925fcab351d01ec7843888a758ff1d79a6e 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/hardirq.h>
 
 extern void die(const char *,struct pt_regs *,long);
+extern void bust_spinlocks(void);
 
 /*
  * Ugly, ugly, but the goto's result in better assembly..
@@ -251,6 +252,8 @@ no_context:
  * terminate things with extreme prejudice.
  */
 
+       bust_spinlocks();
+
        if (address < PAGE_SIZE)
                printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
        else
index 8d6bc8c45e9bdd449349b59813b5bfb2556dcce3..810ef92021d9a1216a6c97b0dc2ea3cf16f3a777 100644 (file)
@@ -241,7 +241,7 @@ int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
                                        return -ENOMEM;
                                new = 1;
                        }
-                       kaddr = (char *)kmap(page);
+                       kaddr = kmap(page);
 
                        if (new && offset)
                                memset(kaddr, 0, offset);
index cc8d2290af33f415be5f2fa0734c0edb2d717218..2c17e7bcbadbe3ac4611e1c6560efe629be94133 100644 (file)
@@ -630,7 +630,7 @@ mmu_context_overflow(void)
 
 void flush_page_to_ram(struct page *page)
 {
-       unsigned long vaddr = kmap(page);
+       unsigned long vaddr = (unsigned long) kmap(page);
        __flush_page_to_ram(vaddr);
        kunmap(page);
 }
index f61be993225dcf94cd5d4ca7c8440925f32e52bc..00c465b10fda246282263d8790b6608e538b6544 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.11 2000/10/10 01:07:38 davem Exp $
+/* $Id: ebus.c,v 1.15 2000/11/08 05:06:21 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
 
 struct linux_ebus *ebus_chain = 0;
 
-#ifdef CONFIG_SUN_OPENPROMIO
-extern int openprom_init(void);
-#endif
 #ifdef CONFIG_SUN_AUXIO
 extern void auxio_probe(void);
 #endif
-#ifdef CONFIG_OBP_FLASH
-extern int flash_init(void);
-#endif
-#ifdef CONFIG_ENVCTRL
-extern int envctrl_init(void);
-#endif
 
 /* We are together with pcic.c under CONFIG_PCI. */
 extern unsigned int pcic_pin_to_irq(unsigned int, char *name);
@@ -367,20 +358,7 @@ void __init ebus_init(void)
                ++num_ebus;
        }
 
-#ifdef CONFIG_SUN_OPENPROMIO
-       openprom_init();
-#endif
-
-#ifdef CONFIG_SUN_BPP
-       bpp_init();
-#endif
 #ifdef CONFIG_SUN_AUXIO
        auxio_probe();
 #endif
-#ifdef CONFIG_ENVCTRL
-       envctrl_init();
-#endif
-#ifdef CONFIG_OBP_FLASH
-       flash_init();
-#endif
 }
index ba86e3d64bfcbfe7d434a31ae54a46ef7f5c96d1..e7b4e96de8a5bd27ea4075d44f9181b95487083c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.18 2000/09/25 06:09:12 anton Exp $
+/* $Id: pcic.c,v 1.19 2000/11/08 04:49:17 davem Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
index 9cbbb1c9c9c900936114545109cfb5e5d09e0e0d..a8f5fb9c202b7c812413828187d39dd8d75659e8 100644 (file)
@@ -579,8 +579,7 @@ void si_meminfo(struct sysinfo *val)
 
 void flush_page_to_ram(struct page *page)
 {
-       unsigned long vaddr;
-       vaddr = kmap(page);
-       __flush_page_to_ram((unsigned long)page_address(page));
+       unsigned long vaddr = (unsigned long) kmap(page);
+       __flush_page_to_ram(vaddr);
        kunmap(page);
 }
index a91809d03bc542e80077648a26bf581b05ded51b..b32199c13b74cd3788050831a3b2c41d86db113b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.223 2000/10/16 14:32:49 anton Exp $
+/* $Id: srmmu.c,v 1.224 2000/11/09 22:40:05 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -1163,7 +1163,7 @@ extern int linux_num_cpus;
 
 void (*poke_srmmu)(void) __initdata = NULL;
 
-extern unsigned long bootmem_init(void);
+extern void bootmem_init(void);
 extern void sun_serial_setup(void);
 
 void __init srmmu_paging_init(void)
index a416ecf19f56982164e2e52f07d2ff287c49ec6b..edba89672894e517d627fa0543fdb091c948d0fc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.200 2000/10/16 14:32:49 anton Exp $
+/* $Id: sun4c.c,v 1.201 2000/11/09 22:39:36 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -2509,7 +2509,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
 
 extern void sparc_context_init(int);
 extern unsigned long end;
-extern unsigned long bootmem_init(void);
+extern void bootmem_init(void);
 extern unsigned long last_valid_pfn;
 extern void sun_serial_setup(void);
 
@@ -2524,7 +2524,8 @@ void __init sun4c_paging_init(void)
        kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4);
        kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
 
-       last_valid_pfn = end_pfn = bootmem_init();
+       bootmem_init();
+       end_pfn = last_valid_pfn;
 
        /* This does not logically belong here, but we need to
         * call it at the moment we are able to use the bootmem
index bba19d4c5967add80a4e707095c25d0f3d08d42f..e449e26fa8a77016d2296c984d693d51838e64e9 100644 (file)
@@ -31,6 +31,9 @@ SECTIONS
   __start___ksymtab = .;
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
+  __start___kallsyms = .;      /* All kernel symbols */
+  __kallsyms : { *(__kallsyms) }
+  __stop___kallsyms = .;
 
   . = ALIGN(4096);
   __init_begin = .;
index 5872046b15ad848846cd5a41d3f8c67a75d3fc81..e175fac27543e82ea805b5335d9954c04b02d6fc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.48 2000/08/02 06:22:35 davem Exp $
+/* $Id: ebus.c,v 1.53 2000/11/08 05:08:23 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
 
 struct linux_ebus *ebus_chain = 0;
 
-#ifdef CONFIG_SUN_OPENPROMIO
-extern int openprom_init(void);
-#endif
 #ifdef CONFIG_SUN_AUXIO
 extern void auxio_probe(void);
 #endif
-#ifdef CONFIG_OBP_FLASH
-extern int flash_init(void);
-#endif
-#ifdef CONFIG_ENVCTRL
-extern int envctrl_init(void);
-#endif
-#ifdef CONFIG_DISPLAY7SEG
-extern int d7s_init(void);
-#endif
 
 static inline void *ebus_alloc(size_t size)
 {
@@ -372,23 +360,8 @@ void __init ebus_init(void)
                ++num_ebus;
        }
 
-#ifdef CONFIG_SUN_OPENPROMIO
-       openprom_init();
-#endif
-#ifdef CONFIG_SUN_BPP
-       bpp_init();
-#endif
 #ifdef CONFIG_SUN_AUXIO
        auxio_probe();
-#endif
-#ifdef CONFIG_ENVCTRL
-       envctrl_init();
-#endif
-#ifdef CONFIG_OBP_FLASH
-       flash_init();
-#endif
-#ifdef CONFIG_DISPLAY7SEG
-       d7s_init();
 #endif
        clock_probe();
        power_init();
index 9f7cd59e90571b29dfdeeda547e663d719f0b460..10e7ccc9cbcb35af4d9dee01e76175faa028d546 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.99 2000/10/17 16:20:33 davem Exp $
+/* $Id: ioctl32.c,v 1.102 2000/11/08 05:13:30 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -73,6 +73,7 @@
 #include <asm/audioio.h>
 #include <asm/ethtool.h>
 #include <asm/display7seg.h>
+#include <asm/module.h>
 #include <linux/soundcard.h>
 
 #include <linux/atm.h>
@@ -3230,6 +3231,7 @@ COMPATIBLE_IOCTL(ENVCTRL_RD_SCSI_TEMPERATURE)
 COMPATIBLE_IOCTL(ENVCTRL_RD_ETHERNET_TEMPERATURE)
 COMPATIBLE_IOCTL(ENVCTRL_RD_MTHRBD_TEMPERATURE)
 COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_VOLTAGE)
+COMPATIBLE_IOCTL(ENVCTRL_RD_GLOBALADDRESS)
 /* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */
 COMPATIBLE_IOCTL(D7SIOCWR)
 COMPATIBLE_IOCTL(D7SIOCTM)
@@ -3467,6 +3469,14 @@ COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN)
 COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1)
 COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2)
 COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3)
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR))
 COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE)
 /* SOUND_MIXER_READ_ENHANCE,  same value as READ_MUTE */
 /* SOUND_MIXER_READ_LOUD,  same value as READ_MUTE */
@@ -3492,6 +3502,14 @@ COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN)
 COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1)
 COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2)
 COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3)
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR))
 COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE)
 /* SOUND_MIXER_WRITE_ENHANCE,  same value as WRITE_MUTE */
 /* SOUND_MIXER_WRITE_LOUD,  same value as WRITE_MUTE */
index 626615da001573ddd607fdcb1eabeccd4ad7e93b..1abef824f63fce1effb4b249f304ce600ec64175 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.18 2000/10/03 11:31:42 anton Exp $
+/* $Id: pci.c,v 1.19 2000/11/08 04:49:17 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
index 1f3386d533bb4ac19f058057d05424ccf0c571c0..4534ad59b14df5b9f73829bdfded3fcb99716e80 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.112 2000/09/06 00:45:01 davem Exp $
+/*  $Id: process.c,v 1.113 2000/11/08 08:14:58 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -647,14 +647,21 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
        long retval;
 
-       __asm__ __volatile("mov %1, %%g1\n\t"
+       /* If the parent runs before fn(arg) is called by the child,
+        * the input registers of this function can be clobbered.
+        * So we stash 'fn' and 'arg' into global registers which
+        * will not be modified by the parent.
+        */
+       __asm__ __volatile("mov %4, %%g2\n\t"      /* Save FN into global */
+                          "mov %5, %%g3\n\t"      /* Save ARG into global */
+                          "mov %1, %%g1\n\t"      /* Clone syscall nr. */
                           "mov %2, %%o0\n\t"      /* Clone flags. */
                           "mov 0, %%o1\n\t"       /* usp arg == 0 */
                           "t 0x6d\n\t"            /* Linux/Sparc clone(). */
                           "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
                           " mov %%o0, %0\n\t"
-                          "jmpl %4, %%o7\n\t"     /* Call the function. */
-                          " mov %5, %%o0\n\t"     /* Set arg in delay. */
+                          "jmpl %%g2, %%o7\n\t"   /* Call the function. */
+                          " mov %%g3, %%o0\n\t"   /* Set arg in delay. */
                           "mov %3, %%g1\n\t"
                           "t 0x6d\n\t"            /* Linux/Sparc exit(). */
                           /* Notreached by child. */
@@ -662,7 +669,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
                           "=r" (retval) :
                           "i" (__NR_clone), "r" (flags | CLONE_VM),
                           "i" (__NR_exit),  "r" (fn), "r" (arg) :
-                          "g1", "o0", "o1", "memory", "cc");
+                          "g1", "g2", "g3", "o0", "o1", "memory", "cc");
        return retval;
 }
 
index 6e7f5930972c9d89007dc6fbf193b154da5e361f..20d8a1a43a7510caf328f75e2bb72f74a2b58356 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.95 2000/10/30 21:01:40 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.96 2000/11/06 06:59:03 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -87,7 +87,6 @@ extern long sparc32_open(const char * filename, int flags, int mode);
 extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
 extern int unregister_ioctl32_conversion(unsigned int cmd);
 extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space);
-extern void __flush_dcache_page(void *addr);
                 
 extern int __ashrdi3(int, int);
 
index 24c8cd5936c2bf4e336f5448ef879ca71c742afa..71676e05ddfaa92c54c8d9545ff8920927b28b2a 100644 (file)
@@ -2952,7 +2952,7 @@ static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
                                        return -ENOMEM;
                                new = 1;
                        }
-                       kaddr = (char *)kmap(page);
+                       kaddr = kmap(page);
 
                        if (new && offset)
                                memset(kaddr, 0, offset);
@@ -2967,7 +2967,7 @@ static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
                        err = copy_from_user(kaddr + offset, (char *)A(str),
                                             bytes_to_copy);
                        flush_page_to_ram(page);
-                       kunmap((unsigned long)kaddr);
+                       kunmap(page);
 
                        if (err)
                                return -EFAULT;
index fa057936a0f4b7898d41d36b4d97a40b79913724..77531321d387e4c9350cc2840874cb5f52be3458 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.23 2000/07/10 20:57:34 davem Exp $
+# $Id: Makefile,v 1.24 2000/11/01 07:33:47 davem Exp $
 # Makefile for Sparc64 library files..
 #
 
@@ -8,7 +8,8 @@ OBJS  = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
        memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
        VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
        VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
-       dec_and_lock.o
+       dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \
+       U3copy_in_user.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
diff --git a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S
new file mode 100644 (file)
index 0000000..b1003e6
--- /dev/null
@@ -0,0 +1,500 @@
+/* $Id: U3copy_from_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $
+ * U3memcpy.S: UltraSparc-III optimized copy from userspace.
+ *
+ * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#undef SMALL_COPY_USES_FPU
+#define EXNV(x,y,a,b)                  \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       ba,pt %xcc, U3cfu_fixup;        \
+        a, b, %o1;                     \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EX(x,y,a,b)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       ba,pt %xcc, U3cfu_fixup;        \
+        a, b, %o1;                     \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EX2(x,y)                       \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o1;       \
+       add %o1, %o4, %o1;              \
+       ba,pt %xcc, U3cfu_fixup;        \
+        add %o1, 0x1c0, %o1;           \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EX3(x,y)                       \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o1;       \
+       sll %g3, 6, %g3;                \
+       add %o1, 0x80, %o1;             \
+       ba,pt %xcc, U3cfu_fixup;        \
+        add %o1, %g3, %o1;             \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EX4(x,y)                       \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o1;       \
+       add %o1, 0x40, %o1;             \
+       ba,pt %xcc, U3cfu_fixup;        \
+        add %o1, %g3, %o1;             \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#else
+#define ASI_BLK_P 0xf0
+#define FPRS_FEF  0x04
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#define SMALL_COPY_USES_FPU
+#define EXNV(x,y,a,b)  x,y;
+#define EX(x,y,a,b)    x,y;
+#define EX2(x,y)       x,y;
+#define EX3(x,y)       x,y;
+#define EX4(x,y)       x,y;
+#endif
+
+       /* Special/non-trivial issues of this code:
+        *
+        * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
+        * 2) Only low 32 FPU registers are used so that only the
+        *    lower half of the FPU register set is dirtied by this
+        *    code.  This is especially important in the kernel.
+        * 3) This code never prefetches cachelines past the end
+        *    of the source buffer.
+        */
+
+       .text
+       .align  32
+
+       /* The cheetah's flexible spine, oversized liver, enlarged heart,
+        * slender muscular body, and claws make it the swiftest hunter
+        * in Africa and the fastest animal on land.  Can reach speeds
+        * of up to 2.4GB per second.
+        */
+
+       .globl          U3copy_from_user
+U3copy_from_user: /* %o0=dst, %o1=src, %o2=len */
+#ifndef __KERNEL__
+       /* Save away original 'dst' for memcpy return value. */
+       mov             %o0, %g3                        ! A0    Group
+#endif
+       /* Anything to copy at all? */
+       cmp             %o2, 0                          ! A1
+       ble,pn          %icc, U3copy_from_user_short_ret! BR
+
+       /* Extremely small copy? */
+        cmp            %o2, 31                         ! A0    Group
+       ble,pn          %icc, U3copy_from_user_short    ! BR
+
+       /* Large enough to use unrolled prefetch loops? */
+        cmp            %o2, 0x100                      ! A1
+       bge,a,pt        %icc, U3copy_from_user_enter    ! BR    Group
+        andcc          %o0, 0x3f, %g2                  ! A0
+
+       ba,pt           %xcc, U3copy_from_user_toosmall ! BR    Group
+        andcc          %o0, 0x7, %g2                   ! A0
+
+       .align          32
+U3copy_from_user_short:
+       /* Copy %o2 bytes from src to dst, one byte at a time. */
+       EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS    Group
+       add             %o1, 0x1, %o1                   ! A0
+       add             %o0, 0x1, %o0                   ! A1
+       subcc           %o2, 1, %o2                     ! A0    Group
+
+       bg,pt           %icc, U3copy_from_user_short    ! BR
+        stb            %o3, [%o0 + -1]                 ! MS    Group (1-cycle stall)
+
+U3copy_from_user_short_ret:
+#ifdef __KERNEL__
+       retl                                            ! BR    Group (0-4 cycle stall)
+        clr            %o0                             ! A0
+#else
+       retl                                            ! BR    Group (0-4 cycle stall)
+        mov            %g3, %o0                        ! A0
+#endif
+
+       /* Here len >= (6 * 64) and condition codes reflect execution
+        * of "andcc %o0, 0x7, %g2", done by caller.
+        */
+       .align          64
+U3copy_from_user_enter:
+       /* Is 'dst' already aligned on an 64-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR
+
+       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x40, %g2                  ! A0    Group
+       sub             %g0, %g2, %g2                   ! A0    Group
+       sub             %o2, %g2, %o2                   ! A0    Group
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS    (Group)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        stb            %o3, [%o0 + -1]                 ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+       and             %o1, 0x7, %g1                   ! A1
+       ba,pt           %xcc, U3copy_from_user_begin            ! BR
+        alignaddr      %o1, %g0, %o1                   ! MS          (Break-after)
+
+       .align          64
+U3copy_from_user_begin:
+       prefetcha       [%o1 + 0x000] %asi, #one_read   ! MS    Group1
+       prefetcha       [%o1 + 0x040] %asi, #one_read   ! MS    Group2
+       andn            %o2, (0x40 - 1), %o4            ! A0
+       prefetcha       [%o1 + 0x080] %asi, #one_read   ! MS    Group3
+       cmp             %o4, 0x140                      ! A0
+       prefetcha       [%o1 + 0x0c0] %asi, #one_read   ! MS    Group4
+       EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)  ! MS    Group5 (%f0 results at G8)
+       bge,a,pt        %icc, 1f                        ! BR
+
+       prefetcha       [%o1 + 0x100] %asi, #one_read   ! MS    Group6
+1:     EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)  ! AX           (%f2 results at G9)
+       cmp             %o4, 0x180                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+        prefetcha      [%o1 + 0x140] %asi, #one_read   ! MS    Group7
+1:     EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)  ! AX           (%f4 results at G10)
+       cmp             %o4, 0x1c0                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetcha      [%o1 + 0x180] %asi, #one_read   ! MS    Group8
+1:     faligndata      %f0, %f2, %f16                  ! FGA   Group9 (%f16 at G12)
+       EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)  ! AX           (%f6 results at G12)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group10 (%f18 results at G13)
+       EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)  ! MS            (%f8 results at G13)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group12 (1-cycle stall,%f20 at G15)
+       EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS            (%f10 results at G15)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group13 (%f22 results at G16)
+
+       EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS            (%f12 results at G16)
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15 (1-cycle stall,%f24 at G18)
+       EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS            (%f14 results at G18)
+       faligndata      %f10, %f12, %f26                ! FGA   Group16 (%f26 results at G19)
+       EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)  ! MS            (%f0 results at G19)
+
+       /* We only use the first loop if len > (7 * 64). */
+       subcc           %o4, 0x1c0, %o4                 ! A0    Group17
+       bg,pt           %icc, U3copy_from_user_loop1    ! BR
+        add            %o1, 0x40, %o1                  ! A1
+
+       add             %o4, 0x140, %o4                 ! A0    Group18
+       ba,pt           %xcc, U3copy_from_user_loop2    ! BR
+        srl            %o4, 6, %o3                     ! A0    Group19
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       nop
+       nop
+
+       /* This loop performs the copy and queues new prefetches.
+        * We drop into the second loop when len <= (5 * 64).  Note
+        * that this (5 * 64) factor has been subtracted from len
+        * already.
+        */
+U3copy_from_user_loop1:
+       EX2(ldda [%o1 + 0x008] %asi, %f2)               ! MS    Group2  (%f2 results at G5)
+       faligndata      %f12, %f14, %f28                ! FGA           (%f28 results at G5)
+       EX2(ldda [%o1 + 0x010] %asi, %f4)               ! MS    Group3  (%f4 results at G6)
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall, %f30 at G7)
+       stda            %f16, [%o0] ASI_BLK_P           ! MS
+       EX2(ldda [%o1 + 0x018] %asi, %f6)               ! AX            (%f6 results at G7)
+
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+       EX2(ldda [%o1 + 0x020] %asi, %f8)               ! MS            (%f8 results at G15)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13 (%f18 results at G16)
+       EX2(ldda [%o1 + 0x028] %asi, %f10)              ! MS            (%f10 results at G16)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14 (%f20 results at G17)
+       EX2(ldda [%o1 + 0x030] %asi, %f12)              ! MS            (%f12 results at G17)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15 (%f22 results at G18)
+       EX2(ldda [%o1 + 0x038] %asi, %f14)              ! MS            (%f14 results at G18)
+
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16 (%f24 results at G19)
+       EX2(ldda [%o1 + 0x040] %asi, %f0)               ! AX            (%f0 results at G19)
+       prefetcha       [%o1 + 0x180] %asi, #one_read   ! MS
+       faligndata      %f10, %f12, %f26                ! FGA   Group17 (%f26 results at G20)
+       subcc           %o4, 0x40, %o4                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3copy_from_user_loop1    ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+U3copy_from_user_loop2_enter:
+       mov             5, %o3                          ! A1
+
+       /* This loop performs on the copy, no new prefetches are
+        * queued.  We do things this way so that we do not perform
+        * any spurious prefetches past the end of the src buffer.
+        */
+U3copy_from_user_loop2:
+       EX3(ldda [%o1 + 0x008] %asi, %f2)               ! MS
+       faligndata      %f12, %f14, %f28                ! FGA   Group2
+       EX3(ldda [%o1 + 0x010] %asi, %f4)               ! MS
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall)
+       stda            %f16, [%o0] ASI_BLK_P           ! MS
+       EX3(ldda [%o1 + 0x018] %asi, %f6)               ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+
+       EX3(ldda [%o1 + 0x020] %asi, %f8)               ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13
+       EX3(ldda [%o1 + 0x028] %asi, %f10)              ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14
+       EX3(ldda [%o1 + 0x030] %asi, %f12)              ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15
+       EX3(ldda [%o1 + 0x038] %asi, %f14)              ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16
+
+       EX3(ldda [%o1 + 0x040] %asi, %f0)               ! AX
+       faligndata      %f10, %f12, %f26                ! FGA   Group17
+       subcc           %o3, 0x01, %o3                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3copy_from_user_loop2    ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+       /* Finally we copy the last full 64-byte block. */
+U3copy_from_user_loopfini:
+       EX3(ldda [%o1 + 0x008] %asi, %f2)               ! MS
+       faligndata      %f12, %f14, %f28                ! FGA
+       EX3(ldda [%o1 + 0x010] %asi, %f4)               ! MS    Group19
+       faligndata      %f14, %f0, %f30                 ! FGA
+       stda            %f16, [%o0] ASI_BLK_P           ! MS    Group20
+       EX3(ldda [%o1 + 0x018] %asi, %f6)               ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group11 (7-cycle stall)
+       EX3(ldda [%o1 + 0x020] %asi, %f8)               ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group12
+       EX3(ldda [%o1 + 0x028] %asi, %f10)              ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group13
+       EX3(ldda [%o1 + 0x030] %asi, %f12)              ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group14
+       EX3(ldda [%o1 + 0x038] %asi, %f14)              ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15
+       cmp             %g1, 0                          ! A0
+       be,pt           %icc, 1f                        ! BR
+        add            %o0, 0x40, %o0                  ! A1
+       EX4(ldda [%o1 + 0x040] %asi, %f0)               ! MS
+1:     faligndata      %f10, %f12, %f26                ! FGA   Group16
+       faligndata      %f12, %f14, %f28                ! FGA   Group17
+       faligndata      %f14, %f0, %f30                 ! FGA   Group18
+       stda            %f16, [%o0] ASI_BLK_P           ! MS
+       add             %o0, 0x40, %o0                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       membar          #Sync                           ! MS    Group26 (7-cycle stall)
+
+       /* Now we copy the (len modulo 64) bytes at the end.
+        * Note how we borrow the %f0 loaded above.
+        *
+        * Also notice how this code is careful not to perform a
+        * load past the end of the src buffer just like similar
+        * code found in U3copy_from_user_toosmall processing.
+        */
+U3copy_from_user_loopend:
+       and             %o2, 0x3f, %o2                  ! A0    Group
+       andcc           %o2, 0x38, %g2                  ! A0    Group
+       be,pn           %icc, U3copy_from_user_endcruft ! BR
+        subcc          %g2, 0x8, %g2                   ! A1
+       be,pn           %icc, U3copy_from_user_endcruft ! BR    Group
+        cmp            %g1, 0                          ! A0
+
+       be,a,pt         %icc, 1f                        ! BR    Group
+        EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)  ! MS
+
+1:     EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)   ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f0, %f2, %f8                   ! FGA   Group
+       std             %f8, [%o0 + 0x00]               ! MS    (XXX does it stall here? XXX)
+       be,pn           %icc, U3copy_from_user_endcruft ! BR
+        add            %o0, 0x8, %o0                   ! A0
+       EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)   ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA
+       std             %f8, [%o0 + 0x00]               ! MS    (XXX does it stall here? XXX)
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A0    Group
+
+       /* If anything is left, we copy it one byte at a time.
+        * Note that %g1 is (src & 0x3) saved above before the
+        * alignaddr was performed.
+        */
+U3copy_from_user_endcruft:
+       cmp             %o2, 0
+       add             %o1, %g1, %o1
+       VISExitHalf
+       be,pn           %icc, U3copy_from_user_short_ret
+        nop
+       ba,a,pt         %xcc, U3copy_from_user_short
+
+       /* If we get here, then 32 <= len < (6 * 64) */
+U3copy_from_user_toosmall:
+
+#ifdef SMALL_COPY_USES_FPU
+
+       /* Is 'dst' already aligned on an 8-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR    Group
+
+       /* Compute abs((dst & 7) - 8) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x8, %g2                   ! A0
+       sub             %g0, %g2, %g2                   ! A0    Group (reg-dep)
+       sub             %o2, %g2, %o2                   ! A0    Group (reg-dep)
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS    (Group) (%o3 in 3 cycles)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        stb            %o3, [%o0 + -1]                 ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+
+       /* Compute (len - (len % 8)) into %g2.  This is guarenteed
+        * to be nonzero.
+        */
+       andn            %o2, 0x7, %g2                   ! A0    Group
+
+       /* You may read this and believe that it allows reading
+        * one 8-byte longword past the end of src.  It actually
+        * does not, as %g2 is subtracted as loads are done from
+        * src, so we always stop before running off the end.
+        * Also, we are guarenteed to have at least 0x10 bytes
+        * to move here.
+        */
+       sub             %g2, 0x8, %g2                   ! A0    Group (reg-dep)
+       alignaddr       %o1, %g0, %g1                   ! MS          (Break-after)
+       EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)   ! MS    Group (1-cycle stall)
+       add             %g1, 0x8, %g1                   ! A0
+
+1:     EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0)   ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+
+       faligndata      %f0, %f2, %f8                   ! FGA   Group (1-cycle stall)
+       std             %f8, [%o0 + 0x00]               ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+       be,pn           %icc, 2f                        ! BR
+
+        add            %o0, 0x8, %o0                   ! A1
+       EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)   ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA   Group (1-cycle stall)
+       std             %f8, [%o0 + 0x00]               ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A1
+
+       /* Nothing left to copy? */
+2:     cmp             %o2, 0                          ! A0    Group
+       VISExitHalf                                     ! A0+MS
+       be,pn           %icc, U3copy_from_user_short_ret! BR    Group
+        nop                                            ! A0
+       ba,a,pt         %xcc, U3copy_from_user_short    ! BR    Group
+
+#else /* !(SMALL_COPY_USES_FPU) */
+
+       xor             %o1, %o0, %g2
+       andcc           %g2, 0x7, %g0
+       bne,pn          %icc, U3copy_from_user_short
+        andcc          %o1, 0x7, %g2
+
+       be,pt           %xcc, 2f
+        sub            %g2, 0x8, %g2
+       sub             %g0, %g2, %g2
+       sub             %o2, %g2, %o2
+
+1:     EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
+       add             %o1, 0x1, %o1
+       add             %o0, 0x1, %o0
+       subcc           %g2, 0x1, %g2
+       bg,pt           %icc, 1b
+        stb            %o3, [%o0 + -1]
+
+2:     andn            %o2, 0x7, %g2
+       sub             %o2, %g2, %o2
+
+3:     EXNV(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2)
+       add             %o1, 0x8, %o1
+       add             %o0, 0x8, %o0
+       subcc           %g2, 0x8, %g2
+       bg,pt           %icc, 3b
+        stx            %o3, [%o0 + -8]
+
+       cmp             %o2, 0
+       bne,pn          %icc, U3copy_from_user_short
+        nop
+       ba,a,pt         %xcc, U3copy_from_user_short_ret
+
+#endif /* !(SMALL_COPY_USES_FPU) */
+
+#ifdef __KERNEL__
+       .globl          U3cfu_fixup
+U3cfu_fixup:
+       /* Since this is copy_from_user(), zero out the rest of the
+        * kernel buffer.
+        */
+       cmp             %o1, 0
+       ble,pn          %icc, 2f
+        mov            %o1, %g2
+
+1:     subcc           %g2, 1, %g2
+       stb             %g0, [%o0]
+       bne,pt          %icc, 1b
+        add            %o0, 1, %o0
+
+2:     retl
+        mov            %o1, %o0
+#endif
diff --git a/arch/sparc64/lib/U3copy_in_user.S b/arch/sparc64/lib/U3copy_in_user.S
new file mode 100644 (file)
index 0000000..0fc169b
--- /dev/null
@@ -0,0 +1,531 @@
+/* $Id: U3copy_in_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $
+ * U3memcpy.S: UltraSparc-III optimized copy within userspace.
+ *
+ * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#undef SMALL_COPY_USES_FPU
+#define EXNV(x,y,a,b)  \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    retl;                           \
+        a, b, %o0;                     \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXNV2(x,y,a,b) \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    a, b, %o0;                      \
+       retl;                           \
+        add %o0, 1, %o0;               \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXNV3(x,y,a,b) \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    a, b, %o0;                      \
+       retl;                           \
+        add %o0, 8, %o0;               \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EX(x,y,a,b)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       retl;                           \
+        a, b, %o0;                     \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK1(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       add %o4, 0x1c0, %o1;            \
+       and %o2, (0x40 - 1), %o2;       \
+       retl;                           \
+        add %o1, %o2, %o0;             \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK2(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       sll %o3, 6, %o3;                \
+       and %o2, (0x40 - 1), %o2;       \
+       add %o3, 0x80, %o1;             \
+       retl;                           \
+        add %o1, %o2, %o0;             \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK3(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o2;       \
+       retl;                           \
+        add %o2, 0x80, %o0;            \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK4(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o2;       \
+       retl;                           \
+        add %o2, 0x40, %o0;            \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#else
+#define ASI_AIUS 0x80
+#define ASI_BLK_AIUS 0xf0
+#define FPRS_FEF  0x04
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#define SMALL_COPY_USES_FPU
+#define EXNV(x,y,a,b)  x,y;
+#define EXNV2(x,y,a,b) x,y;
+#define EXNV3(x,y,a,b) x,y;
+#define EX(x,y,a,b)    x,y;
+#define EXBLK1(x,y)    x,y;
+#define EXBLK2(x,y)    x,y;
+#define EXBLK3(x,y)    x,y;
+#define EXBLK4(x,y)    x,y;
+#endif
+
+       /* Special/non-trivial issues of this code:
+        *
+        * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
+        * 2) Only low 32 FPU registers are used so that only the
+        *    lower half of the FPU register set is dirtied by this
+        *    code.  This is especially important in the kernel.
+        * 3) This code never prefetches cachelines past the end
+        *    of the source buffer.
+        *
+        *    XXX Actually, Cheetah can buffer up to 8 concurrent
+        *    XXX prefetches, revisit this...
+        */
+
+       .text
+       .align  32
+
+       /* The cheetah's flexible spine, oversized liver, enlarged heart,
+        * slender muscular body, and claws make it the swiftest hunter
+        * in Africa and the fastest animal on land.  Can reach speeds
+        * of up to 2.4GB per second.
+        */
+
+       .globl          U3copy_in_user
+U3copy_in_user: /* %o0=dst, %o1=src, %o2=len */
+       /* Writing to %asi is _expensive_ so we hardcode it.
+        * Reading %asi to check for KERNEL_DS is comparatively
+        * cheap.
+        */
+       rd              %asi, %g1                       ! MS    Group   (4 cycles)
+       cmp             %g1, ASI_AIUS                   ! A0    Group
+       bne             U3memcpy                        ! BR
+        nop                                            ! A1
+#ifndef __KERNEL__
+       /* Save away original 'dst' for memcpy return value. */
+       mov             %o0, %g3                        ! A0    Group
+#endif
+       /* Anything to copy at all? */
+       cmp             %o2, 0                          ! A1
+       ble,pn          %icc, U3copy_in_user_short_ret  ! BR
+
+       /* Extremely small copy? */
+        cmp            %o2, 31                         ! A0    Group
+       ble,pn          %icc, U3copy_in_user_short      ! BR
+
+       /* Large enough to use unrolled prefetch loops? */
+        cmp            %o2, 0x100                      ! A1
+       bge,a,pt        %icc, U3copy_in_user_enter      ! BR    Group
+        andcc          %o0, 0x3f, %g2                  ! A0
+
+       ba,pt           %xcc, U3copy_in_user_toosmall   ! BR    Group
+        andcc          %o0, 0x7, %g2                   ! A0
+
+       .align          32
+U3copy_in_user_short:
+       /* Copy %o2 bytes from src to dst, one byte at a time. */
+       EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS    Group
+       add             %o1, 0x1, %o1                   ! A0
+       add             %o0, 0x1, %o0                   ! A1
+       subcc           %o2, 1, %o2                     ! A0    Group
+
+       bg,pt           %icc, U3copy_in_user_short      ! BR
+        EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1)    ! MS    Group (1-cycle stall)
+
+U3copy_in_user_short_ret:
+#ifdef __KERNEL__
+       retl                                            ! BR    Group (0-4 cycle stall)
+        clr            %o0                             ! A0
+#else
+       retl                                            ! BR    Group (0-4 cycle stall)
+        mov            %g3, %o0                        ! A0
+#endif
+
+       /* Here len >= (6 * 64) and condition codes reflect execution
+        * of "andcc %o0, 0x7, %g2", done by caller.
+        */
+       .align          64
+U3copy_in_user_enter:
+       /* Is 'dst' already aligned on an 64-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR
+
+       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x40, %g2                  ! A0    Group
+       sub             %g0, %g2, %g2                   ! A0    Group
+       sub             %o2, %g2, %o2                   ! A0    Group
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS    (Group)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+       and             %o1, 0x7, %g1                   ! A1
+       ba,pt           %xcc, U3copy_in_user_begin      ! BR
+        alignaddr      %o1, %g0, %o1                   ! MS          (Break-after)
+
+       .align          64
+U3copy_in_user_begin:
+       prefetch        [%o1 + 0x000], #one_read        ! MS    Group1
+       prefetch        [%o1 + 0x040], #one_read        ! MS    Group2
+       andn            %o2, (0x40 - 1), %o4            ! A0
+       prefetch        [%o1 + 0x080], #one_read        ! MS    Group3
+       cmp             %o4, 0x140                      ! A0
+       prefetch        [%o1 + 0x0c0], #one_read        ! MS    Group4
+       EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)  ! MS    Group5 (%f0 results at G8)
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetch       [%o1 + 0x100], #one_read        ! MS    Group6
+1:     EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)  ! AX           (%f2 results at G9)
+       cmp             %o4, 0x180                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+        prefetch       [%o1 + 0x140], #one_read        ! MS    Group7
+1:     EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)  ! AX           (%f4 results at G10)
+       cmp             %o4, 0x1c0                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetch       [%o1 + 0x180], #one_read        ! MS    Group8
+1:     faligndata      %f0, %f2, %f16                  ! FGA   Group9 (%f16 at G12)
+       EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)  ! AX           (%f6 results at G12)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group10 (%f18 results at G13)
+       EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)  ! MS            (%f8 results at G13)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group12 (1-cycle stall,%f20 at G15)
+       EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS            (%f10 results at G15)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group13 (%f22 results at G16)
+       
+       EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS            (%f12 results at G16)
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15 (1-cycle stall,%f24 at G18)
+       EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS            (%f14 results at G18)
+       faligndata      %f10, %f12, %f26                ! FGA   Group16 (%f26 results at G19)
+       EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)  ! MS            (%f0 results at G19)
+
+       /* We only use the first loop if len > (7 * 64). */
+       subcc           %o4, 0x1c0, %o4                 ! A0    Group17
+       bg,pt           %icc, U3copy_in_user_loop1      ! BR
+        add            %o1, 0x40, %o1                  ! A1
+
+       add             %o4, 0x140, %o4                 ! A0    Group18
+       ba,pt           %xcc, U3copy_in_user_loop2      ! BR
+        srl            %o4, 6, %o3                     ! A0    Group19
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       nop
+       nop
+
+       /* This loop performs the copy and queues new prefetches.
+        * We drop into the second loop when len <= (5 * 64).  Note
+        * that this (5 * 64) factor has been subtracted from len
+        * already.
+        */
+U3copy_in_user_loop1:
+       EXBLK1(ldda [%o1 + 0x008] %asi, %f2)            ! MS    Group2  (%f2 results at G5)
+       faligndata      %f12, %f14, %f28                ! FGA           (%f28 results at G5)
+       EXBLK1(ldda [%o1 + 0x010] %asi, %f4)            ! MS    Group3  (%f4 results at G6)
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall, %f30 at G7)
+       EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS
+       EXBLK1(ldda [%o1 + 0x018] %asi, %f6)            ! AX            (%f6 results at G7)
+
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+       EXBLK1(ldda [%o1 + 0x020] %asi, %f8)            ! MS            (%f8 results at G15)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13 (%f18 results at G16)
+       EXBLK1(ldda [%o1 + 0x028] %asi, %f10)           ! MS            (%f10 results at G16)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14 (%f20 results at G17)
+       EXBLK1(ldda [%o1 + 0x030] %asi, %f12)           ! MS            (%f12 results at G17)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15 (%f22 results at G18)
+       EXBLK1(ldda [%o1 + 0x038] %asi, %f14)           ! MS            (%f14 results at G18)
+
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16 (%f24 results at G19)
+       EXBLK1(ldda [%o1 + 0x040] %asi, %f0)            ! AX            (%f0 results at G19)
+       prefetch        [%o1 + 0x180], #one_read        ! MS
+       faligndata      %f10, %f12, %f26                ! FGA   Group17 (%f26 results at G20)
+       subcc           %o4, 0x40, %o4                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3copy_in_user_loop1              ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+U3copy_in_user_loop2_enter:
+       mov             5, %o3                          ! A1
+
+       /* This loop performs on the copy, no new prefetches are
+        * queued.  We do things this way so that we do not perform
+        * any spurious prefetches past the end of the src buffer.
+        */
+U3copy_in_user_loop2:
+       EXBLK2(ldda [%o1 + 0x008] %asi, %f2)            ! MS
+       faligndata      %f12, %f14, %f28                ! FGA   Group2
+       EXBLK2(ldda [%o1 + 0x010] %asi, %f4)            ! MS
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall)
+       EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS
+       EXBLK2(ldda [%o1 + 0x018] %asi, %f6)            ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+
+       EXBLK2(ldda [%o1 + 0x020] %asi, %f8)            ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13
+       EXBLK2(ldda [%o1 + 0x028] %asi, %f10)           ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14
+       EXBLK2(ldda [%o1 + 0x030] %asi, %f12)           ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15
+       EXBLK2(ldda [%o1 + 0x038] %asi, %f14)           ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16
+
+       EXBLK2(ldda [%o1 + 0x040] %asi, %f0)            ! AX
+       faligndata      %f10, %f12, %f26                ! FGA   Group17
+       subcc           %o3, 0x01, %o3                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3copy_in_user_loop2      ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+       /* Finally we copy the last full 64-byte block. */
+U3copy_in_user_loopfini:
+       EXBLK3(ldda [%o1 + 0x008] %asi, %f2)            ! MS
+       faligndata      %f12, %f14, %f28                ! FGA
+       EXBLK3(ldda [%o1 + 0x010] %asi, %f4)            ! MS    Group19
+       faligndata      %f14, %f0, %f30                 ! FGA
+       EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS    Group20
+       EXBLK4(ldda [%o1 + 0x018] %asi, %f6)            ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group11 (7-cycle stall)
+       EXBLK4(ldda [%o1 + 0x020] %asi, %f8)            ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group12
+       EXBLK4(ldda [%o1 + 0x028] %asi, %f10)           ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group13
+       EXBLK4(ldda [%o1 + 0x030] %asi, %f12)           ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group14
+       EXBLK4(ldda [%o1 + 0x038] %asi, %f14)           ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15
+       cmp             %g1, 0                          ! A0
+       be,pt           %icc, 1f                        ! BR
+        add            %o0, 0x40, %o0                  ! A1
+       EXBLK4(ldda [%o1 + 0x040] %asi, %f0)            ! MS
+1:     faligndata      %f10, %f12, %f26                ! FGA   Group16
+       faligndata      %f12, %f14, %f28                ! FGA   Group17
+       faligndata      %f14, %f0, %f30                 ! FGA   Group18
+       EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS
+       add             %o0, 0x40, %o0                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       membar          #Sync                           ! MS    Group26 (7-cycle stall)
+
+       /* Now we copy the (len modulo 64) bytes at the end.
+        * Note how we borrow the %f0 loaded above.
+        *
+        * Also notice how this code is careful not to perform a
+        * load past the end of the src buffer just like similar
+        * code found in U3copy_in_user_toosmall processing.
+        */
+U3copy_in_user_loopend:
+       and             %o2, 0x3f, %o2                  ! A0    Group
+       andcc           %o2, 0x38, %g2                  ! A0    Group
+       be,pn           %icc, U3copy_in_user_endcruft   ! BR
+        subcc          %g2, 0x8, %g2                   ! A1
+       be,pn           %icc, U3copy_in_user_endcruft   ! BR    Group
+        cmp            %g1, 0                          ! A0
+
+       be,a,pt         %icc, 1f                        ! BR    Group
+        EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)  ! MS
+
+1:     EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)   ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f0, %f2, %f8                   ! FGA   Group
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    (XXX does it stall here? XXX)
+       be,pn           %icc, U3copy_in_user_endcruft   ! BR
+        add            %o0, 0x8, %o0                   ! A0
+       EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)   ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    (XXX does it stall here? XXX)
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A0    Group
+
+       /* If anything is left, we copy it one byte at a time.
+        * Note that %g1 is (src & 0x3) saved above before the
+        * alignaddr was performed.
+        */
+U3copy_in_user_endcruft:
+       cmp             %o2, 0
+       add             %o1, %g1, %o1
+       VISExitHalf
+       be,pn           %icc, U3copy_in_user_short_ret
+        nop
+       ba,a,pt         %xcc, U3copy_in_user_short
+
+       /* If we get here, then 32 <= len < (6 * 64) */
+U3copy_in_user_toosmall:
+
+#ifdef SMALL_COPY_USES_FPU
+
+       /* Is 'dst' already aligned on an 8-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR    Group
+
+       /* Compute abs((dst & 7) - 8) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x8, %g2                   ! A0
+       sub             %g0, %g2, %g2                   ! A0    Group (reg-dep)
+       sub             %o2, %g2, %o2                   ! A0    Group (reg-dep)
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS   (Group) (%o3 in 3 cycles)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+
+       /* Compute (len - (len % 8)) into %g2.  This is guarenteed
+        * to be nonzero.
+        */
+       andn            %o2, 0x7, %g2                   ! A0    Group
+
+       /* You may read this and believe that it allows reading
+        * one 8-byte longword past the end of src.  It actually
+        * does not, as %g2 is subtracted as loads are done from
+        * src, so we always stop before running off the end.
+        * Also, we are guarenteed to have at least 0x10 bytes
+        * to move here.
+        */
+       sub             %g2, 0x8, %g2                   ! A0    Group (reg-dep)
+       alignaddr       %o1, %g0, %g1                   ! MS          (Break-after)
+       EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)   ! MS    Group (1-cycle stall)
+       add             %g1, 0x8, %g1                   ! A0
+
+1:     EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0)   ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+
+       faligndata      %f0, %f2, %f8                   ! FGA   Group (1-cycle stall)
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+       be,pn           %icc, 2f                        ! BR
+
+        add            %o0, 0x8, %o0                   ! A1
+       EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)   ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA   Group (1-cycle stall)
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A1
+
+       /* Nothing left to copy? */
+2:     cmp             %o2, 0                          ! A0    Group
+       VISExitHalf                                     ! A0+MS
+       be,pn           %icc, U3copy_in_user_short_ret  ! BR    Group
+        nop                                            ! A0
+       ba,a,pt         %xcc, U3copy_in_user_short      ! BR    Group
+
+#else /* !(SMALL_COPY_USES_FPU) */
+
+       xor             %o1, %o0, %g2
+       andcc           %g2, 0x7, %g0
+       bne,pn          %icc, U3copy_in_user_short
+        andcc          %o1, 0x7, %g2
+
+       be,pt           %xcc, 2f
+        sub            %g2, 0x8, %g2
+       sub             %g0, %g2, %g2
+       sub             %o2, %g2, %o2
+
+1:     EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
+       add             %o1, 0x1, %o1
+       add             %o0, 0x1, %o0
+       subcc           %g2, 0x1, %g2
+       bg,pt           %icc, 1b
+        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
+
+2:     andn            %o2, 0x7, %g2
+       sub             %o2, %g2, %o2
+
+3:     EXNV3(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2)
+       add             %o1, 0x8, %o1
+       add             %o0, 0x8, %o0
+       subcc           %g2, 0x8, %g2
+       bg,pt           %icc, 3b
+        EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2)
+
+       cmp             %o2, 0
+       bne,pn          %icc, U3copy_in_user_short
+        nop
+       ba,a,pt         %xcc, U3copy_in_user_short_ret
+
+#endif /* !(SMALL_COPY_USES_FPU) */
diff --git a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S
new file mode 100644 (file)
index 0000000..e08b129
--- /dev/null
@@ -0,0 +1,528 @@
+/* $Id: U3copy_to_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $
+ * U3memcpy.S: UltraSparc-III optimized copy to userspace.
+ *
+ * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#undef SMALL_COPY_USES_FPU
+#define EXNV(x,y,a,b)  \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    retl;                           \
+        a, b, %o0;                     \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXNV2(x,y,a,b) \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    a, b, %o0;                      \
+       retl;                           \
+        add %o0, 1, %o0;               \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXNV3(x,y,a,b) \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    a, b, %o0;                      \
+       retl;                           \
+        add %o0, 8, %o0;               \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EX(x,y,a,b)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       retl;                           \
+        a, b, %o0;                     \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK1(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       add %o4, 0x1c0, %o1;            \
+       and %o2, (0x40 - 1), %o2;       \
+       retl;                           \
+        add %o1, %o2, %o0;             \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK2(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       sll %o3, 6, %o3;                \
+       and %o2, (0x40 - 1), %o2;       \
+       add %o3, 0x80, %o1;             \
+       retl;                           \
+        add %o1, %o2, %o0;             \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK3(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o2;       \
+       retl;                           \
+        add %o2, 0x80, %o0;            \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#define EXBLK4(x,y)                    \
+98:    x,y;                            \
+       .section .fixup;                \
+       .align 4;                       \
+99:    VISExitHalf;                    \
+       and %o2, (0x40 - 1), %o2;       \
+       retl;                           \
+        add %o2, 0x40, %o0;            \
+       .section __ex_table;            \
+       .align 4;                       \
+       .word 98b, 99b;                 \
+       .text;                          \
+       .align 4;
+#else
+#define ASI_AIUS 0x80
+#define ASI_BLK_AIUS 0xf0
+#define FPRS_FEF  0x04
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#define SMALL_COPY_USES_FPU
+#define EXNV(x,y,a,b)  x,y;
+#define EXNV2(x,y,a,b) x,y;
+#define EXNV3(x,y,a,b) x,y;
+#define EX(x,y,a,b)    x,y;
+#define EXBLK1(x,y)    x,y;
+#define EXBLK2(x,y)    x,y;
+#define EXBLK3(x,y)    x,y;
+#define EXBLK4(x,y)    x,y;
+#endif
+
+       /* Special/non-trivial issues of this code:
+        *
+        * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
+        * 2) Only low 32 FPU registers are used so that only the
+        *    lower half of the FPU register set is dirtied by this
+        *    code.  This is especially important in the kernel.
+        * 3) This code never prefetches cachelines past the end
+        *    of the source buffer.
+        */
+
+       .text
+       .align  32
+
+       /* The cheetah's flexible spine, oversized liver, enlarged heart,
+        * slender muscular body, and claws make it the swiftest hunter
+        * in Africa and the fastest animal on land.  Can reach speeds
+        * of up to 2.4GB per second.
+        */
+
+       .globl          U3copy_to_user
+U3copy_to_user: /* %o0=dst, %o1=src, %o2=len */
+       /* Writing to %asi is _expensive_ so we hardcode it.
+        * Reading %asi to check for KERNEL_DS is comparatively
+        * cheap.
+        */
+       rd              %asi, %g1                       ! MS    Group   (4 cycles)
+       cmp             %g1, ASI_AIUS                   ! A0    Group
+       bne             U3memcpy                        ! BR
+        nop                                            ! A1
+#ifndef __KERNEL__
+       /* Save away original 'dst' for memcpy return value. */
+       mov             %o0, %g3                        ! A0    Group
+#endif
+       /* Anything to copy at all? */
+       cmp             %o2, 0                          ! A1
+       ble,pn          %icc, U3copy_to_user_short_ret  ! BR
+
+       /* Extremely small copy? */
+        cmp            %o2, 31                         ! A0    Group
+       ble,pn          %icc, U3copy_to_user_short      ! BR
+
+       /* Large enough to use unrolled prefetch loops? */
+        cmp            %o2, 0x100                      ! A1
+       bge,a,pt        %icc, U3copy_to_user_enter      ! BR    Group
+        andcc          %o0, 0x3f, %g2                  ! A0
+
+       ba,pt           %xcc, U3copy_to_user_toosmall   ! BR    Group
+        andcc          %o0, 0x7, %g2                   ! A0
+
+       .align          32
+U3copy_to_user_short:
+       /* Copy %o2 bytes from src to dst, one byte at a time. */
+       ldub            [%o1 + 0x00], %o3               ! MS    Group
+       add             %o1, 0x1, %o1                   ! A0
+       add             %o0, 0x1, %o0                   ! A1
+       subcc           %o2, 1, %o2                     ! A0    Group
+
+       bg,pt           %icc, U3copy_to_user_short      ! BR
+        EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1)    ! MS    Group (1-cycle stall)
+
+U3copy_to_user_short_ret:
+#ifdef __KERNEL__
+       retl                                            ! BR    Group (0-4 cycle stall)
+        clr            %o0                             ! A0
+#else
+       retl                                            ! BR    Group (0-4 cycle stall)
+        mov            %g3, %o0                        ! A0
+#endif
+
+       /* Here len >= (6 * 64) and condition codes reflect execution
+        * of "andcc %o0, 0x7, %g2", done by caller.
+        */
+       .align          64
+U3copy_to_user_enter:
+       /* Is 'dst' already aligned on an 64-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR
+
+       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x40, %g2                  ! A0    Group
+       sub             %g0, %g2, %g2                   ! A0    Group
+       sub             %o2, %g2, %o2                   ! A0    Group
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     ldub            [%o1 + 0x00], %o3               ! MS    (Group)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+       and             %o1, 0x7, %g1                   ! A1
+       ba,pt           %xcc, U3copy_to_user_begin      ! BR
+        alignaddr      %o1, %g0, %o1                   ! MS          (Break-after)
+
+       .align          64
+U3copy_to_user_begin:
+       prefetch        [%o1 + 0x000], #one_read        ! MS    Group1
+       prefetch        [%o1 + 0x040], #one_read        ! MS    Group2
+       andn            %o2, (0x40 - 1), %o4            ! A0
+       prefetch        [%o1 + 0x080], #one_read        ! MS    Group3
+       cmp             %o4, 0x140                      ! A0
+       prefetch        [%o1 + 0x0c0], #one_read        ! MS    Group4
+       ldd             [%o1 + 0x000], %f0              ! MS    Group5 (%f0 results at G8)
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetch       [%o1 + 0x100], #one_read        ! MS    Group6
+1:     ldd             [%o1 + 0x008], %f2              ! AX           (%f2 results at G9)
+       cmp             %o4, 0x180                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+        prefetch       [%o1 + 0x140], #one_read        ! MS    Group7
+1:     ldd             [%o1 + 0x010], %f4              ! AX           (%f4 results at G10)
+       cmp             %o4, 0x1c0                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetch       [%o1 + 0x180], #one_read        ! MS    Group8
+1:     faligndata      %f0, %f2, %f16                  ! FGA   Group9 (%f16 at G12)
+       ldd             [%o1 + 0x018], %f6              ! AX           (%f6 results at G12)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group10 (%f18 results at G13)
+       ldd             [%o1 + 0x020], %f8              ! MS            (%f8 results at G13)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group12 (1-cycle stall,%f20 at G15)
+       ldd             [%o1 + 0x028], %f10             ! MS            (%f10 results at G15)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group13 (%f22 results at G16)
+       
+       ldd             [%o1 + 0x030], %f12             ! MS            (%f12 results at G16)
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15 (1-cycle stall,%f24 at G18)
+       ldd             [%o1 + 0x038], %f14             ! MS            (%f14 results at G18)
+       faligndata      %f10, %f12, %f26                ! FGA   Group16 (%f26 results at G19)
+       ldd             [%o1 + 0x040], %f0              ! MS            (%f0 results at G19)
+
+       /* We only use the first loop if len > (7 * 64). */
+       subcc           %o4, 0x1c0, %o4                 ! A0    Group17
+       bg,pt           %icc, U3copy_to_user_loop1      ! BR
+        add            %o1, 0x40, %o1                  ! A1
+
+       add             %o4, 0x140, %o4                 ! A0    Group18
+       ba,pt           %xcc, U3copy_to_user_loop2      ! BR
+        srl            %o4, 6, %o3                     ! A0    Group19
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       nop
+       nop
+
+       /* This loop performs the copy and queues new prefetches.
+        * We drop into the second loop when len <= (5 * 64).  Note
+        * that this (5 * 64) factor has been subtracted from len
+        * already.
+        */
+U3copy_to_user_loop1:
+       ldd             [%o1 + 0x008], %f2              ! MS    Group2  (%f2 results at G5)
+       faligndata      %f12, %f14, %f28                ! FGA           (%f28 results at G5)
+       ldd             [%o1 + 0x010], %f4              ! MS    Group3  (%f4 results at G6)
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall, %f30 at G7)
+       EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS
+       ldd             [%o1 + 0x018], %f6              ! AX            (%f6 results at G7)
+
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+       ldd             [%o1 + 0x020], %f8              ! MS            (%f8 results at G15)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13 (%f18 results at G16)
+       ldd             [%o1 + 0x028], %f10             ! MS            (%f10 results at G16)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14 (%f20 results at G17)
+       ldd             [%o1 + 0x030], %f12             ! MS            (%f12 results at G17)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15 (%f22 results at G18)
+       ldd             [%o1 + 0x038], %f14             ! MS            (%f14 results at G18)
+
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16 (%f24 results at G19)
+       ldd             [%o1 + 0x040], %f0              ! AX            (%f0 results at G19)
+       prefetch        [%o1 + 0x180], #one_read        ! MS
+       faligndata      %f10, %f12, %f26                ! FGA   Group17 (%f26 results at G20)
+       subcc           %o4, 0x40, %o4                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3copy_to_user_loop1              ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+U3copy_to_user_loop2_enter:
+       mov             5, %o3                          ! A1
+
+       /* This loop performs on the copy, no new prefetches are
+        * queued.  We do things this way so that we do not perform
+        * any spurious prefetches past the end of the src buffer.
+        */
+U3copy_to_user_loop2:
+       ldd             [%o1 + 0x008], %f2              ! MS
+       faligndata      %f12, %f14, %f28                ! FGA   Group2
+       ldd             [%o1 + 0x010], %f4              ! MS
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall)
+       EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS
+       ldd             [%o1 + 0x018], %f6              ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+
+       ldd             [%o1 + 0x020], %f8              ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13
+       ldd             [%o1 + 0x028], %f10             ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14
+       ldd             [%o1 + 0x030], %f12             ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15
+       ldd             [%o1 + 0x038], %f14             ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16
+
+       ldd             [%o1 + 0x040], %f0              ! AX
+       faligndata      %f10, %f12, %f26                ! FGA   Group17
+       subcc           %o3, 0x01, %o3                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3copy_to_user_loop2      ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+       /* Finally we copy the last full 64-byte block. */
+U3copy_to_user_loopfini:
+       ldd             [%o1 + 0x008], %f2              ! MS
+       faligndata      %f12, %f14, %f28                ! FGA
+       ldd             [%o1 + 0x010], %f4              ! MS    Group19
+       faligndata      %f14, %f0, %f30                 ! FGA
+       EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS    Group20
+       ldd             [%o1 + 0x018], %f6              ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group11 (7-cycle stall)
+       ldd             [%o1 + 0x020], %f8              ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group12
+       ldd             [%o1 + 0x028], %f10             ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group13
+       ldd             [%o1 + 0x030], %f12             ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group14
+       ldd             [%o1 + 0x038], %f14             ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15
+       cmp             %g1, 0                          ! A0
+       be,pt           %icc, 1f                        ! BR
+        add            %o0, 0x40, %o0                  ! A1
+       ldd             [%o1 + 0x040], %f0              ! MS
+1:     faligndata      %f10, %f12, %f26                ! FGA   Group16
+       faligndata      %f12, %f14, %f28                ! FGA   Group17
+       faligndata      %f14, %f0, %f30                 ! FGA   Group18
+       EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)           ! MS
+       add             %o0, 0x40, %o0                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       membar          #Sync                           ! MS    Group26 (7-cycle stall)
+
+       /* Now we copy the (len modulo 64) bytes at the end.
+        * Note how we borrow the %f0 loaded above.
+        *
+        * Also notice how this code is careful not to perform a
+        * load past the end of the src buffer just like similar
+        * code found in U3copy_to_user_toosmall processing.
+        */
+U3copy_to_user_loopend:
+       and             %o2, 0x3f, %o2                  ! A0    Group
+       andcc           %o2, 0x38, %g2                  ! A0    Group
+       be,pn           %icc, U3copy_to_user_endcruft   ! BR
+        subcc          %g2, 0x8, %g2                   ! A1
+       be,pn           %icc, U3copy_to_user_endcruft   ! BR    Group
+        cmp            %g1, 0                          ! A0
+
+       be,a,pt         %icc, 1f                        ! BR    Group
+        ldd            [%o1 + 0x00], %f0               ! MS
+
+1:     ldd             [%o1 + 0x08], %f2               ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f0, %f2, %f8                   ! FGA   Group
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    (XXX does it stall here? XXX)
+       be,pn           %icc, U3copy_to_user_endcruft   ! BR
+        add            %o0, 0x8, %o0                   ! A0
+       ldd             [%o1 + 0x08], %f0               ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    (XXX does it stall here? XXX)
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A0    Group
+
+       /* If anything is left, we copy it one byte at a time.
+        * Note that %g1 is (src & 0x3) saved above before the
+        * alignaddr was performed.
+        */
+U3copy_to_user_endcruft:
+       cmp             %o2, 0
+       add             %o1, %g1, %o1
+       VISExitHalf
+       be,pn           %icc, U3copy_to_user_short_ret
+        nop
+       ba,a,pt         %xcc, U3copy_to_user_short
+
+       /* If we get here, then 32 <= len < (6 * 64) */
+U3copy_to_user_toosmall:
+
+#ifdef SMALL_COPY_USES_FPU
+
+       /* Is 'dst' already aligned on an 8-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR    Group
+
+       /* Compute abs((dst & 7) - 8) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x8, %g2                   ! A0
+       sub             %g0, %g2, %g2                   ! A0    Group (reg-dep)
+       sub             %o2, %g2, %o2                   ! A0    Group (reg-dep)
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     ldub            [%o1 + 0x00], %o3               ! MS    (Group) (%o3 in 3 cycles)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+
+       /* Compute (len - (len % 8)) into %g2.  This is guarenteed
+        * to be nonzero.
+        */
+       andn            %o2, 0x7, %g2                   ! A0    Group
+
+       /* You may read this and believe that it allows reading
+        * one 8-byte longword past the end of src.  It actually
+        * does not, as %g2 is subtracted as loads are done from
+        * src, so we always stop before running off the end.
+        * Also, we are guarenteed to have at least 0x10 bytes
+        * to move here.
+        */
+       sub             %g2, 0x8, %g2                   ! A0    Group (reg-dep)
+       alignaddr       %o1, %g0, %g1                   ! MS          (Break-after)
+       ldd             [%g1 + 0x00], %f0               ! MS    Group (1-cycle stall)
+       add             %g1, 0x8, %g1                   ! A0
+
+1:     ldd             [%g1 + 0x00], %f2               ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+
+       faligndata      %f0, %f2, %f8                   ! FGA   Group (1-cycle stall)
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+       be,pn           %icc, 2f                        ! BR
+
+        add            %o0, 0x8, %o0                   ! A1
+       ldd             [%g1 + 0x00], %f0               ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA   Group (1-cycle stall)
+       EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)   ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A1
+
+       /* Nothing left to copy? */
+2:     cmp             %o2, 0                          ! A0    Group
+       VISExitHalf                                     ! A0+MS
+       be,pn           %icc, U3copy_to_user_short_ret  ! BR    Group
+        nop                                            ! A0
+       ba,a,pt         %xcc, U3copy_to_user_short      ! BR    Group
+
+#else /* !(SMALL_COPY_USES_FPU) */
+
+       xor             %o1, %o0, %g2
+       andcc           %g2, 0x7, %g0
+       bne,pn          %icc, U3copy_to_user_short
+        andcc          %o1, 0x7, %g2
+
+       be,pt           %xcc, 2f
+        sub            %g2, 0x8, %g2
+       sub             %g0, %g2, %g2
+       sub             %o2, %g2, %o2
+
+1:     ldub            [%o1 + 0x00], %o3
+       add             %o1, 0x1, %o1
+       add             %o0, 0x1, %o0
+       subcc           %g2, 0x1, %g2
+       bg,pt           %icc, 1b
+        EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
+
+2:     andn            %o2, 0x7, %g2
+       sub             %o2, %g2, %o2
+
+3:     ldx             [%o1 + 0x00], %o3
+       add             %o1, 0x8, %o1
+       add             %o0, 0x8, %o0
+       subcc           %g2, 0x8, %g2
+       bg,pt           %icc, 3b
+        EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2)
+
+       cmp             %o2, 0
+       bne,pn          %icc, U3copy_to_user_short
+        nop
+       ba,a,pt         %xcc, U3copy_to_user_short_ret
+
+#endif /* !(SMALL_COPY_USES_FPU) */
diff --git a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S
new file mode 100644 (file)
index 0000000..d382891
--- /dev/null
@@ -0,0 +1,409 @@
+/* $Id: U3memcpy.S,v 1.2 2000/11/01 09:29:19 davem Exp $
+ * U3memcpy.S: UltraSparc-III optimized memcpy.
+ *
+ * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#undef SMALL_COPY_USES_FPU
+#else
+#define ASI_BLK_P 0xf0
+#define FPRS_FEF  0x04
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#define SMALL_COPY_USES_FPU
+#endif
+
+       /* Special/non-trivial issues of this code:
+        *
+        * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
+        * 2) Only low 32 FPU registers are used so that only the
+        *    lower half of the FPU register set is dirtied by this
+        *    code.  This is especially important in the kernel.
+        * 3) This code never prefetches cachelines past the end
+        *    of the source buffer.
+        */
+
+       .text
+       .align  32
+
+       /* The cheetah's flexible spine, oversized liver, enlarged heart,
+        * slender muscular body, and claws make it the swiftest hunter
+        * in Africa and the fastest animal on land.  Can reach speeds
+        * of up to 2.4GB per second.
+        */
+
+       .globl          U3memcpy
+U3memcpy: /* %o0=dst, %o1=src, %o2=len */
+#ifndef __KERNEL__
+       /* Save away original 'dst' for memcpy return value. */
+       mov             %o0, %g3                        ! A0    Group
+#endif
+       /* Anything to copy at all? */
+       cmp             %o2, 0                          ! A1
+       ble,pn          %icc, U3memcpy_short_ret        ! BR
+
+       /* Extremely small copy? */
+        cmp            %o2, 31                         ! A0    Group
+       ble,pn          %icc, U3memcpy_short            ! BR
+
+       /* Large enough to use unrolled prefetch loops? */
+        cmp            %o2, 0x100                      ! A1
+       bge,a,pt        %icc, U3memcpy_enter            ! BR    Group
+        andcc          %o0, 0x3f, %g2                  ! A0
+
+       ba,pt           %xcc, U3memcpy_toosmall         ! BR    Group
+        andcc          %o0, 0x7, %g2                   ! A0
+
+       .align          32
+U3memcpy_short:
+       /* Copy %o2 bytes from src to dst, one byte at a time. */
+       ldub            [%o1 + 0x00], %o3               ! MS    Group
+       add             %o1, 0x1, %o1                   ! A0
+       add             %o0, 0x1, %o0                   ! A1
+       subcc           %o2, 1, %o2                     ! A0    Group
+
+       bg,pt           %icc, U3memcpy_short            ! BR
+        stb            %o3, [%o0 + -1]                 ! MS    Group (1-cycle stall)
+
+U3memcpy_short_ret:
+#ifdef __KERNEL__
+       retl                                            ! BR    Group (0-4 cycle stall)
+        clr            %o0                             ! A0
+#else
+       retl                                            ! BR    Group (0-4 cycle stall)
+        mov            %g3, %o0                        ! A0
+#endif
+
+       /* Here len >= (6 * 64) and condition codes reflect execution
+        * of "andcc %o0, 0x7, %g2", done by caller.
+        */
+       .align          64
+U3memcpy_enter:
+       /* Is 'dst' already aligned on an 64-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR
+
+       /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x40, %g2                  ! A0    Group
+       sub             %g0, %g2, %g2                   ! A0    Group
+       sub             %o2, %g2, %o2                   ! A0    Group
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     ldub            [%o1 + 0x00], %o3               ! MS    (Group)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        stb            %o3, [%o0 + -1]                 ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+       and             %o1, 0x7, %g1                   ! A1
+       ba,pt           %xcc, U3memcpy_begin            ! BR
+        alignaddr      %o1, %g0, %o1                   ! MS          (Break-after)
+
+       .align          64
+U3memcpy_begin:
+       prefetch        [%o1 + 0x000], #one_read        ! MS    Group1
+       prefetch        [%o1 + 0x040], #one_read        ! MS    Group2
+       andn            %o2, (0x40 - 1), %o4            ! A0
+       prefetch        [%o1 + 0x080], #one_read        ! MS    Group3
+       cmp             %o4, 0x140                      ! A0
+       prefetch        [%o1 + 0x0c0], #one_read        ! MS    Group4
+       ldd             [%o1 + 0x000], %f0              ! MS    Group5 (%f0 results at G8)
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetch       [%o1 + 0x100], #one_read        ! MS    Group6
+1:     ldd             [%o1 + 0x008], %f2              ! AX           (%f2 results at G9)
+       cmp             %o4, 0x180                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+        prefetch       [%o1 + 0x140], #one_read        ! MS    Group7
+1:     ldd             [%o1 + 0x010], %f4              ! AX           (%f4 results at G10)
+       cmp             %o4, 0x1c0                      ! A1
+       bge,a,pt        %icc, 1f                        ! BR
+
+        prefetch       [%o1 + 0x180], #one_read        ! MS    Group8
+1:     faligndata      %f0, %f2, %f16                  ! FGA   Group9 (%f16 at G12)
+       ldd             [%o1 + 0x018], %f6              ! AX           (%f6 results at G12)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group10 (%f18 results at G13)
+       ldd             [%o1 + 0x020], %f8              ! MS            (%f8 results at G13)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group12 (1-cycle stall,%f20 at G15)
+       ldd             [%o1 + 0x028], %f10             ! MS            (%f10 results at G15)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group13 (%f22 results at G16)
+
+       ldd             [%o1 + 0x030], %f12             ! MS            (%f12 results at G16)
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15 (1-cycle stall,%f24 at G18)
+       ldd             [%o1 + 0x038], %f14             ! MS            (%f14 results at G18)
+       faligndata      %f10, %f12, %f26                ! FGA   Group16 (%f26 results at G19)
+       ldd             [%o1 + 0x040], %f0              ! MS            (%f0 results at G19)
+
+       /* We only use the first loop if len > (7 * 64). */
+       subcc           %o4, 0x1c0, %o4                 ! A0    Group17
+       bg,pt           %icc, U3memcpy_loop1            ! BR
+        add            %o1, 0x40, %o1                  ! A1
+
+       add             %o4, 0x140, %o4                 ! A0    Group18
+       ba,pt           %xcc, U3memcpy_loop2            ! BR
+        srl            %o4, 6, %o3                     ! A0    Group19
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       nop
+       nop
+
+       /* This loop performs the copy and queues new prefetches.
+        * We drop into the second loop when len <= (5 * 64).  Note
+        * that this (5 * 64) factor has been subtracted from len
+        * already.
+        */
+U3memcpy_loop1:
+       ldd             [%o1 + 0x008], %f2              ! MS    Group2  (%f2 results at G5)
+       faligndata      %f12, %f14, %f28                ! FGA           (%f28 results at G5)
+       ldd             [%o1 + 0x010], %f4              ! MS    Group3  (%f4 results at G6)
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall, %f30 at G7)
+       stda            %f16, [%o0] ASI_BLK_P           ! MS
+       ldd             [%o1 + 0x018], %f6              ! AX            (%f6 results at G7)
+
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+       ldd             [%o1 + 0x020], %f8              ! MS            (%f8 results at G15)
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13 (%f18 results at G16)
+       ldd             [%o1 + 0x028], %f10             ! MS            (%f10 results at G16)
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14 (%f20 results at G17)
+       ldd             [%o1 + 0x030], %f12             ! MS            (%f12 results at G17)
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15 (%f22 results at G18)
+       ldd             [%o1 + 0x038], %f14             ! MS            (%f14 results at G18)
+
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16 (%f24 results at G19)
+       ldd             [%o1 + 0x040], %f0              ! AX            (%f0 results at G19)
+       prefetch        [%o1 + 0x180], #one_read        ! MS
+       faligndata      %f10, %f12, %f26                ! FGA   Group17 (%f26 results at G20)
+       subcc           %o4, 0x40, %o4                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3memcpy_loop1            ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+U3memcpy_loop2_enter:
+       mov             5, %o3                          ! A1
+
+       /* This loop performs on the copy, no new prefetches are
+        * queued.  We do things this way so that we do not perform
+        * any spurious prefetches past the end of the src buffer.
+        */
+U3memcpy_loop2:
+       ldd             [%o1 + 0x008], %f2              ! MS
+       faligndata      %f12, %f14, %f28                ! FGA   Group2
+       ldd             [%o1 + 0x010], %f4              ! MS
+       faligndata      %f14, %f0, %f30                 ! FGA   Group4  (1-cycle stall)
+       stda            %f16, [%o0] ASI_BLK_P           ! MS
+       ldd             [%o1 + 0x018], %f6              ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group12 (7-cycle stall)
+
+       ldd             [%o1 + 0x020], %f8              ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group13
+       ldd             [%o1 + 0x028], %f10             ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group14
+       ldd             [%o1 + 0x030], %f12             ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group15
+       ldd             [%o1 + 0x038], %f14             ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group16
+
+       ldd             [%o1 + 0x040], %f0              ! AX
+       faligndata      %f10, %f12, %f26                ! FGA   Group17
+       subcc           %o3, 0x01, %o3                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       bg,pt           %xcc, U3memcpy_loop2            ! BR
+        add            %o0, 0x40, %o0                  ! A0    Group18
+
+       /* Finally we copy the last full 64-byte block. */
+U3memcpy_loopfini:
+       ldd             [%o1 + 0x008], %f2              ! MS
+       faligndata      %f12, %f14, %f28                ! FGA
+       ldd             [%o1 + 0x010], %f4              ! MS    Group19
+       faligndata      %f14, %f0, %f30                 ! FGA
+       stda            %f16, [%o0] ASI_BLK_P           ! MS    Group20
+       ldd             [%o1 + 0x018], %f6              ! AX
+       faligndata      %f0, %f2, %f16                  ! FGA   Group11 (7-cycle stall)
+       ldd             [%o1 + 0x020], %f8              ! MS
+       faligndata      %f2, %f4, %f18                  ! FGA   Group12
+       ldd             [%o1 + 0x028], %f10             ! MS
+       faligndata      %f4, %f6, %f20                  ! FGA   Group13
+       ldd             [%o1 + 0x030], %f12             ! MS
+       faligndata      %f6, %f8, %f22                  ! FGA   Group14
+       ldd             [%o1 + 0x038], %f14             ! MS
+       faligndata      %f8, %f10, %f24                 ! FGA   Group15
+       cmp             %g1, 0                          ! A0
+       be,pt           %icc, 1f                        ! BR
+        add            %o0, 0x40, %o0                  ! A1
+       ldd             [%o1 + 0x040], %f0              ! MS
+1:     faligndata      %f10, %f12, %f26                ! FGA   Group16
+       faligndata      %f12, %f14, %f28                ! FGA   Group17
+       faligndata      %f14, %f0, %f30                 ! FGA   Group18
+       stda            %f16, [%o0] ASI_BLK_P           ! MS
+       add             %o0, 0x40, %o0                  ! A0
+       add             %o1, 0x40, %o1                  ! A1
+       membar          #Sync                           ! MS    Group26 (7-cycle stall)
+
+       /* Now we copy the (len modulo 64) bytes at the end.
+        * Note how we borrow the %f0 loaded above.
+        *
+        * Also notice how this code is careful not to perform a
+        * load past the end of the src buffer just like similar
+        * code found in U3memcpy_toosmall processing.
+        */
+U3memcpy_loopend:
+       and             %o2, 0x3f, %o2                  ! A0    Group
+       andcc           %o2, 0x38, %g2                  ! A0    Group
+       be,pn           %icc, U3memcpy_endcruft         ! BR
+        subcc          %g2, 0x8, %g2                   ! A1
+       be,pn           %icc, U3memcpy_endcruft         ! BR    Group
+        cmp            %g1, 0                          ! A0
+
+       be,a,pt         %icc, 1f                        ! BR    Group
+        ldd            [%o1 + 0x00], %f0               ! MS
+
+1:     ldd             [%o1 + 0x08], %f2               ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f0, %f2, %f8                   ! FGA   Group
+       std             %f8, [%o0 + 0x00]               ! MS    (XXX does it stall here? XXX)
+       be,pn           %icc, U3memcpy_endcruft         ! BR
+        add            %o0, 0x8, %o0                   ! A0
+       ldd             [%o1 + 0x08], %f0               ! MS    Group
+       add             %o1, 0x8, %o1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA
+       std             %f8, [%o0 + 0x00]               ! MS    (XXX does it stall here? XXX)
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A0    Group
+
+       /* If anything is left, we copy it one byte at a time.
+        * Note that %g1 is (src & 0x3) saved above before the
+        * alignaddr was performed.
+        */
+U3memcpy_endcruft:
+       cmp             %o2, 0
+       add             %o1, %g1, %o1
+       VISExitHalf
+       be,pn           %icc, U3memcpy_short_ret
+        nop
+       ba,a,pt         %xcc, U3memcpy_short
+
+       /* If we get here, then 32 <= len < (6 * 64) */
+U3memcpy_toosmall:
+
+#ifdef SMALL_COPY_USES_FPU
+
+       /* Is 'dst' already aligned on an 8-byte boundary? */
+       be,pt           %xcc, 2f                        ! BR    Group
+
+       /* Compute abs((dst & 7) - 8) into %g2.  This is the number
+        * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
+        * subtract this from 'len'.
+        */
+        sub            %g2, 0x8, %g2                   ! A0
+       sub             %g0, %g2, %g2                   ! A0    Group (reg-dep)
+       sub             %o2, %g2, %o2                   ! A0    Group (reg-dep)
+
+       /* Copy %g2 bytes from src to dst, one byte at a time. */
+1:     ldub            [%o1 + 0x00], %o3               ! MS    (Group) (%o3 in 3 cycles)
+       add             %o1, 0x1, %o1                   ! A1
+       add             %o0, 0x1, %o0                   ! A0    Group
+       subcc           %g2, 0x1, %g2                   ! A1
+
+       bg,pt           %icc, 1b                        ! BR    Group
+        stb            %o3, [%o0 + -1]                 ! MS    Group
+
+2:     VISEntryHalf                                    ! MS+MS
+
+       /* Compute (len - (len % 8)) into %g2.  This is guarenteed
+        * to be nonzero.
+        */
+       andn            %o2, 0x7, %g2                   ! A0    Group
+
+       /* You may read this and believe that it allows reading
+        * one 8-byte longword past the end of src.  It actually
+        * does not, as %g2 is subtracted as loads are done from
+        * src, so we always stop before running off the end.
+        * Also, we are guarenteed to have at least 0x10 bytes
+        * to move here.
+        */
+       sub             %g2, 0x8, %g2                   ! A0    Group (reg-dep)
+       alignaddr       %o1, %g0, %g1                   ! MS          (Break-after)
+       ldd             [%g1 + 0x00], %f0               ! MS    Group (1-cycle stall)
+       add             %g1, 0x8, %g1                   ! A0
+
+1:     ldd             [%g1 + 0x00], %f2               ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+
+       faligndata      %f0, %f2, %f8                   ! FGA   Group (1-cycle stall)
+       std             %f8, [%o0 + 0x00]               ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+       be,pn           %icc, 2f                        ! BR
+
+        add            %o0, 0x8, %o0                   ! A1
+       ldd             [%g1 + 0x00], %f0               ! MS    Group
+       add             %g1, 0x8, %g1                   ! A0
+       sub             %o2, 0x8, %o2                   ! A1
+
+       subcc           %g2, 0x8, %g2                   ! A0    Group
+       faligndata      %f2, %f0, %f8                   ! FGA   Group (1-cycle stall)
+       std             %f8, [%o0 + 0x00]               ! MS    Group (2-cycle stall)
+       add             %o1, 0x8, %o1                   ! A0
+
+       bne,pn          %icc, 1b                        ! BR
+        add            %o0, 0x8, %o0                   ! A1
+
+       /* Nothing left to copy? */
+2:     cmp             %o2, 0                          ! A0    Group
+       VISExitHalf                                     ! A0+MS
+       be,pn           %icc, U3memcpy_short_ret        ! BR    Group
+        nop                                            ! A0
+       ba,a,pt         %xcc, U3memcpy_short            ! BR    Group
+
+#else /* !(SMALL_COPY_USES_FPU) */
+
+       xor             %o1, %o0, %g2
+       andcc           %g2, 0x7, %g0
+       bne,pn          %icc, U3memcpy_short
+        andcc          %o1, 0x7, %g2
+
+       be,pt           %xcc, 2f
+        sub            %g2, 0x8, %g2
+       sub             %g0, %g2, %g2
+       sub             %o2, %g2, %o2
+
+1:     ldub            [%o1 + 0x00], %o3
+       add             %o1, 0x1, %o1
+       add             %o0, 0x1, %o0
+       subcc           %g2, 0x1, %g2
+       bg,pt           %icc, 1b
+        stb            %o3, [%o0 + -1]
+
+2:     andn            %o2, 0x7, %g2
+       sub             %o2, %g2, %o2
+
+3:     ldx             [%o1 + 0x00], %o3
+       add             %o1, 0x8, %o1
+       add             %o0, 0x8, %o0
+       subcc           %g2, 0x8, %g2
+       bg,pt           %icc, 3b
+        stx            %o3, [%o0 + -8]
+
+       cmp             %o2, 0
+       bne,pn          %icc, U3memcpy_short
+        nop
+       ba,a,pt         %xcc, U3memcpy_short_ret
+
+#endif /* !(SMALL_COPY_USES_FPU) */
index 56634f83f15f989a07c9a501f61ceb4fd10fd4e6..b944a0ae7d672a5f83dea65dca51b08f2cb5172c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: VIScopy.S,v 1.23 2000/03/26 09:13:49 davem Exp $
+/* $Id: VIScopy.S,v 1.25 2000/11/01 09:29:19 davem Exp $
  * VIScopy.S: High speed copy operations utilizing the UltraSparc
  *            Visual Instruction Set.
  *
@@ -361,6 +361,38 @@ bcopy:             or              %o0, 0, %g3                     ! IEU0  Group
                 clr            %o0                             ! IEU0
 
 
+#ifdef __KERNEL__
+#define BRANCH_ALWAYS  0x10680000
+#define NOP            0x01000000
+#define ULTRA3_DO_PATCH(OLD, NEW)      \
+       sethi   %hi(NEW), %g1; \
+       or      %g1, %lo(NEW), %g1; \
+       sethi   %hi(OLD), %g2; \
+       or      %g2, %lo(OLD), %g2; \
+       sub     %g1, %g2, %g1; \
+       sethi   %hi(BRANCH_ALWAYS), %g3; \
+       srl     %g1, 2, %g1; \
+       or      %g3, %lo(BRANCH_ALWAYS), %g3; \
+       or      %g3, %g1, %g3; \
+       stw     %g3, [%g2]; \
+       sethi   %hi(NOP), %g3; \
+       or      %g3, %lo(NOP), %g3; \
+       stw     %g3, [%g2 + 0x4]; \
+       flush   %g2;
+
+       .globl  cheetah_patch_copyops
+cheetah_patch_copyops:
+       ULTRA3_DO_PATCH(memcpy, U3memcpy)
+       ULTRA3_DO_PATCH(__copy_from_user, U3copy_from_user)
+       ULTRA3_DO_PATCH(__copy_to_user, U3copy_to_user)
+       ULTRA3_DO_PATCH(__copy_in_user, U3copy_in_user)
+       retl
+        nop
+#undef BRANCH_ALWAYS
+#undef NOP
+#undef ULTRA3_DO_PATCH
+#endif /* __KERNEL__ */
+
        .align                  32
 #ifdef __KERNEL__
 __memcpy_384plus:
index 65fbd6e3762dc94232428a8ad29347bc8e17bd2d..6da2d0b8560d1e66f9742a1f610e8e65b06a57ef 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.157 2000/10/19 00:49:52 davem Exp $
+/*  $Id: init.c,v 1.159 2000/11/06 06:59:04 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -99,6 +99,20 @@ int do_check_pgt_cache(int low, int high)
         return freed;
 }
 
+extern void __update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+       struct page *page = pte_page(pte);
+
+       if (VALID_PAGE(page) && page->mapping &&
+           test_bit(PG_dcache_dirty, &page->flags)) {
+               __flush_dcache_page(page->virtual, 1);
+               clear_bit(PG_dcache_dirty, &page->flags);
+       }
+       __update_mmu_cache(vma, address, pte);
+}
+
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
index 7940218d289f25a287a0063d2b5e13ff037bb1b6..daaf580a0a66ad17650c4da5cbe8b74ec8ef957f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.46 2000/08/05 13:30:33 davem Exp $
+/* $Id: ultra.S,v 1.48 2000/11/06 06:59:04 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
@@ -208,27 +208,58 @@ iflush2:sub               %o1, 0x20, %g3
 
        .align          64
        .globl          __flush_dcache_page
-__flush_dcache_page:
+__flush_dcache_page:   /* %o0=kaddr, %o1=flush_icache */
        sub             %o0, %g4, %o0
-       clr             %o1
+       clr             %o4
        srlx            %o0, 11, %o0
        sethi           %hi(1 << 14), %o2
-1:     ldxa            [%o1] ASI_DCACHE_TAG, %o3
-       andn            %o3, 0x3, %o3
-       cmp             %o0, %o3
-       bne,pt          %xcc, 2f
-        nop
-       stxa            %g0, [%o1] ASI_DCACHE_TAG
-       membar          #Sync
-2:     add             %o1, (1 << 5), %o1
-       cmp             %o1, %o2
-       bne,pt          %xcc, 1b
-        nop
+1:     ldxa            [%o4] ASI_DCACHE_TAG, %o3       ! LSU   Group
+       add             %o4, (1 << 5), %o4              ! IEU0
+       ldxa            [%o4] ASI_DCACHE_TAG, %g1       ! LSU   Group
+       add             %o4, (1 << 5), %o4              ! IEU0
+       ldxa            [%o4] ASI_DCACHE_TAG, %g2       ! LSU   Group   o3 available
+       add             %o4, (1 << 5), %o4              ! IEU0
+       andn            %o3, 0x3, %o3                   ! IEU1
+       ldxa            [%o4] ASI_DCACHE_TAG, %g3       ! LSU   Group
+       add             %o4, (1 << 5), %o4              ! IEU0
+       andn            %g1, 0x3, %g1                   ! IEU1
+       cmp             %o0, %o3                        ! IEU1  Group
+       be,a,pn         %xcc, dflush1                   ! CTI
+        sub            %o4, (4 << 5), %o4              ! IEU0  (Group)
+       cmp             %o0, %g1                        ! IEU1  Group
+       andn            %g2, 0x3, %g2                   ! IEU0
+       be,a,pn         %xcc, dflush2                   ! CTI
+        sub            %o4, (3 << 5), %o4              ! IEU0  (Group)
+       cmp             %o0, %g2                        ! IEU1  Group
+       andn            %g3, 0x3, %g3                   ! IEU0
+       be,a,pn         %xcc, dflush3                   ! CTI
+        sub            %o4, (2 << 5), %o4              ! IEU0  (Group)
+       cmp             %o0, %g3                        ! IEU1  Group
+       be,a,pn         %xcc, dflush4                   ! CTI
+        sub            %o4, (1 << 5), %o4              ! IEU0
+2:     cmp             %o4, %o2                        ! IEU1  Group
+       bne,pt          %xcc, 1b                        ! CTI
+        nop                                            ! IEU0
+
        /* The I-cache does not snoop local stores so we
-        * better flush that too.
+        * better flush that too when necessary.
         */
-       ba,pt           %xcc, __flush_icache_page
+       brnz,pt         %o1, __flush_icache_page
         sllx           %o0, 11, %o0
+       retl
+        nop
+
+dflush1:stxa           %g0, [%o4] ASI_DCACHE_TAG
+       add             %o4, (1 << 5), %o4
+dflush2:stxa           %g0, [%o4] ASI_DCACHE_TAG
+       add             %o4, (1 << 5), %o4
+dflush3:stxa           %g0, [%o4] ASI_DCACHE_TAG
+       add             %o4, (1 << 5), %o4
+dflush4:stxa           %g0, [%o4] ASI_DCACHE_TAG
+       add             %o4, (1 << 5), %o4
+       membar          #Sync
+       ba,pt           %xcc, 2b
+        nop
 
        .align          32
 __prefill_dtlb:
@@ -250,8 +281,8 @@ __prefill_itlb:
        retl
         wrpr           %g7, %pstate
 
-       .globl          update_mmu_cache
-update_mmu_cache:      /* %o0=vma, %o1=address, %o2=pte */
+       .globl          __update_mmu_cache
+__update_mmu_cache:    /* %o0=vma, %o1=address, %o2=pte */
        ldub            [%g6 + AOFF_task_thread + AOFF_thread_fault_code], %o3
        srlx            %o1, 13, %o1
        ldx             [%o0 + 0x0], %o4                /* XXX vma->vm_mm */
index f686decfb3715d9751ab6865b59ab1eb6df75a10..91d4575d05942dd823b0229652bf48b8227ed5a9 100644 (file)
@@ -35,6 +35,9 @@ SECTIONS
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
   __kstrtab  : { *(.kstrtab) }
+  __start___kallsyms = .;      /* All kernel symbols */
+  __kallsyms : { *(__kallsyms) }
+  __stop___kallsyms = .;
   . = ALIGN(8192);
   __init_begin = .;
   .text.init : { *(.text.init) }
index 58da76eb05056d5ed24fb6e39ffc9fa365abf60f..411e07fcbbba7aba2bb7d1ab615e514d2cfb26c2 100644 (file)
@@ -284,7 +284,7 @@ acpi_thread(void *context)
        /*
         * initialize
         */
-       exit_files(current);
+
        daemonize();
        strcpy(current->comm, "acpi");
 
index 329d10c9cd0148f0d7aebecb9a3c54c91bc291fc..ae8489380edbc773853340e3f8b416ee2ac5a74f 100644 (file)
@@ -235,7 +235,7 @@ static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned l
        if (size > count)
                size = count;
 
-       kaddr = (char*)kmap(page);
+       kaddr = kmap(page);
        if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,IV)) {
                size = 0;
                printk(KERN_ERR "loop: transfer error block %ld\n",
index 6f583c3de480191e54f6b86a7005f1807955ba84..6a2352281713c54b71edd5d61ceaf35a7442c43f 100644 (file)
@@ -194,50 +194,47 @@ __setup("ramdisk_blocksize=", ramdisk_blocksize);
  * 19-JAN-1998  Richard Gooch <rgooch@atnf.csiro.au>  Added devfs support
  *
  */
-static void rd_request(request_queue_t * q)
+static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh)
 {
        unsigned int minor;
        unsigned long offset, len;
        struct buffer_head *rbh;
-       struct buffer_head *sbh;
 
-repeat:
-       INIT_REQUEST;
        
-       minor = MINOR(CURRENT->rq_dev);
+       minor = MINOR(sbh->b_rdev);
+
+       if (minor >= NUM_RAMDISKS)
+               goto fail;
 
-       if (minor >= NUM_RAMDISKS) {
-               end_request(0);
-               goto repeat;
-       }
        
-       offset = CURRENT->sector << 9;
-       len = CURRENT->current_nr_sectors << 9;
+       offset = sbh->b_rsector << 9;
+       len = sbh->b_size;
 
-       if ((offset + len) > rd_length[minor]) {
-               end_request(0);
-               goto repeat;
-       }
+       if ((offset + len) > rd_length[minor])
+               goto fail;
 
-       if ((CURRENT->cmd != READ) && (CURRENT->cmd != WRITE)) {
-               printk(KERN_INFO "RAMDISK: bad command: %d\n", CURRENT->cmd);
-               end_request(0);
-               goto repeat;
+       if (rw==READA)
+               rw=READ;
+       if ((rw != READ) && (rw != WRITE)) {
+               printk(KERN_INFO "RAMDISK: bad command: %d\n", rw);
+               goto fail;
        }
 
-       sbh = CURRENT->bh;
-       rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
-       if (CURRENT->cmd == READ) {
+       rbh = getblk(sbh->b_rdev, sbh->b_rsector/(sbh->b_size>>9), sbh->b_size);
+       if (rw == READ) {
                if (sbh != rbh)
-                       memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size);
+                       memcpy(sbh->b_data, rbh->b_data, rbh->b_size);
        } else
                if (sbh != rbh)
-                       memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size);
+                       memcpy(rbh->b_data, sbh->b_data, rbh->b_size);
        mark_buffer_protected(rbh);
        brelse(rbh);
 
-       end_request(1);
-       goto repeat;
+       sbh->b_end_io(sbh,1);
+       return 0;
+ fail:
+       sbh->b_end_io(sbh,0);
+       return 0;
 } 
 
 static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -378,7 +375,6 @@ static void __exit rd_cleanup (void)
 
        devfs_unregister (devfs_handle);
        unregister_blkdev( MAJOR_NR, "ramdisk" );
-       blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
        hardsect_size[MAJOR_NR] = NULL;
        blksize_size[MAJOR_NR] = NULL;
        blk_size[MAJOR_NR] = NULL;
@@ -403,7 +399,7 @@ int __init rd_init (void)
                return -EIO;
        }
 
-       blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_request);
+       blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request);
 
        for (i = 0; i < NUM_RAMDISKS; i++) {
                /* rd_size is given in kB */
index 76ddf7c3896c0046528f8c5158cde7d39584a21c..8389039d6540e9b6e6a0aec0a97ab5cd2ce9382f 100644 (file)
@@ -584,7 +584,6 @@ static int i2ob_evt(void *dummy)
        int i;
 
        lock_kernel();
-       exit_files(current);
        daemonize();
        unlock_kernel();
 
@@ -593,6 +592,7 @@ static int i2ob_evt(void *dummy)
 
        while(1)
        {
+#warning "RACE"
                interruptible_sleep_on(&i2ob_evt_wait);
                if(signal_pending(current)) {
                        evt_running = 0;
index 87871fa1503d5272f19cd27131a93ee7f1c86415..e9942c614a502ba13d8d992d8700693ff50f8a78 100644 (file)
@@ -842,7 +842,6 @@ static int i2o_core_evt(void *reply_data)
        int flags;
 
        lock_kernel();
-       exit_files(current);
        daemonize();
        unlock_kernel();
 
@@ -1005,7 +1004,6 @@ static int i2o_dyn_lct(void *foo)
        char name[16];
 
        lock_kernel();
-       exit_files(current);
        daemonize();
        unlock_kernel();
 
index d5b4b637e7e38fc43de313174392d984e307f730..f85ab2aa409c4aa8d43dc63c72901e400965f22c 100644 (file)
@@ -31,7 +31,7 @@ ide-obj-$(CONFIG_BLK_DEV_DTC2278)     += dtc2278.o
 ide-obj-$(CONFIG_BLK_DEV_FALCON_IDE)   += falconide.o
 ide-obj-$(CONFIG_BLK_DEV_GAYLE)                += gayle.o
 ide-obj-$(CONFIG_BLK_DEV_Q40IDE)       += q40ide.o
-ide-obj-$(CONFIG_BLK_DEV_HD)           += hd.o
+obj-$(CONFIG_BLK_DEV_HD)               += hd.o
 ide-obj-$(CONFIG_BLK_DEV_HPT34X)       += hpt34x.o
 ide-obj-$(CONFIG_BLK_DEV_HPT366)       += hpt366.o
 ide-obj-$(CONFIG_BLK_DEV_HT6560B)      += ht6560b.o
index 158d9463ed78359bfbf6c90904225fb9162ced01..2e9eb02df03de44963cc1faa66a1cd39763f0bc7 100644 (file)
@@ -563,37 +563,6 @@ act2000_readstatus(u_char * buf, int len, int user, act2000_card * card)
         return count;
 }
 
-static void
-act2000_putmsg(act2000_card *card, char c)
-{
-        ulong flags;
-
-        save_flags(flags);
-        cli();
-        *card->status_buf_write++ = c;
-        if (card->status_buf_write == card->status_buf_read) {
-                if (++card->status_buf_read > card->status_buf_end)
-                card->status_buf_read = card->status_buf;
-        }
-        if (card->status_buf_write > card->status_buf_end)
-                card->status_buf_write = card->status_buf;
-        restore_flags(flags);
-}
-
-static void
-act2000_logstat(struct act2000_card *card, char *str)
-{
-        char *p = str;
-        isdn_ctrl c;
-
-       while (*p)
-               act2000_putmsg(card, *p++);
-        c.command = ISDN_STAT_STAVAIL;
-        c.driver = card->myid;
-        c.arg = strlen(str);
-        card->interface.statcallb(&c);
-}
-
 /*
  * Find card with given driverId
  */
index b61f397d26460a9726098ac3216b139a8e225e93..ac0392251581c75f2935a78d384d20a73e7af5ef 100644 (file)
@@ -31,6 +31,7 @@
 #include "isdnl1.h"
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
 extern const char *CardType[];
 
@@ -1631,11 +1632,9 @@ static struct pci_dev *dev_hfcpci __initdata = NULL;
 
 #endif                         /* CONFIG_PCI */
 
-__initfunc(int
-          setup_hfcpci(struct IsdnCard *card))
+int __init setup_hfcpci(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
-       unsigned short cmd;
        char tmp[64];
        int i;
        struct pci_dev *tmp_hfcpci = NULL;
@@ -1645,15 +1644,11 @@ __initfunc(int
 #endif
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
        cs->hw.hfcpci.int_s1 = 0;
        cs->dc.hfcpci.ph_state = 0;
        cs->hw.hfcpci.fifo = 255;
        if (cs->typ == ISDN_CTYPE_HFC_PCI) {
-               if (!pci_present()) {
-                       printk(KERN_ERR "HFC-PCI: no PCI bus present\n");
-                       return (0);
-               }
                i = 0;
                while (id_list[i].vendor_id) {
                        tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
@@ -1686,41 +1681,6 @@ __initfunc(int
                        printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
                        return (0);
                }
-#ifdef notdef
-               if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) {
-                       printk(KERN_WARNING "HFC-PCI shared mem address will be corrected\n");
-                       pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
-                                            cs->hw.hfcpci.pci_device_fn,
-                                                 PCI_COMMAND,
-                                                 0x0103);      /* set SERR */
-                       pcibios_read_config_word(cs->hw.hfcpci.pci_bus,
-                                            cs->hw.hfcpci.pci_device_fn,
-                                                PCI_COMMAND,
-                                                &cmd);
-                       pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
-                                            cs->hw.hfcpci.pci_device_fn,
-                                                 PCI_COMMAND,
-                                                 cmd & ~2);
-                       (int) cs->hw.hfcpci.pci_io &= ~(PAGE_SIZE - 1);
-                       pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
-                                            cs->hw.hfcpci.pci_device_fn,
-                                                  PCI_BASE_ADDRESS_1,
-                                            (int) cs->hw.hfcpci.pci_io);
-                       pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
-                                            cs->hw.hfcpci.pci_device_fn,
-                                                 PCI_COMMAND,
-                                                 cmd);
-                       pcibios_read_config_dword(cs->hw.hfcpci.pci_bus,
-                                            cs->hw.hfcpci.pci_device_fn,
-                                                 PCI_BASE_ADDRESS_1,
-                                        (void *) &cs->hw.hfcpci.pci_io);
-                       if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) {
-                               printk(KERN_WARNING "HFC-PCI unable to align address %x\n", (unsigned) cs->hw.hfcpci.pci_io);
-                               return (0);
-                       }
-                       dev_hfcpci->resource[1].start = (int) cs->hw.hfcpci.pci_io;
-               }
-#endif
                if (!cs->hw.hfcpci.pci_io) {
                        printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
                        return (0);
index cd58e0d3be3f576af8453772d9b401930cfa3576..125742e6a8931006d1a0246f6c13ddf560297912 100644 (file)
@@ -114,9 +114,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
        dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
        if (!dev->b1) {
                printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
-               kfree(dev);
                iounmap((unsigned char*)dev->sh_mem);
                release_mem_region(dev->ph_mem, 4096);
+               kfree(dev);
                return -ENOMEM;
        }
     
@@ -124,9 +124,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
        if (!dev->b2) {
                printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
                kfree(dev->b1);
-               kfree(dev);
                iounmap((unsigned char*)dev->sh_mem);
                release_mem_region(dev->ph_mem, 4096);
+               kfree(dev);
                return -ENOMEM;
        }
 
@@ -148,9 +148,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
        {
                kfree(dev->b1);
                kfree(dev->b2);
-               kfree(dev);
                iounmap((unsigned char*)dev->sh_mem);
                release_mem_region(dev->ph_mem, 4096);
+               kfree(dev);
                dev_pcbit[board] = NULL;
                return -EIO;
        }
@@ -170,9 +170,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
                free_irq(irq, dev);
                kfree(dev->b1);
                kfree(dev->b2);
-               kfree(dev);
                iounmap((unsigned char*)dev->sh_mem);
                release_mem_region(dev->ph_mem, 4096);
+               kfree(dev);
                dev_pcbit[board] = NULL;
                return -EIO;
        }
@@ -201,9 +201,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
                free_irq(irq, dev);
                kfree(dev->b1);
                kfree(dev->b2);
-               kfree(dev);
                iounmap((unsigned char*)dev->sh_mem);
                release_mem_region(dev->ph_mem, 4096);
+               kfree(dev);
                dev_pcbit[board] = NULL;
                return -EIO;
        }
@@ -239,9 +239,9 @@ void pcbit_terminate(int board)
                        del_timer(&dev->b2->fsm_timer);
                kfree(dev->b1);
                kfree(dev->b2);
-               kfree(dev);
                iounmap((unsigned char*)dev->sh_mem);
                release_mem_region(dev->ph_mem, 4096);
+               kfree(dev);
        }
 }
 #endif
index b1bdf57affb0b4ea7281e4fa958550dec1cf9823..7d24ed731493575ef50d03e65998b1d8ccbd0d43 100644 (file)
  */
 #include <linux/kernel.h>
 
-#define NULL   0x0
-
-#define REQUEST_IRQ(a,b,c,d,e) request_irq(a,b,c,d,e)
-#define FREE_IRQ(a,b) free_irq(a,b)
-
 inline char *strcpy(char *, const char *);
 
 int dbg_level = 0;
@@ -61,7 +56,7 @@ inline char *strcpy(char *dest, const char *src)
                *i = *j;
                i++; j++;
        }
-       *(++i) = NULL;
+       *(++i) = 0;
        return dest;
 }
 
index 239ed99aa13a12b6feee9b52644739a9a768cb7c..5aa88df9e4537e4269aeee13293777e59351b46f 100644 (file)
@@ -1928,7 +1928,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
 {
        int l, le, l_new, p, size;
        ulong lv_status_save;
-       char *lv_tmp, *lv_buf;
+       char *lv_tmp, *lv_buf = NULL;
        lv_block_exception_t *lvbe = lv->lv_block_exception;
        vg_t *vg_ptr = vg[VG_CHR(minor)];
        lv_t *lv_ptr = NULL;
index c89314c788efbf59cdaa34c08cd8221b8039f874..a20e2d9d021483b2bede9c9737ffc87cad3e304a 100644 (file)
@@ -2836,14 +2836,13 @@ int md_thread(void * arg)
        mdk_thread_t *thread = arg;
 
        md_lock_kernel();
-       exit_mm(current);
-       exit_files(current);
-       exit_fs(current);
 
        /*
         * Detach thread
         */
+
        daemonize();
+
        sprintf(current->comm, thread->name);
        md_init_signals();
        md_flush_signals();
index 3f68a8e0a45555c16a5d83fce0636c2796fa24bc..85073b564683d5419a9e0173cac89772c3a5cf6b 100644 (file)
@@ -374,7 +374,7 @@ static void raid1_end_bh_io (struct raid1_bh *r1_bh, int uptodate)
 {
        struct buffer_head *bh = r1_bh->master_bh;
 
-       io_request_done(bh->b_blocknr*(bh->b_size>>9), mddev_to_conf(r1_bh->mddev),
+       io_request_done(bh->b_rsector, mddev_to_conf(r1_bh->mddev),
                        test_bit(R1BH_SyncPhase, &r1_bh->state));
 
        bh->b_end_io(bh, uptodate);
index f47ee246299e64f2ba22f7e8e98ecf1d8d31e1fd..b26b0630217d9c5b91214a1fb5636aaa6f5a291e 100644 (file)
@@ -72,7 +72,7 @@
 
                Jean-Jacques Michel - bug fix
                
-               Tobias - Rx interrupt status checking suggestion
+               Tobias Ringström - Rx interrupt status checking suggestion
 
        Submitting bug reports:
 
index b749908bd5e73d5388d03edde373068b7ca8ec9d..b8e1e297d5626603b11e1f62eaf8e704847dcd13 100644 (file)
@@ -766,6 +766,20 @@ struct de4x5_desc {
 #define DE4X5_PKT_BIN_SZ  128            /* Should be >=100 unless you
                                             increase DE4X5_PKT_STAT_SZ */
 
+struct pkt_stats {
+       u_int bins[DE4X5_PKT_STAT_SZ];      /* Private stats counters       */
+       u_int unicast;
+       u_int multicast;
+       u_int broadcast;
+       u_int excessive_collisions;
+       u_int tx_underruns;
+       u_int excessive_underruns;
+       u_int rx_runt_frames;
+       u_int rx_collision;
+       u_int rx_dribble;
+       u_int rx_overflow;
+};
+
 struct de4x5_private {
     char adapter_name[80];                  /* Adapter name                 */
     u_long interrupt;                       /* Aligned ISR flag             */
@@ -779,19 +793,7 @@ struct de4x5_private {
     char frame[64];                         /* Min sized packet for loopback*/
     spinlock_t lock;                        /* Adapter specific spinlock    */
     struct net_device_stats stats;          /* Public stats                 */
-    struct {
-       u_int bins[DE4X5_PKT_STAT_SZ];      /* Private stats counters       */
-       u_int unicast;
-       u_int multicast;
-       u_int broadcast;
-       u_int excessive_collisions;
-       u_int tx_underruns;
-       u_int excessive_underruns;
-       u_int rx_runt_frames;
-       u_int rx_collision;
-       u_int rx_dribble;
-       u_int rx_overflow;
-    } pktStats;
+    struct pkt_stats pktStats;             /* Private stats counters       */
     char rxRingSize;
     char txRingSize;
     int  bus;                               /* EISA or PCI                  */
@@ -5639,6 +5641,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        break;
 
     case DE4X5_SAY_BOO:              /* Say "Boo!" to the kernel log file */
+       if (!capable(CAP_NET_ADMIN)) return -EPERM;
        printk("%s: Boo!\n", dev->name);
        break;
 
@@ -5650,12 +5653,16 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        break;
 
     case DE4X5_GET_STATS:            /* Get the driver statistics */
-       ioc->len = sizeof(lp->pktStats);
+    {
+        struct pkt_stats statbuf;
+       ioc->len = sizeof(statbuf);
        spin_lock_irqsave(&lp->lock, flags);
-       if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT; 
+       memcpy(&statbuf, &lp->pktStats, ioc->len);
        spin_unlock_irqrestore(&lp->lock, flags);
+       if (copy_to_user(ioc->data, &statbuf, ioc->len)) 
+               return -EFAULT; 
        break;
-
+    }
     case DE4X5_CLR_STATS:            /* Zero out the driver statistics */
        if (!capable(CAP_NET_ADMIN)) return -EPERM;
        spin_lock_irqsave(&lp->lock, flags);
index 8d4ebe1a377aa82a5e2a0f4158b90d942c5462c0..5cdad9da4babb4b4c82de02550d6a091f8e137fe 100644 (file)
@@ -3791,6 +3791,9 @@ struct pci_dev *pdev = NULL;
                sprintf(fi->name, "fc%d", count);
 
                host = scsi_register(tmpt, sizeof(struct iph5526_hostdata));
+               if(host==NULL)
+                       return no_of_hosts;
+                       
                hostdata = (struct iph5526_hostdata *)host->hostdata;
                memset(hostdata, 0 , sizeof(struct iph5526_hostdata));
                for (j = 0; j < MAX_SCSI_TARGETS; j++)
index d12a9e150504ef032aa01be92e2595f59a940cc3..e705868d6449c6e669a7604b666a51244232c157 100644 (file)
@@ -1550,7 +1550,6 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        rrpriv = (struct rr_private *)dev->priv;
 
-       spin_lock(&rrpriv->lock);
 
        switch(cmd){
        case SIOCRRGFW:
@@ -1559,12 +1558,6 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        goto out;
                }
 
-               if (rrpriv->fw_running){
-                       printk("%s: Firmware already running\n", dev->name);
-                       error = -EPERM;
-                       goto out;
-               }
-
                image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
                if (!image){
                        printk(KERN_ERR "%s: Unable to allocate memory "
@@ -1572,51 +1565,63 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        error = -ENOMEM;
                        goto out;
                }
+               
+               spin_lock(&rrpriv->lock);
+               
+               if (rrpriv->fw_running){
+                       printk("%s: Firmware already running\n", dev->name);
+                       kfree(image);
+                       error = -EPERM;
+                       goto out_spin;
+               }
+
                i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
                if (i != EEPROM_BYTES){
                        kfree(image);
                        printk(KERN_ERR "%s: Error reading EEPROM\n",
                               dev->name);
                        error = -EFAULT;
-                       goto out;
+                       goto out_spin;
                }
+               spin_unlock(&rrpriv->lock);
                error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
                if (error)
                        error = -EFAULT;
                kfree(image);
-               break;
+               return error;
+               
        case SIOCRRPFW:
                if (!capable(CAP_SYS_RAWIO)){
-                       error = -EPERM;
-                       goto out;
-               }
-
-               if (rrpriv->fw_running){
-                       printk("%s: Firmware already running\n", dev->name);
-                       error = -EPERM;
-                       goto out;
+                       return -EPERM;
                }
 
                image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
                if (!image){
                        printk(KERN_ERR "%s: Unable to allocate memory "
                               "for EEPROM image\n", dev->name);
-                       error = -ENOMEM;
-                       goto out;
+                       return -ENOMEM;
                }
 
                oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
                if (!oldimage){
                        printk(KERN_ERR "%s: Unable to allocate memory "
                               "for old EEPROM image\n", dev->name);
-                       error = -ENOMEM;
-                       goto out;
+                       return -ENOMEM;
                }
 
                error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
                if (error)
                        error = -EFAULT;
 
+               spin_lock(&rrpriv->lock);
+               if (rrpriv->fw_running){
+                       kfree(image);
+                       kfree(oldimage);
+                       printk("%s: Firmware already running\n", dev->name);
+                       error = -EPERM;
+                       goto out_spin;
+               }
+
                printk("%s: Updating EEPROM firmware\n", dev->name);
 
                error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
@@ -1629,6 +1634,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        printk(KERN_ERR "%s: Error reading back EEPROM "
                               "image\n", dev->name);
 
+               spin_unlock(&rrpriv->lock);
                error = memcmp(image, oldimage, EEPROM_BYTES);
                if (error){
                        printk(KERN_ERR "%s: Error verifying EEPROM image\n",
@@ -1637,16 +1643,15 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                }
                kfree(image);
                kfree(oldimage);
-               break;
+               return error;
+               
        case SIOCRRID:
-               error = put_user(0x52523032, (int *)(&rq->ifr_data[0]));
-               if (error)
-                       error = -EFAULT;
-               break;
+               return put_user(0x52523032, (int *)(&rq->ifr_data[0]));
        default:
+               return error;
        }
 
- out:
+ out_spin:
        spin_unlock(&rrpriv->lock);
        return error;
 }
index bf64b5e1aa27b710edd66533f766732a42b996e6..3fc785761927f261c0b806ff6d34cea1bb7c0e00 100644 (file)
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:   1.07.04 Sep. 6 2000
+   Revision:   1.07.06 Nov. 7 2000
 
    Modified from the driver which is originally written by Donald Becker.
    
@@ -18,6 +18,8 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.07.06 Nov.  7 2000 Jeff Garzik <jgarzik@mandrakesoft.com> some bug fix and cleaning
+   Rev 1.07.05 Nov.  6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig
    Rev 1.07.04 Sep.  6 2000 Lei-Chun Chang added ICS1893 PHY support
    Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E eqaulizer workaroung rule
    Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update for SiS 630E and SiS 630E A1
@@ -56,7 +58,7 @@
 #include "sis900.h"
 
 static const char *version =
-"sis900.c: v1.07.04  09/06/2000\n";
+"sis900.c: v1.07.06  11/07/2000\n";
 
 static int max_interrupt_work = 20;
 static int multicast_filter_limit = 128;
@@ -169,6 +171,7 @@ static u16 sis900_compute_hashtable_index(u8 *addr);
 static void set_rx_mode(struct net_device *net_dev);
 static void sis900_reset(struct net_device *net_dev);
 static void sis630e_set_eq(struct net_device *net_dev);
+static int sis900_set_config(struct net_device *dev, struct ifmap *map);
 
 /* older SiS900 and friends, use EEPROM to store MAC address */
 static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
@@ -288,6 +291,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev
        net_dev->hard_start_xmit = &sis900_start_xmit;
        net_dev->stop = &sis900_close;
        net_dev->get_stats = &sis900_get_stats;
+       net_dev->set_config = &sis900_set_config;
        net_dev->set_multicast_list = &set_rx_mode;
        net_dev->do_ioctl = &mii_ioctl;
        net_dev->tx_timeout = sis900_tx_timeout;
@@ -1311,6 +1315,96 @@ sis900_get_stats(struct net_device *net_dev)
        return &sis_priv->stats;
 }
 
+/* Support for media type changes via net_device->set_config */
+static int sis900_set_config(struct net_device *dev, struct ifmap *map)
+{    
+       struct sis900_private *sis_priv = (struct sis900_private *)dev->priv;
+       struct mii_phy *mii_phy = sis_priv->mii;
+        
+       u16 status;
+
+       /* we support only port changes. All other runtime configuration
+          changes will be ignored (io base and interrupt changes for example)*/    
+       if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
+        /* we switch on the ifmap->port field. I couldn't find anything
+           like a definition or standard for the values of that field.
+           I think the meaning of those values is device specific. But
+           since I would like to change the media type via the ifconfig
+           command I use the definition from linux/netdevice.h 
+           (which seems to be different from the ifport(pcmcia) definition) 
+        */
+               switch(map->port){
+                       case IF_PORT_UNKNOWN: /* use auto here */   
+                               dev->if_port = map->port;
+                               /* we are going to change the media type, so the Link will
+                               be temporary down and we need to reflect that here. When
+                               the Link comes up again, it will be sensed by the sis_timer
+                               procedure, which also does all the rest for us */
+                               sis_priv->LinkOn=FALSE;
+                
+                               /* read current state */
+                               status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
+                
+                               /* enable auto negotiation and reset the negotioation
+                               (I dont really know what the auto negatiotiation reset
+                               really means, but it sounds for me right to do one here)*/
+                               mdio_write(dev, mii_phy->phy_addr,
+                                           MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
+
+                               break;
+            
+                       case IF_PORT_10BASET: /* 10BaseT */         
+                               dev->if_port = map->port;
+                
+                               /* we are going to change the media type, so the Link will
+                               be temporary down and we need to reflect that here. When
+                               the Link comes up again, it will be sensed by the sis_timer
+                               procedure, which also does all the rest for us */
+                               sis_priv->LinkOn=FALSE;
+        
+                               /* set Speed to 10Mbps */
+                               /* read current state */
+                               status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
+                
+                               /* disable auto negotiation and force 10MBit mode*/
+                               mdio_write(dev, mii_phy->phy_addr,
+                                           MII_CONTROL, status & ~(MII_CNTL_SPEED | MII_CNTL_AUTO));
+                               break;
+            
+                       case IF_PORT_100BASET: /* 100BaseT */
+                       case IF_PORT_100BASETX: /* 100BaseTx */ 
+                               dev->if_port = map->port;
+                
+                               /* we are going to change the media type, so the Link will
+                               be temporary down and we need to reflect that here. When
+                               the Link comes up again, it will be sensed by the sis_timer
+                               procedure, which also does all the rest for us */
+                               sis_priv->LinkOn=FALSE;
+                
+                               /* set Speed to 100Mbps */
+                               /* disable auto negotiation and enable 100MBit Mode */
+                               status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
+                               mdio_write(dev, mii_phy->phy_addr,
+                                           MII_CONTROL, (status & ~MII_CNTL_SPEED) | MII_CNTL_SPEED);
+                
+                               break;
+            
+                       case IF_PORT_10BASE2: /* 10Base2 */
+                       case IF_PORT_AUI: /* AUI */
+                       case IF_PORT_100BASEFX: /* 100BaseFx */
+                       /* These Modes are not supported (are they?)*/
+                               printk(KERN_INFO "Not supported");
+                               return -EOPNOTSUPP;
+                               break;
+            
+                       default:
+                               printk(KERN_INFO "Invalid");
+                               return -EINVAL;
+               }
+       }
+       return 0;
+}
+
 /* SiS 900 uses the most sigificant 7 bits to index a 128 bits multicast hash table, which makes
    this function a little bit different from other drivers */
 static u16 sis900_compute_hashtable_index(u8 *addr)
@@ -1448,3 +1542,4 @@ static void __exit sis900_cleanup_module(void)
 
 module_init(sis900_init_module);
 module_exit(sis900_cleanup_module);
+
index e905f09a6ac0a96be30a1cf187215b336758997e..740b72dc815a961e666c919bd13c4029473eaecc 100644 (file)
  *   http://www.sis.com.tw/support/databook.htm
  */
 
-/* MAC operation registers of SiS 7016 and SiS 900 ethernet controller */
+/*
+ * SiS 7016 and SiS 900 ethernet controller registers
+ */
+
 /* The I/O extent, SiS 900 needs 256 bytes of io address */
 #define SIS900_TOTAL_SIZE 0x100
 
@@ -259,7 +262,7 @@ enum sis630_revision_id {
 #define PCI_DEVICE_ID_SI_900   0x900   
 #define PCI_DEVICE_ID_SI_7016  0x7016  
 
-/* ioctl for accessing MII transveiver */
+/* ioctl for accessing MII transceiver */
 #define SIOCGMIIPHY (SIOCDEVPRIVATE)           /* Get the PHY in use. */
 #define SIOCGMIIREG (SIOCDEVPRIVATE+1)         /* Read a PHY register. */
 #define SIOCSMIIREG (SIOCDEVPRIVATE+2)         /* Write a PHY register */
index 3383f3e737e5b08d33ecefdceefc36851491aef2..3a83b10c8dc0f3c400bca503ac0a770690b5ef1f 100644 (file)
@@ -383,7 +383,7 @@ void cb_enable(socket_info_t * s)
                dev = &s->cb_config[i].dev;
                pci_writeb(dev, PCI_COMMAND, PCI_COMMAND_MASTER |
                           PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-               pci_writeb(dev, PCI_CACHE_LINE_SIZE, 8);
+               pci_writeb(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
        }
 
        if (s->irq.AssignedIRQ) {
index 44566c0a9354052aed2fa300871aad727e402b92..f2ee5ccc38b8550715b773b92d57683dcbd6053d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: aurora.c,v 1.7 1999/09/21 14:37:46 davem Exp $
+/*     $Id: aurora.c,v 1.9 2000/11/08 05:33:03 davem Exp $
  *     linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
  *
  *     Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -2387,7 +2387,6 @@ static void aurora_release_drivers(void)
 #endif
 }
 
-#ifndef MODULE
 /*
  * Called at boot time.
  *
@@ -2406,10 +2405,7 @@ void __init aurora_setup(char *str, int *ints)
                }
 }
 
-int __init aurora_init(void)
-#else
-int aurora_init(void)
-#endif
+static int __init aurora_real_init(void)
 {
        int found;
        int i;
@@ -2439,7 +2435,6 @@ int aurora_init(void)
        return 0;
 }
 
-#ifdef MODULE
 int irq  = 0;
 int irq1 = 0;
 int irq2 = 0;
@@ -2449,16 +2444,16 @@ MODULE_PARM(irq1, "i");
 MODULE_PARM(irq2, "i");
 MODULE_PARM(irq3, "i");
 
-int init_module(void) 
+static int __init aurora_init(void) 
 {
        if (irq ) irqs[0]=irq ;
        if (irq1) irqs[1]=irq1;
        if (irq2) irqs[2]=irq2;
        if (irq3) irqs[3]=irq3;
-       return aurora_init();
+       return aurora_real_init();
 }
        
-void cleanup_module(void)
+static void __exit aurora_cleanup(void)
 {
        int i;
        
@@ -2473,4 +2468,6 @@ printk("cleanup_module: aurora_release_drivers\n");
                        aurora_release_io_range(&aurora_board[i]);
                }
 }
-#endif /* MODULE */
+
+module_init(aurora_init);
+module_exit(aurora_cleanup);
index 4579404e310e5c70e867df408902c8397c583914..c96a141a5a095144228fe676c16dd04a82d7e117 100644 (file)
@@ -1017,11 +1017,7 @@ static inline void freeLptPort(int idx)
 
 static devfs_handle_t devfs_handle;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init bpp_init(void)
-#endif
+static int __init bpp_init(void)
 {
        int rc;
        unsigned idx;
@@ -1046,8 +1042,7 @@ int __init bpp_init(void)
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit bpp_cleanup(void)
 {
        unsigned idx;
 
@@ -1059,4 +1054,6 @@ void cleanup_module(void)
                        freeLptPort(idx);
        }
 }
-#endif
+
+module_init(bpp_init);
+module_exit(bpp_cleanup);
index 2ee0aee371900004f6aae468f8d0845924301652..091152a1c65f911649bd97ef9aed9e59f8612a4d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: display7seg.c,v 1.3 2000/08/29 07:01:55 davem Exp $
+/* $Id: display7seg.c,v 1.4 2000/11/08 05:08:23 davem Exp $
  *
  * display7seg - Driver implementation for the 7-segment display
  * present on Sun Microsystems CP1400 and CP1500
@@ -172,11 +172,7 @@ static struct file_operations d7s_fops = {
 
 static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops };
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init d7s_init(void)
-#endif
+static int __init d7s_init(void)
 {
        struct linux_ebus *ebus = NULL;
        struct linux_ebus_device *edev = NULL;
@@ -222,8 +218,7 @@ ebus_done:
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit d7s_cleanup(void)
 {
        int regs = readb(d7s_regs);
 
@@ -237,4 +232,6 @@ void cleanup_module(void)
        misc_deregister(&d7s_miscdev);
        d7s_free();
 }
-#endif
+
+module_init(d7s_init);
+module_exit(d7s_cleanup);
index 31c9de932fd2fa94c9a0e0f108df8227e3f3778c..e1de7a680baa7f35eaeb6b1383a0457f9371ad0a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.18 2000/10/17 16:20:35 davem Exp $
+/* $Id: envctrl.c,v 1.19 2000/11/03 00:37:40 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -11,7 +11,9 @@
  *     http://www-eu2.semiconductors.com/pip/PCF8584P
  *     http://www-eu2.semiconductors.com/pip/PCF8574AP
  *     http://www-eu2.semiconductors.com/pip/PCF8591P
- * 
+ *
+ * EB - Added support for CP1500 Global Address and PS/Voltage monitoring.
+ *             Eric Brower <ebrower@usa.net>
  */
 
 #include <linux/config.h>
  * Firmware definitions.
  */
 #define PCF8584_MAX_CHANNELS            8
+#define PCF8584_GLOBALADDR_TYPE                        6  /* global address monitor */
 #define PCF8584_FANSTAT_TYPE            3  /* fan status monitor */
 #define PCF8584_VOLTAGE_TYPE            2  /* voltage monitor    */
-#define PCF8584_TEMP_TYPE              1  /* temperature monitor*/
+#define PCF8584_TEMP_TYPE                      1  /* temperature monitor*/
 
 /* Monitor type of i2c child device.
  * Driver definitions.
  */
-#define ENVCTRL_NOMON                  0
-#define ENVCTRL_CPUTEMP_MON            1    /* cpu temperature monitor */
+#define ENVCTRL_NOMON                          0
+#define ENVCTRL_CPUTEMP_MON                    1    /* cpu temperature monitor */
 #define ENVCTRL_CPUVOLTAGE_MON         2    /* voltage monitor         */
 #define ENVCTRL_FANSTAT_MON            3    /* fan status monitor      */
 #define ENVCTRL_ETHERTEMP_MON          4    /* ethernet temperarture */
@@ -88,6 +91,7 @@
 #define ENVCTRL_VOLTAGESTAT_MON                5    /* voltage status monitor  */
 #define ENVCTRL_MTHRBDTEMP_MON         6    /* motherboard temperature */
 #define ENVCTRL_SCSITEMP_MON           7    /* scsi temperarture */
+#define ENVCTRL_GLOBALADDR_MON         8    /* global address */
 
 /* Child device type.
  * Driver definitions.
 #define ENVCTRL_MAX_CPU                        4
 #define CHANNEL_DESC_SZ                        256
 
+/* Mask values for combined GlobalAddress/PowerStatus node */
+#define ENVCTRL_GLOBALADDR_ADDR_MASK   0x1F
+#define ENVCTRL_GLOBALADDR_PSTAT_MASK  0x60
+
+/* Node 0x70 ignored on CompactPCI CP1400/1500 platforms 
+ * (see envctrl_init_i2c_child)
+ */
+#define ENVCTRL_CPCI_IGNORED_NODE              0x70
+
 struct pcf8584_reg {
         unsigned char data;
         unsigned char csr;
@@ -317,7 +330,6 @@ static unsigned char envctrl_i2c_read_8574(unsigned char addr)
        /* Do a single byte read and send stop. */
        rd = envctrl_i2c_read_data();
        envctrl_i2c_stop();
-
        return rd;
 }
 
@@ -462,7 +474,32 @@ static int envctrl_i2c_fan_status(struct i2c_child_t *pchild,
        return 1;
 }
 
-/* Function Description: Read voltage and power supply status.
+/* Function Description: Read global addressing line.
+ * Return : Always 1 byte. Status stored in bufdata.
+ */
+static int envctrl_i2c_globaladdr(struct i2c_child_t *pchild,
+                                 unsigned char data,
+                                 char *bufdata)
+{
+       /* Translatation table is not necessary, as global
+        * addr is the integer value of the GA# bits.
+        *
+        * NOTE: MSB is documented as zero, but I see it as '1' always....
+        *
+        * -----------------------------------------------
+        * | 0 | FAL | DEG | GA4 | GA3 | GA2 | GA1 | GA0 |
+        * -----------------------------------------------
+        * GA0 - GA4    integer value of Global Address (backplane slot#)
+        * DEG                  0 = cPCI Power supply output is starting to degrade
+        *                              1 = cPCI Power supply output is OK
+        * FAL                  0 = cPCI Power supply has failed
+        *                              1 = cPCI Power supply output is OK
+        */
+       bufdata[0] = (data & ENVCTRL_GLOBALADDR_ADDR_MASK);
+       return 1;
+}
+
+/* Function Description: Read standard voltage and power supply status.
  * Return : Always 1 byte. Status stored in bufdata.
  */
 static unsigned char envctrl_i2c_voltage_status(struct i2c_child_t *pchild,
@@ -587,10 +624,20 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
                ret = envctrl_i2c_fan_status(pchild,data[0], data);
                copy_to_user((unsigned char *)buf, data, ret);
                break;
+       
+       case ENVCTRL_RD_GLOBALADDRESS:
+               if (!(pchild = envctrl_get_i2c_child(ENVCTRL_GLOBALADDR_MON)))
+                       return 0;
+               data[0] = envctrl_i2c_read_8574(pchild->addr);
+               ret = envctrl_i2c_globaladdr(pchild, data[0], data);
+               copy_to_user((unsigned char *)buf, data, ret);
+               break;
 
        case ENVCTRL_RD_VOLTAGE_STATUS:
                if (!(pchild = envctrl_get_i2c_child(ENVCTRL_VOLTAGESTAT_MON)))
-                       return 0;
+                       /* If voltage monitor not present, check for CPCI equivalent */
+                       if (!(pchild = envctrl_get_i2c_child(ENVCTRL_GLOBALADDR_MON)))
+                               return 0;
                data[0] = envctrl_i2c_read_8574(pchild->addr);
                ret = envctrl_i2c_voltage_status(pchild, data[0], data);
                copy_to_user((unsigned char *)buf, data, ret);
@@ -621,6 +668,7 @@ envctrl_ioctl(struct inode *inode, struct file *file,
        case ENVCTRL_RD_VOLTAGE_STATUS:
        case ENVCTRL_RD_ETHERNET_TEMPERATURE:
        case ENVCTRL_RD_SCSI_TEMPERATURE:
+       case ENVCTRL_RD_GLOBALADDRESS:
                file->private_data = (void *)(long)cmd;
                break;
 
@@ -714,9 +762,6 @@ static void envctrl_set_mon(struct i2c_child_t *pchild,
 
        if (!(strcmp(chnl_desc,"temp,ethernet")))
                pchild->mon_type[chnl_no] = ENVCTRL_ETHERTEMP_MON;
-
-       if (!(strcmp(chnl_desc,"temp,ethernet")))
-               pchild->mon_type[chnl_no] = ENVCTRL_ETHERTEMP_MON;
 }
 
 /* Function Description: Initialize monitor channel with channel desc,
@@ -770,6 +815,39 @@ static void envctrl_init_fanstat(struct i2c_child_t *pchild)
        pchild->mon_type[0] = ENVCTRL_FANSTAT_MON;
 }
 
+/* Function Description: Initialize child device for global addressing line.
+ * Return: None.
+ */
+static void envctrl_init_globaladdr(struct i2c_child_t *pchild)
+{
+       int i;
+
+       /* Voltage/PowerSupply monitoring is piggybacked 
+        * with Global Address on CompactPCI.  See comments
+        * within envctrl_i2c_globaladdr for bit assignments.
+        *
+        * The mask is created here by assigning mask bits to each
+        * bit position that represents PCF8584_VOLTAGE_TYPE data.
+        * Channel numbers are not consecutive within the globaladdr
+        * node (why?), so we use the actual counter value as chnls_mask
+        * index instead of the chnl_array[x].chnl_no value.
+        *
+        * NOTE: This loop could be replaced with a constant representing
+        * a mask of bits 5&6 (ENVCTRL_GLOBALADDR_PSTAT_MASK).
+        */
+       for (i = 0; i < pchild->total_chnls; i++) {
+               if (PCF8584_VOLTAGE_TYPE == pchild->chnl_array[i].type) {
+                       pchild->voltage_mask |= chnls_mask[i];
+               }
+       }
+
+       /* We only need to know if this child has global addressing 
+        * line monitored.  We dont care which channels since we know 
+        * the mask already (ENVCTRL_GLOBALADDR_ADDR_MASK).
+        */
+       pchild->mon_type[0] = ENVCTRL_GLOBALADDR_MON;
+}
+
 /* Initialize child device monitoring voltage status. */
 static void envctrl_init_voltage_status(struct i2c_child_t *pchild)
 {
@@ -822,6 +900,27 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
                }
        }
 
+       /* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04)
+        * sections 2.5, 3.5, 4.5 state node 0x70 for CP1400/1500 is
+        * "For Factory Use Only."
+        *
+        * We ignore the node on these platforms by assigning the
+        * 'NULL' monitor type.
+        */
+       if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) {
+               int len;
+               char prop[56];
+
+               len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
+               if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len)))
+               {
+                       for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
+                               pchild->mon_type[len] = ENVCTRL_NOMON;
+                       }
+                       return;
+               }
+       }
+
        /* Get the monitor channels. */
        len = prom_getproperty(node, "channels-in-use",
                               (char *) pchild->chnl_array,
@@ -835,6 +934,11 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
                        envctrl_init_adc(pchild, node);
                        break;
 
+               case PCF8584_GLOBALADDR_TYPE:
+                       envctrl_init_globaladdr(pchild);
+                       i = pchild->total_chnls;
+                       break;
+
                case PCF8584_FANSTAT_TYPE:
                        envctrl_init_fanstat(pchild);
                        i = pchild->total_chnls;
@@ -865,7 +969,7 @@ static struct i2c_child_t *envctrl_get_i2c_child(unsigned char mon_type)
        for (i = 0; i < ENVCTRL_MAX_CPU*2; i++) {
                for (j = 0; j < PCF8584_MAX_CHANNELS; j++) {
                        if (i2c_childlist[i].mon_type[j] == mon_type) {
-                               return (struct i2c_child_t*)(&(i2c_childlist[i]));
+                               return (struct i2c_child_t *)(&(i2c_childlist[i]));
                        }
                }
        }
@@ -932,8 +1036,7 @@ done:
         * child devices.
         */
        printk("envctrl: initialized ");
-       for(--i; i >= 0; --i)
-       {
+       for (--i; i >= 0; --i) {
                printk("[%s 0x%lx]%s", 
                        (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") : 
                        ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")), 
index 8690638b35ea693fae26dd2a97c54875ecf7057c..71809b59d5f1e2231f43926f7adf57237b325d7c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.19 2000/07/13 08:06:40 davem Exp $
+/* $Id: flash.c,v 1.20 2000/11/08 04:57:49 davem Exp $
  * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -149,11 +149,7 @@ static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
 
 EXPORT_NO_SYMBOLS;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init flash_init(void)
-#endif
+static int __init flash_init(void)
 {
        struct sbus_bus *sbus;
        struct sbus_dev *sdev = 0;
@@ -236,9 +232,10 @@ int __init flash_init(void)
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit flash_cleanup(void)
 {
        misc_deregister(&flash_dev);
 }
-#endif
+
+module_init(flash_init);
+module_exit(flash_cleanup);
index 26e5ae8d95e57afc3a46ef1a16e57cc618ec42b5..f565ef6d2abe8790dfc4b54ac9112739c9ee73f0 100644 (file)
@@ -626,11 +626,7 @@ static struct miscdevice openprom_dev = {
 
 EXPORT_NO_SYMBOLS;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init openprom_init(void)
-#endif
+static int __init openprom_init(void)
 {
        unsigned long flags;
        int error;
@@ -655,9 +651,10 @@ int __init openprom_init(void)
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit openprom_cleanup(void)
 {
        misc_deregister(&openprom_dev);
 }
-#endif
+
+module_init(openprom_init);
+module_exit(openprom_cleanup);
index 6294d0e3774ce81922b7a5a5fd67a0001e9e1ed7..2740c62f31d8c0e7369083aa0076486c11e63a6e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: uctrl.c,v 1.8 2000/06/19 06:24:47 davem Exp $
+/* $Id: uctrl.c,v 1.9 2000/11/08 05:04:06 davem Exp $
  * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
  *
  * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
@@ -363,11 +363,7 @@ void uctrl_get_external_status()
        
 }
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init ts102_uctrl_init(void)
-#endif
+static int __init ts102_uctrl_init(void)
 {
        struct uctrl_driver *driver = &drv;
        int len, i;
@@ -419,9 +415,7 @@ int __init ts102_uctrl_init(void)
         return 0;
 }
 
-
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit ts102_uctrl_cleanup(void)
 {
        struct uctrl_driver *driver = &drv;
 
@@ -433,4 +427,6 @@ void cleanup_module(void)
        if (driver->regs)
                driver->regs = 0;
 }
-#endif
+
+module_init(ts102_uctrl_init);
+module_exit(ts102_uctrl_cleanup);
index 35865dd7066ad96f149527254571d2d07998bf1b..942a6c59bbca843c320acc3360c411d69824feff 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.86 2000/03/16 09:23:57 jj Exp $
+/* $Id: sbus.c,v 1.91 2000/11/08 05:04:06 davem Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -165,21 +165,9 @@ no_ranges:
 extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
 extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus);
 void sun4_init(void);
-#ifdef CONFIG_SUN_OPENPROMIO
-extern int openprom_init(void);
-#endif
 #ifdef CONFIG_SUN_AUXIO
 extern void auxio_probe(void);
 #endif
-#ifdef CONFIG_OBP_FLASH
-extern int flash_init(void);
-#endif
-#ifdef CONFIG_SUN_AURORA
-extern int aurora_init(void);
-#endif
-#ifdef CONFIG_TADPOLE_TS102_UCTRL
-extern int ts102_uctrl_init(void);
-#endif
 
 static void __init sbus_do_child_siblings(int start_node,
                                          struct sbus_dev *child,
@@ -520,25 +508,10 @@ void __init sbus_init(void)
                firetruck_init();
        }
 #endif
-#ifdef CONFIG_SUN_OPENPROMIO
-       openprom_init();
-#endif
-#ifdef CONFIG_SUN_BPP
-       bpp_init();
-#endif
 #ifdef CONFIG_SUN_AUXIO
        if (sparc_cpu_model == sun4u)
                auxio_probe ();
 #endif
-#ifdef CONFIG_OBP_FLASH
-       flash_init();
-#endif
-#ifdef CONFIG_SUN_AURORA
-       aurora_init();
-#endif
-#ifdef CONFIG_TADPOLE_TS102_UCTRL
-       ts102_uctrl_init();
-#endif
 #ifdef __sparc_v9__
        if (sparc_cpu_model == sun4u) {
                extern void clock_probe(void);
index cb70168a3b73cb458842f62dfcde24e04cefd53d..0a3db13f82b213bd63a3ae4d1d766371dc2a559c 100644 (file)
@@ -696,8 +696,13 @@ int tw_findcards(Scsi_Host_Template *tw_host)
 
                /* Register the card with the kernel SCSI layer */
                host = scsi_register(tw_host, sizeof(TW_Device_Extension));
-               
-               /* FIXME - check for NULL */
+               if( host == NULL)
+               {
+                       release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
+                       tw_free_device_extension(tw_dev);
+                       kfree(tw_dev);
+                       continue;
+               }
 
                status_reg_value = inl(tw_dev->registers.status_reg_addr);
 
index c22be78c0d7131eaaac45f09604457ce31ac7f3e..25636b008aad0ab75189bdfdc982db5cdeac166e 100644 (file)
@@ -2566,7 +2566,7 @@ static void datai_run(struct Scsi_Host *shpnt)
                 * STCNT to trigger ENSWRAP interrupt, instead of
                 * polling for DFIFOFULL
                 */
-               the_time=jiffies + 1000;
+               the_time=jiffies + 10*HZ;
                while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT) && time_before(jiffies,the_time))
                        barrier();
 
@@ -2735,7 +2735,7 @@ static void datao_run(struct Scsi_Host *shpnt)
                        CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
                }
 
-               the_time=jiffies+1000;
+               the_time=jiffies+10*HZ;
                while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time))
                        barrier();
 
index 8dce8b2cfeed2ad7cc44c26862fd0a2a6094743c..828c9e2903cbfbf4542ced6986ab04d1fd99d86b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: esp.c,v 1.97 2000/09/19 01:29:27 davem Exp $
+/* $Id: esp.c,v 1.98 2000/11/02 22:34:16 davem Exp $
  * esp.c:  EnhancedScsiProcessor Sun SCSI driver code.
  *
  * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
@@ -400,7 +400,7 @@ extern inline void esp_cmd(struct esp *esp, u8 cmd)
  *
  * struct scsi_cmnd:
  *
- *   We keep track of the syncronous capabilities of a target
+ *   We keep track of the synchronous capabilities of a target
  *   in the device member, using sync_min_period and
  *   sync_max_offset.  These are the values we directly write
  *   into the ESP registers while running a command.  If offset
@@ -2661,7 +2661,7 @@ static int esp_do_data_finale(struct esp *esp)
         * on HME broken adapters because we skip the HME fifo
         * workaround code in esp_handle() if we are doing data
         * phase things.  We don't want to fuck directly with
-        * the fifo like that, especially if doing syncronous
+        * the fifo like that, especially if doing synchronous
         * transfers!  Also, will need to double the count on
         * HME if we are doing wide transfers, as the HME fifo
         * will move and count 16-bit quantities during wide data.
index 8630e8ddf6f1fd8f0d31aa762f9bd1f3d8540511..d98c57686479ef40eb833deaf642b98ac9d73969 100644 (file)
@@ -4552,6 +4552,8 @@ ips_allocatescbs(ips_ha_t *ha) {
 
    /* Allocate memory for the CCBs */
    ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_ATOMIC|GFP_DMA);
+   if(ha->scbs == NULL)
+       return 0;
 
    memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t));
 
index fea2a9b4f34934e1558ba4dbe04f23ed8ccbd4eb..0e1dec16938219820c0c285661bc41deb1deff13 100644 (file)
@@ -1491,21 +1491,6 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
            pciDev,
            pdev->slot_name);
 
-    /*
-     * Dont crash on boot with AMI cards configured for I2O. 
-     *  (our I2O code will find them then they will fail oddly until
-     *   we figure why they upset our I2O code). This driver will die
-     *   if it tries to boot an I2O mode board and we dont stop it now.
-     *     - Alan Cox , Red Hat Software, Jan 2000
-     */
-           
-    if((pdev->class >> 8) == PCI_CLASS_INTELLIGENT_I2O)
-    {
-       printk( KERN_INFO "megaraid: Board configured for I2O, ignoring this card. Reconfigure the card\n"
-               KERN_INFO "megaraid: in the BIOS for \"mass storage\" to use it with this driver.\n");
-       continue;
-    }          
-
     /* Read the base port and IRQ from PCI */
     megaBase = pci_resource_start (pdev, 0);
     megaIrq  = pdev->irq;
@@ -1517,6 +1502,8 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
 
     /* Initialize SCSI Host structure */
     host = scsi_register (pHostTmpl, sizeof (mega_host_config));
+    if(host == NULL)
+       continue;
     megaCfg = (mega_host_config *) host->hostdata;
     memset (megaCfg, 0, sizeof (mega_host_config));
 
@@ -1543,12 +1530,11 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
     megaCtlrs[numCtlrs++] = megaCfg; 
     if (flag != BOARD_QUARTZ) {
       /* Request our IO Range */
-      if (check_region (megaBase, 16)) {
+      if (request_region (megaBase, 16, "megaraid")) {
        printk (KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR);
        scsi_unregister (host);
        continue;
       }
-      request_region (megaBase, 16, "megaraid");
     }
 
     /* Request our IRQ */
index e7b8bbe199c377e08f643a9e923dd6a72a6ef1c6..3d6e45fcdc36cb0ce1e2e34dbdd3a31b2ee06bce 100644 (file)
@@ -1861,9 +1861,6 @@ void scsi_error_handler(void *data)
         *    Flush resources
         */
 
-       exit_files(current);
-       current->files = init_task.files;
-       atomic_inc(&current->files->count);
        daemonize();
 
        /*
index 0b25bd4e2e5e3580ab5b4cf65ae6d6bd2f66a8d4..55adb72af27a3810d08fb535bd542ef4345bc547 100644 (file)
@@ -370,7 +370,7 @@ void scsi_old_done(Scsi_Cmnd * SCpnt)
                   * crashing, all scsi_done() calls during sync resets are ignored.
                 */
                printk("scsi%d: device driver called scsi_done() "
-                      "for a syncronous reset.\n", SCpnt->host->host_no);
+                      "for a synchronous reset.\n", SCpnt->host->host_no);
                return;
        }
        if (SCpnt->flags & WAS_SENSE) {
index 82869fb81cabc64fe6957ff2c3de4ebcdcf7ea7a..4448026521ffe4626290207d6369a79651def486 100644 (file)
@@ -274,7 +274,7 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 
 /* ----------------------------------------------------------------------- */
 /* this is called by the generic cdrom driver. arg is a _kernel_ pointer,  */
-/* becauce the generic cdrom driver does the user access stuff for us.     */
+/* because the generic cdrom driver does the user access stuff for us.     */
 /* only cdromreadtochdr and cdromreadtocentry are left - for use with the  */
 /* sr_disk_status interface for the generic cdrom driver.                  */
 
index 54b50bb1e13ff40470e52b5df02fc1bfa4e02251..c4d2c50cec90f300dc108438f79e6c737f29ceed 100644 (file)
  *     Analog Devices (A major AC97 codec maker)
  *     Intel Corp  (you've probably heard of them already)
  *
+ * AC97 clues and assistance provided by
+ *     Analog Devices
+ *     Zach 'Fufu' Brown
+ *     Jeff Garzik
+ *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
  *     the Free Software Foundation; either version 2 of the License, or
 #endif
 
 static int ftsodell=0;
-static int clocking=48000;
+static unsigned int clocking=48000;
 
 
 #define ADC_RUNNING    1
@@ -377,7 +382,7 @@ static void i810_free_pcm_channel(struct i810_card *card, int channel)
 static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate)
 {      
        struct dmabuf *dmabuf = &state->dmabuf;
-       u16 dacp, rp;
+       u32 dacp;
        struct ac97_codec *codec=state->card->ac97_codec[0];
        
        if(!(state->card->ac97_features&0x0001))
@@ -403,22 +408,18 @@ static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int ra
        if(rate < 8000)
                rate = 8000;
 
-       /* Power down the DAC */
-       dacp=i810_ac97_get(codec, AC97_POWER_CONTROL);
-       i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0200);
-       
-       /* Load the rate and read the effective rate */
-       i810_ac97_set(codec, AC97_PCM_FRONT_DAC_RATE, rate);
-       rp=i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE);
-       
-//     printk("DAC rate set to %d Returned %d\n", 
-//             rate, (int)rp);
-               
-       rate=(rp * 48000) / clocking;
-               
-       /* Power it back up */
-       i810_ac97_set(codec, AC97_POWER_CONTROL, dacp);
-       
+       if(rate != i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE))
+       {
+               /* Power down the DAC */
+               dacp=i810_ac97_get(codec, AC97_POWER_CONTROL);
+               i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0200);
+               /* Load the rate and read the effective rate */
+               i810_ac97_set(codec, AC97_PCM_FRONT_DAC_RATE, rate);
+               rate=i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE);
+               /* Power it back up */
+               i810_ac97_set(codec, AC97_POWER_CONTROL, dacp);
+       }
+       rate=(rate * 48000) / clocking;
        dmabuf->rate = rate;
 #ifdef DEBUG
        printk("i810_audio: called i810_set_dac_rate : rate = %d\n", rate);
@@ -431,7 +432,7 @@ static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int ra
 static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate)
 {
        struct dmabuf *dmabuf = &state->dmabuf;
-       u16 dacp, rp;
+       u32 dacp;
        struct ac97_codec *codec=state->card->ac97_codec[0];
        
        if(!(state->card->ac97_features&0x0001))
@@ -457,30 +458,23 @@ static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int ra
        if(rate < 8000)
                rate = 8000;
 
-
-       /* Power down the ADC */
-       dacp=i810_ac97_get(codec, AC97_POWER_CONTROL);
-       i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0100);
-       
-       /* Load the rate and read the effective rate */
-       i810_ac97_set(codec, AC97_PCM_LR_DAC_RATE, rate);
-       rp=i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE);
-       
-//     printk("ADC rate set to %d Returned %d\n", 
-//             rate, (int)rp);
-               
-       rate = (rp * 48000) / clocking;
-               
-       /* Power it back up */
-       i810_ac97_set(codec, AC97_POWER_CONTROL, dacp);
-       
+       if(rate != i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE))
+       {
+               /* Power down the ADC */
+               dacp=i810_ac97_get(codec, AC97_POWER_CONTROL);
+               i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0100);
+               /* Load the rate and read the effective rate */
+               i810_ac97_set(codec, AC97_PCM_LR_DAC_RATE, rate);
+               rate=i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE);
+               /* Power it back up */
+               i810_ac97_set(codec, AC97_POWER_CONTROL, dacp);
+       }
+       rate = (rate * 48000) / clocking;
        dmabuf->rate = rate;
 #ifdef DEBUG
        printk("i810_audio: called i810_set_adc_rate : rate = %d\n", rate);
 #endif
-
        return rate;
-
 }
 
 /* prepare channel attributes for playback */ 
@@ -1726,10 +1720,37 @@ static int __init i810_ac97_init(struct i810_card *card)
        int ready_2nd = 0;
        struct ac97_codec *codec;
        u16 eid;
+       int i=0;
+       u32 reg;
 
-       outl(0, card->iobase + GLOB_CNT);
-       udelay(500);
-       outl(1<<1, card->iobase + GLOB_CNT);
+       reg = inl(card->iobase + GLOB_CNT);
+       
+       if((reg&2)==0)  /* Cold required */
+               reg|=2;
+       else
+               reg|=4; /* Warm */
+               
+       reg&=~8;        /* ACLink on */
+       outl(reg , card->iobase + GLOB_CNT);
+       
+       while(i<10)
+       {
+               if((inl(card->iobase+GLOB_CNT)&4)==0)
+                       break;
+               current->state = TASK_UNINTERRUPTIBLE;
+               schedule_timeout(HZ/20);
+               i++;
+       }
+       if(i==10)
+       {
+               printk(KERN_ERR "i810_audio: AC'97 reset failed.\n");
+               return 0;
+       }
+
+       current->state = TASK_UNINTERRUPTIBLE;
+       schedule_timeout(HZ/5);
+               
+       inw(card->ac97base);
 
        for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
                if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
index 8b9b0bfbc41f9294dce29767560ddea202dc01fd..144cea36c3e6e2981df5a4413be7504876870afc 100644 (file)
@@ -751,9 +751,7 @@ static int usb_hub_thread(void *__hub)
         * This thread doesn't need any user-level access,
         * so get rid of all our resources
         */
-       exit_files(current);  /* daemonize doesn't do exit_files */
-       current->files = init_task.files;
-       atomic_inc(&current->files->count);
+
        daemonize();
 
        /* Setup a nice name */
index d3d1b4e6ac8b3857e3fb12e8cbbcec2475ba2a16..d247c0b289f7a62066ae7c276ff5568c49bbd452 100644 (file)
@@ -1,9 +1,11 @@
 /*****************************************************************************/
 
 /*
- *      plusb.c  --  prolific pl-2302 driver.
+ *      plusb.c  --  prolific pl-2301/pl-2302 driver.
  *
  *      Copyright (C) 2000  Deti Fliegl (deti@fliegl.de)
+ *      Copyright (C) 2000  Pavel Machek (pavel@suse.cz)
+ *      Copyright (C) 2000  Eric Z. Ayers (eric@compgen.com)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *
+ *  This driver creates a network interface (plusb0, plusb1, ...) that will
+ *  send messages over a USB host-host cable based on the Prolific ASIC.
+ *  It works a lot like plip or PP over an RS-232C null modem cable.
+ *
+ *  Expect speeds of around 330Kbytes/second over a UHCI host controller.
+ *  OHCI should be faster.  Increase the MTU for faster transfers of large
+ *  files.  (16384 is a good size)
  *
  *  $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $
  *
+ *  Changelog:
+ *
+ *    v0.1                deti
+ *        Original Version of driver.
+ *    v0.2     15 Sep 2000  pavel
+ *        Patches to decrease latency by rescheduling the bottom half of
+ *          interrupt code.
+ *    v0.3     10 Oct 2000  eric
+ *        Patches to work in v2.2 backport (v2.4 changes the way net_dev.name
+ *          is allocated)
+ *    v0.4     19 Oct 2000  eric
+ *        Some more performance fixes.  Lock re-submitting urbs.
+ *          Lower the number of sk_buff's to queue.
+ *    v0.5     25 Oct 2000 eric
+ *        Removed use of usb_bulk_msg() all together.  This caused
+ *          the driver to block in an interrupt context.
+ *        Consolidate read urb submission into read_urb_submit().
+ *        Performance is the same as v0.4.
+ *    v0.5.1   27 Oct 2000 eric
+ *        Extra debugging messages to help diagnose problem with uchi.o stack.
+ *    v0.5.2   27 Oct 2000 eric
+ *        Set the 'start' flag for the network device in plusb_net_start()
+ *         and plusb_net_stop() (doesn't help)
+ *    v0.5.3   27 Oct 2000 pavel
+ *        Commented out handlers when -EPIPE is received,
+ *         (remove calls to usb_clear_halt()) Since the callback is in
+ *         an interrupt context, it doesn't help, it just panics
+ *         the kernel. (what do we do?)
+ *        Under high load, dev_alloc_skb() fails, the read URB must
+ *         be re-submitted.
+ *        Added plusb_change_mtu() and increased the size of _BULK_DATA_LEN
+ *    v0.5.4   31 Oct 2000 eric
+ *        Fix race between plusb_net_xmit() and plusb_bulk_write_complete()
+ *    v0.5.5    1 Nov 2000 eric
+ *        Remove dev->start field, otherwise, it won't compile in 2.4
+ *        Use dev_kfree_skb_any(). (important in 2.4 kernel)
+ *    v0.5.6   2 Nov 2000 pavel,eric
+ *        Add calls to netif_stop_queue() and netif_start_queue()
+ *        Drop packets that come in while the free list is empty.
+ *        (This version is being submitted after the release of 2.4-test10)
+ *    v0.5.7   6 Nov 2000
+ *        Fix to not re-submit the urb on error to help when cables
+ *          are yanked (not tested)
+ *
+ *
+ * KNOWN PROBLEMS: (Any suggestions greatfully accepted!)
+ *
+ *     2 Nov 2000
+ *      - The shutdown for this may not be entirely clean.  Sometimes, the
+ *         kernel will Oops when the cable is unplugged, or
+ *         if the plusb module is removed.
+ *      - If you ifdown a device and then ifup it again, the link will not
+ *         always work.  You have to 'rmmod plusb ; modprobe plusb' on
+ *         both machines to get it to work again.  Something must be wrong with
+ *         plusb_net_open() and plusb_net_start() ?  Maybe
+ *         the 'suspend' and 'resume' entry points need to be
+ *         implemented?
+ *      - Needs to handle -EPIPE correctly in bulk complete handlers.
+ *         (replace usb_clear_halt() function with async urbs?)
+ *      - I think this code relies too much on one spinlock and does
+ *         too much in the interrupt handler.  The net1080 code is
+ *         much more elegant, and should work for this chip.  Its
+ *         only drawback is that it is going to be tough to backport
+ *         it to v2.2.
+ *      - Occasionally the device will hang under the 'uhci.o'
+ *         driver.   The workaround is to ifdown the device and
+ *         remove the modules, then re-insert them.  You may have
+ *         better luck with the 'usb-uhci.o' driver.
+ *      - After using ifconfig down ; ifconfig up, sometimes packets
+ *         continue to be received, but there is a framing problem.
+ *
+ * FUTURE DIRECTIONS:
+ *
+ *     - Fix the known problems.
+ *     - There isn't much functional difference between the net1080
+ *        driver and this one.  It would be neat if the same driver
+ *        could handle both types of chips.  Or if both drivers
+ *        could handle both types of chips - this one is easier to
+ *        backport to the 2.2 kernel.
+ *     - Get rid of plusb_add_buf_tail and the single spinlock.
+ *        Use a separate spinlock for the 2 lists, and use atomic
+ *        operators for writeurb_submitted and readurb_submitted members.
+ *
+ *
  */
 
 /*****************************************************************************/
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-//#define DEBUG
+//#define DEBUG 1
 #include <linux/usb.h>
 
-#include "plusb.h"
+/* Definitions formerly in plusb.h relocated. No need to export them -EZA */
+
+#define _PLUSB_INTPIPE         0x1
+#define _PLUSB_BULKOUTPIPE     0x2
+#define _PLUSB_BULKINPIPE      0x3
+
+#define _SKB_NUM               32
+
+/* increase size of BULK_DATA_LEN so we can use bigger MTU's*/
+#define _BULK_DATA_LEN         32768
+
+
+typedef struct
+{
+       int connected;   /* indicates if this structure is active */
+       struct usb_device *usbdev;
+                                        /* keep track of USB structure */
+       int status;      /* Prolific status byte returned from interrupt */
+       int in_bh;       /* flag to indicate that we are in the bulk handler */
+       int opened;      /* flag to indicate that network dev is open    */
+
+       spinlock_t lock; /* Lock for the buffer list. re-used for
+                                               locking around submitting the readurb member.
+                                        */
+       urb_t *inturb;   /* Read buffer for the interrupt callback */
+       unsigned char *         interrupt_in_buffer;
+                        /* holds data for the inturb*/
+       urb_t *readurb;  /* Read buffer for the bulk data callback */
+       unsigned char *         bulk_in_buffer;
+                                        /* kmalloc'ed data for the readurb */
+       int readurb_submitted;
+                                        /* Flag to indicate that readurb already sent */
+       urb_t *writeurb; /* Write buffer for the bulk data callback */
+       int writeurb_submitted;
+                                        /* Flag to indicate that writeurb already sent */
+       
+       struct list_head tx_skb_list;
+                                        /* sk_buff's read from net device */
+       struct list_head free_skb_list;
+                                       /* free sk_buff list */
+       struct net_device net_dev;
+                                       /* handle to linux network device */
+       struct net_device_stats net_stats;
+                                       /* stats to return for ifconfig output */
+} plusb_t,*pplusb_t;
+
+/*
+ * skb_list - queue of packets from the network driver to be delivered to USB
+ */
+typedef struct
+{
+       struct list_head skb_list;
+       struct sk_buff *skb;
+       int state;
+       plusb_t *s;
+} skb_list_t,*pskb_list_t;
+
 
 /* --------------------------------------------------------------------- */
 
 #define NRPLUSB 4
 
+/*
+ * Interrupt endpoint status byte, from Prolific PL-2301 docs
+ * Check the 'download' link at www.prolifictech.com
+ */
+#define _PL_INT_RES1    0x80 /* reserved              */
+#define _PL_INT_RES2    0x40 /* reserved              */
+#define _PL_INT_RXD    _PL_INT_RES2  /* Read data ready - Not documented by Prolific, but seems to work! */
+#define _PL_INT_TX_RDY 0x20 /* OK to transmit data   */
+#define _PL_INT_RESET_O        0x10 /* reset output pipe     */
+#define _PL_INT_RESET_I 0x08 /* reset input pipe      */
+#define _PL_INT_TX_C    0x04 /* transmission complete */
+#define _PL_INT_TX_REQ  0x02 /* transmission received */
+#define _PL_INT_PEER_E  0x01 /* peer exists           */
+
 /*-------------------------------------------------------------------*/
 
 static plusb_t plusb[NRPLUSB];
 
+static void plusb_write_bulk_complete(urb_t *purb);
+static void plusb_read_bulk_complete(urb_t *purb);
+static void plusb_int_complete(urb_t *purb);
+
 /* --------------------------------------------------------------------- */
+
+/*
+ * plusb_add_buf_tail - Take the head of the src list and append it to
+ *                      the tail of the dest list
+ */
 static int plusb_add_buf_tail (plusb_t *s, struct list_head *dst, struct list_head *src)
 {
-       unsigned long flags;
+       unsigned long flags = 0;
        struct list_head *tmp;
        int ret = 0;
 
@@ -76,126 +248,227 @@ static int plusb_add_buf_tail (plusb_t *s, struct list_head *dst, struct list_he
 }
 /*-------------------------------------------------------------------*/
 
-static int plusb_my_bulk(plusb_t *s, int pipe, void *data, int size, int *actual_length)
+/*
+ * dequeue_next_skb - submit the first thing on the tx_skb_list to the
+ * USB stack.  This function should be called each time we get a new
+ * message to send to the other host, or each time a message is sucessfully
+ * sent.
+ */
+static void dequeue_next_skb(char * func, plusb_t * s)
 {
-       int ret;
+       skb_list_t * skb_list;
+       unsigned long flags = 0;
 
-       dbg("plusb_my_bulk: len:%d",size);
+       if (!s->connected)
+               return;
+       
+       spin_lock_irqsave (&s->lock, flags);
+       
+       if (!list_empty (&s->tx_skb_list) && !s->writeurb_submitted) {
+               int submit_ret;
+               skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list);
 
-       ret=usb_bulk_msg(s->usbdev, pipe, data, size, actual_length, 500);
-       if(ret<0) {
-               err("plusb: usb_bulk_msg failed(%d)",ret);
+               if (skb_list->skb) {
+                       s->writeurb_submitted = 1;
+               
+                       /* Use the buffer inside the sk_buff directly. why copy? */
+                       FILL_BULK_URB_TO(s->writeurb, s->usbdev,
+                                                        usb_sndbulkpipe(s->usbdev, _PLUSB_BULKOUTPIPE),
+                                                        skb_list->skb->data, skb_list->skb->len,
+                                                        plusb_write_bulk_complete, skb_list, 500);
+                       
+                       dbg ("%s: %s: submitting urb. skb_list %p", s->net_dev.name, func, skb_list);
+               
+                       submit_ret = usb_submit_urb(s->writeurb);
+                       if (submit_ret) {
+                               s->writeurb_submitted = 0;
+                               printk (KERN_CRIT "%s: %s: can't submit writeurb: %d\n",
+                                               s->net_dev.name, func, submit_ret);
+                       }
+               } /* end if the skb value has been filled in */
        }
        
-       if( ret == -EPIPE ) {
-               warn("CLEAR_FEATURE request to remove STALL condition.");
-               if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
-                       err("request failed");
-               }
-
-       dbg("plusb_my_bulk: finished act: %d", *actual_length);         
-       return ret;
+       spin_unlock_irqrestore (&s->lock, flags);       
 }
 
-/* --------------------------------------------------------------------- */
-
-static void plusb_bh(void *context)
+/*
+ * submit_read_urb - re-submit the read URB to the stack
+ */
+void submit_read_urb(char * func, plusb_t * s)
 {
-       plusb_t *s=context;
-       struct net_device_stats *stats=&s->net_stats;
-       int ret=0;
-       int actual_length;
-       skb_list_t *skb_list;
-       struct sk_buff *skb;
-
-       dbg("plusb_bh: i:%d",in_interrupt());
-
-       while(!list_empty(&s->tx_skb_list)) {
+       unsigned long flags=0;
 
-               if(!(s->status&_PLUSB_TXOK))
-                       break; 
-               
-               skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list);
-               if(!skb_list->state) {
-                       dbg("plusb_bh: not yet ready");
-                       schedule();
-                       continue;
-               }
-
-               skb=skb_list->skb;
-               ret=plusb_my_bulk(s, usb_sndbulkpipe (s->usbdev, _PLUSB_BULKOUTPIPE),
-                                 skb->data, skb->len, &actual_length);
+       if (!s->connected)
+               return;
        
-               if(ret || skb->len != actual_length ||!(skb->len%64)) {
-                       plusb_my_bulk(s, usb_sndbulkpipe (s->usbdev, _PLUSB_BULKOUTPIPE),
-                             NULL, 0, &actual_length);
-               }
-
-               if(!ret) {
-                       stats->tx_packets++;
-                       stats->tx_bytes+=skb->len;
-                }
-               else {
-                       stats->tx_errors++;
-                       stats->tx_aborted_errors++;
+       spin_lock_irqsave (&s->lock, flags);
+       
+       if (!s->readurb_submitted) {
+               int ret;
+               s->readurb_submitted=1;
+               s->readurb->dev=s->usbdev;
+               ret = usb_submit_urb(s->readurb);
+               if (ret) {
+                       printk (KERN_CRIT "%s: %s: error %d submitting read URB\n",
+                                  s->net_dev.name, func, ret);
+                       s->readurb_submitted=0;
                }
-
-               dbg("plusb_bh: dev_kfree_skb");
-
-               dev_kfree_skb(skb);
-               skb_list->state=0;
-               plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list);     
        }
 
-       dbg("plusb_bh: finished");
-       s->in_bh=0;
+       spin_unlock_irqrestore (&s->lock, flags);
+       
 }
-
 /* --------------------------------------------------------------------- */
 
+/*
+ * plusb_net_xmit - callback from the network device driver for outgoing data
+ *
+ * Data has arrived to the network device from the local machine and needs
+ * to be sent over the USB cable.  This is in an interrupt, so we don't
+ * want to spend too much time in this function.
+ *
+ */
 static int plusb_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        plusb_t *s=dev->priv;
        skb_list_t *skb_list;
-       int ret=NET_XMIT_SUCCESS;
+       unsigned int flags;
 
        dbg("plusb_net_xmit: len:%d i:%d",skb->len,in_interrupt());
 
-        if(!s->connected || list_empty(&s->free_skb_list)) {
-               ret=NET_XMIT_CN;
-               goto lab;
-       }       
+       if(!s->connected || !s->opened) {
+               /*
+                 NOTE: If we get to this point, you'll return the error
+                 kernel: virtual device plusb0 asks to queue packet
+
+                 Other things we could do:
+                 1) just drop this packet
+                 2) drop other packets in the queue
+               */
+               return 1;
+       }
 
-       plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list);
+       spin_lock_irqsave (&s->lock, flags);
+
+       if  (list_empty(&s->free_skb_list)
+       || plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list)) {
+               /* The buffers on this side are full. DROP the packet
+                  I think that this shouldn't happen with the correct
+                  use of the netif_XXX functions -EZA
+                */
+               dbg ("plusb: Free list is empty.");
+               kfree_skb(skb);
+               s->net_stats.tx_dropped++;
+               spin_unlock_irqrestore (&s->lock, flags);
+               return 0;
+       }
+       
        skb_list = list_entry (s->tx_skb_list.prev, skb_list_t, skb_list);
        skb_list->skb=skb;
        skb_list->state=1;
+       skb_list->s=s;
+
+       if (list_empty(&s->free_skb_list)) {
+               /* apply "backpressure". Tell the net layer to stop sending
+                  the driver packets.
+               */
+               netif_stop_queue(dev);
+       }
+       
+       spin_unlock_irqrestore (&s->lock, flags);
+       
+       /* If there is no write urb outstanding, pull the first thing
+          off of the list and submit it to the USB stack
+       */
+       dequeue_next_skb("plusb_net_xmit", s);
+       
+       return 0;
+}
 
-lab:
-       if(s->in_bh)
-               return ret;
+/* --------------------------------------------------------------------- */
 
-       dbg("plusb_net_xmit: queue_task");
+/*
+ * plusb_write_bulk_complete () - callback after the data has been
+ *   sent to the USB device, or a timeout occured.
+ */
+static void plusb_write_bulk_complete(urb_t *purb)
+{
+       skb_list_t * skb_list=purb->context;
+       plusb_t *s=skb_list->s;
 
-       s->in_bh=1;
-       queue_task(&s->bh, &tq_scheduler);
+       dbg ("%s: plusb_write_bulk_complete: status:%d skb_list:%p\n",
+                s->net_dev.name, purb->status, skb_list);
 
-       dbg("plusb_net_xmit: finished");
-       return ret;
+       skb_list->state=0;
 
-}
+       if( purb->status == -EPIPE ) {
+               
+               printk(KERN_CRIT "%s: plusb_write_bulk_complete: got -EPIPE and don't know what to do!\n",
+                    s->net_dev.name);
+       }
+               
+       if(!purb->status) {
+               s->net_stats.tx_packets++;
+               s->net_stats.tx_bytes+=skb_list->skb->len;
+       }
+       else {
+               err ("%s: plusb_write_bulk_complete: returned ERROR status:%d\n",
+                        s->net_dev.name, purb->status);
 
-/* --------------------------------------------------------------------- */
+               s->net_stats.tx_errors++;
+               s->net_stats.tx_aborted_errors++;
+       }
+       
+       dbg("plusb_bh: dev_kfree_skb");
+
+
+#if (LINUX_VERSION_CODE < 0x020300)
+       dev_kfree_skb(skb_list->skb);
+#else
+       /* NOTE: In 2.4 it's a problem to call dev_kfree_skb() in a hard IRQ:
+          Oct 28 23:42:14 bug kernel: Warning: kfree_skb on hard IRQ c023329a
+       */
+       dev_kfree_skb_any(skb_list->skb);
+#endif
+       
+       skb_list->skb = NULL;
+       if (plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list)) {
+               err ("plusb: tx list empty. This shouldn't happen.");
+       }
+
+       purb->status = 0;
+       s->writeurb_submitted = 0;
+       
+    netif_wake_queue((&s->net_dev));
+       
+       dequeue_next_skb("plusb_write_bulk_complete", s);
+
+       
+}
 
-static void plusb_bulk_complete(urb_t *purb)
+/*
+ * plusb_read_bulk_complete - Callback for data arriving from the USB device
+ *
+ * This gets called back when a full 'urb' is received from the remote system.
+ * This urb was allocated by this driver and is kept in the member: s->readurb
+ *
+ */
+static void plusb_read_bulk_complete(urb_t *purb)
 {
+       
        plusb_t *s=purb->context;
 
-       dbg("plusb_bulk_complete: status:%d length:%d",purb->status,purb->actual_length);
+       dbg("plusb_read_bulk_complete: status:%d length:%d", purb->status,purb->actual_length);
+       
        if(!s->connected)
                return;
 
-       if( !purb->status) {
+       if( purb->status == -EPIPE ) {
+               
+               printk(KERN_CRIT "%s: plusb_read_bulk_complete: got -EPIPE and I don't know what to do!\n",
+                    s->net_dev.name);
+               
+       } else if (!purb->status) {
                struct sk_buff *skb;
                unsigned char *dst;
                int len=purb->transfer_buffer_length;
@@ -204,31 +477,69 @@ static void plusb_bulk_complete(urb_t *purb)
                skb=dev_alloc_skb(len);
 
                if(!skb) {
-                       err("plusb_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame",len);
+                       printk (KERN_CRIT "%s: plusb_read_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame\n", s->net_dev.name, len);
                        stats->rx_dropped++;
-                       return;
+               } else {
+                       dst=(char *)skb_put(skb, len);
+                       memcpy( dst, purb->transfer_buffer, len);
+                       
+                       skb->dev=&s->net_dev;
+                       skb->protocol=eth_type_trans(skb, skb->dev);
+                       stats->rx_packets++;
+                       stats->rx_bytes+=len;
+                       netif_rx(skb);
                }
+               
+       }
+       
+       s->readurb_submitted = 0;
+       
+       if (purb->status) {
+               /* Give the system a chance to "catch its breath". Shortcut
+                  re-submitting the read URB>  It will be re-submitted if
+                  another interrupt comes back.  The problem scenario is that
+                  the plub is pulled and the read returns an error.
+                  You don't want to resumbit in this case.
+               */
+               err ("%s: plusb_read_bulk_complete: returned status %d\n",
+                        s->net_dev.name, purb->status);
+               return;
+       }
 
-               dst=(char *)skb_put(skb, len);
-               memcpy( dst, purb->transfer_buffer, len);
 
-               skb->dev=&s->net_dev;
-               skb->protocol=eth_type_trans(skb, skb->dev);
-               stats->rx_packets++;
-               stats->rx_bytes+=len;
-               netif_rx(skb);
-       }
-       else
-               purb->status=0;
+       purb->status=0;
+
+       /* Keep it coming! resubmit the URB for reading.. Make sure
+          we aren't in contention with the interrupt callback.
+       */
+       submit_read_urb("plusb_read_bulk_complete", s);
 }
 
 /* --------------------------------------------------------------------- */
-
+/*
+ * plusb_int_complete - USB driver callback for interrupt msg from the device
+ *
+ * Interrupts are scheduled to go off on a periodic basis (see FILL_INT_URB)
+ * For the prolific device, this is basically just returning a register
+ * filled with bits.  See the macro definitions for _PL_INT_XXX above.
+ * Most of these bits are for implementing a machine-machine protocol
+ * and can be set with a special message (described as the "Quicklink"
+ * feature in the prolific documentation.)
+ *
+ * I don't think we need any of that to work as a network device. If a
+ * message is lost, big deal - that's what UNIX networking expects from
+ * the physical layer.
+ *
+ */
 static void plusb_int_complete(urb_t *purb)
 {
        plusb_t *s=purb->context;
        s->status=((unsigned char*)purb->transfer_buffer)[0]&255;
+       
 #if 0
+       /* This isn't right because 0x20 is TX_RDY and
+          sometimes will not be set
+       */
        if((s->status&0x3f)!=0x20) {
                warn("invalid device status %02X", s->status);
                return;
@@ -237,67 +548,95 @@ static void plusb_int_complete(urb_t *purb)
        if(!s->connected)
                return;
 
-       if(s->status&_PLUSB_RXD) {
-               int ret;
-               
-               if(s->bulkurb->status) {
-                       err("plusb_int_complete: URB still in use");
-                       return;
-               }
-               
-               s->bulkurb->dev = s->usbdev;
-               ret=usb_submit_urb(s->bulkurb);
-               if(ret && ret!=-EBUSY) {
-                       err("plusb_int_complete: usb_submit_urb failed");
-               }
-       }
-               
-       if(purb->status || s->status!=160)
-               dbg("status: %p %d buf: %02X", purb->dev, purb->status, s->status);
+       /* Don't turn this on unless you want to see the log flooded. */
+#if 0
+       printk("plusb_int_complete: PEER_E:%d TX_REQ:%d TX_C:%d RESET_IN:%d RESET_O: %d TX_RDY:%d RES1:%d RES2:%d\n",
+           s->status & _PL_INT_PEER_E  ? 1 : 0,
+           s->status & _PL_INT_TX_REQ  ? 1 : 0,
+           s->status & _PL_INT_TX_C    ? 1 : 0,
+           s->status & _PL_INT_RESET_I ? 1 : 0,
+           s->status & _PL_INT_RESET_O ? 1 : 0,
+           s->status & _PL_INT_TX_RDY  ? 1 : 0,
+           s->status & _PL_INT_RES1    ? 1 : 0,
+           s->status & _PL_INT_RES2    ? 1 : 0);
+#endif
+
+#if 1
+       /* At first glance, this logic appears to not really be needed, but
+          it can help recover from intermittent problems where the
+          usb_submit_urb() fails in the read callback. -EZA
+       */
+       
+       /* Try to submit the read URB again. Make sure
+          we aren't in contention with the bulk read callback
+       */
+       submit_read_urb ("plusb_int_complete", s);
+       
+       /* While we are at it, why not check to see if the
+          write urb should be re-submitted?
+       */
+       dequeue_next_skb("plusb_int_complete", s);      
+       
+#endif
+
 }
 
 /* --------------------------------------------------------------------- */
-
+/*
+ * plusb_free_all - deallocate all memory kept for an instance of the device.
+ */
 static void plusb_free_all(plusb_t *s)
 {
        struct list_head *skb;
        skb_list_t *skb_list;
        
        dbg("plusb_free_all");
+       
+       /* set a flag to tell all callbacks to cease and desist */
+       s->connected = 0;
+
+       /* If the interrupt handler is about to fire, let it finish up */
        run_task_queue(&tq_immediate);  
 
        if(s->inturb) {
                dbg("unlink inturb");
                usb_unlink_urb(s->inturb);
-       }
-
-       if(s->inturb && s->inturb->transfer_buffer) {
-               dbg("kfree inturb->transfer_buffer");
-               kfree(s->inturb->transfer_buffer);
-               s->inturb->transfer_buffer=NULL;
-       }
-       
-       if(s->inturb) {
                dbg("free_urb inturb");
                usb_free_urb(s->inturb);
                s->inturb=NULL;
        }
+       
+       if(s->interrupt_in_buffer) {
+               dbg("kfree s->interrupt_in_buffer");
+               kfree(s->interrupt_in_buffer);
+               s->interrupt_in_buffer=NULL;
+       }
 
-       if(s->bulkurb) {
-               dbg("unlink bulkurb");
-               usb_unlink_urb(s->bulkurb);
+       if(s->readurb) {
+               dbg("unlink readurb");
+               usb_unlink_urb(s->readurb);
+               dbg("free_urb readurb:");
+               usb_free_urb(s->readurb);
+               s->readurb=NULL;
        }
-       
-       if(s->bulkurb && s->bulkurb->transfer_buffer) {
-               dbg("kfree bulkurb->transfer_buffer");
-               kfree(s->bulkurb->transfer_buffer);
-               s->bulkurb->transfer_buffer=NULL;
+
+       if(s->bulk_in_buffer) {
+               dbg("kfree s->bulk_in_buffer");
+               kfree(s->bulk_in_buffer);
+               s->bulk_in_buffer=NULL;
        }
-       if(s->bulkurb) {
-               dbg("free_urb bulkurb");
-               usb_free_urb(s->bulkurb);
-               s->bulkurb=NULL;
+       
+       s->readurb_submitted = 0;
+       
+       if(s->writeurb) {
+               dbg("unlink writeurb");
+               usb_unlink_urb(s->writeurb);
+               dbg("free_urb writeurb:");
+               usb_free_urb(s->writeurb);
+               s->writeurb=NULL;
        }
+
+       s->writeurb_submitted = 0;
        
        while(!list_empty(&s->free_skb_list)) {
                skb=s->free_skb_list.next;
@@ -310,20 +649,34 @@ static void plusb_free_all(plusb_t *s)
                skb=s->tx_skb_list.next;
                list_del(skb);
                skb_list = list_entry (skb, skb_list_t, skb_list);
-               kfree(skb_list);        
+               if (skb_list->skb) {
+                       dbg ("Freeing SKB in queue");
+#if (LINUX_VERSION_CODE < 0x020300)
+                       dev_kfree_skb(skb_list->skb);
+#else
+                       dev_kfree_skb_any(skb_list->skb);
+#endif
+                       skb_list->skb = NULL;
+               }
+               kfree(skb_list);
        }
+       
+       s->in_bh=0;
+       
        dbg("plusb_free_all: finished");        
 }
 
 /*-------------------------------------------------------------------*/
-
+/*
+ * plusb_alloc - allocate memory associated with one instance of the device
+ */
 static int plusb_alloc(plusb_t *s)
 {
        int i;
        skb_list_t *skb;
 
        dbg("plusb_alloc");
-       
+
        for(i=0 ; i < _SKB_NUM ; i++) {
                skb=kmalloc(sizeof(skb_list_t), GFP_KERNEL);
                if(!skb) {
@@ -341,47 +694,63 @@ static int plusb_alloc(plusb_t *s)
                goto reject;
        }
 
-       dbg("bulkurb allocation:");     
-       s->bulkurb=usb_alloc_urb(0);
-       if(!s->bulkurb) {
+       dbg("bulk read urb allocation:");
+       s->readurb=usb_alloc_urb(0);
+       if(!s->readurb) {
                err("alloc_urb failed");
                goto reject;
        }
        
-       dbg("bulkurb/inturb init:");
-       s->inturb->dev=s->usbdev;
-       s->inturb->pipe=usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE);
-       s->inturb->transfer_buffer=kmalloc(64, GFP_KERNEL);
-       if(!s->inturb->transfer_buffer) {
-               err("kmalloc failed");
+       dbg("bulk write urb allocation:");
+       s->writeurb=usb_alloc_urb(0);
+       if(!s->writeurb) {
+               err("alloc_urb for writeurb failed");
                goto reject;
        }
        
-       s->inturb->transfer_buffer_length=1;
-       s->inturb->complete=plusb_int_complete;
-       s->inturb->context=s;
-       s->inturb->interval=10;
+       dbg("readurb/inturb init:");
+       s->interrupt_in_buffer=kmalloc(64, GFP_KERNEL);
+       if(!s->interrupt_in_buffer) {
+               err("kmalloc failed");
+               goto reject;
+       }
+
+       /* The original value of '10' makes this interrupt fire off a LOT.
+          It was set so low because the callback determined when to
+          sumbit the buld read URB. I've lowered it to 100 - the driver
+          doesn't depend on that logic anymore. -EZA
+       */
+       FILL_INT_URB(s->inturb, s->usbdev,
+                    usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE),
+                    s->interrupt_in_buffer, 1,
+                    plusb_int_complete, s, HZ);
 
        dbg("inturb submission:");
        if(usb_submit_urb(s->inturb)<0) {
                err("usb_submit_urb failed");
                goto reject;
        }
-
-       dbg("bulkurb init:");
-       s->bulkurb->dev=s->usbdev;
-       s->bulkurb->pipe=usb_rcvbulkpipe (s->usbdev, _PLUSB_BULKINPIPE);
-       s->bulkurb->transfer_buffer=kmalloc(_BULK_DATA_LEN, GFP_KERNEL);
-       if(!s->bulkurb->transfer_buffer) {
-               err("kmalloc failed");
-               goto reject;
-       }
-       
-       s->bulkurb->transfer_buffer_length=_BULK_DATA_LEN;
-       s->bulkurb->complete=plusb_bulk_complete;
-       s->bulkurb->context=s;
        
-       dbg("plusb_alloc: finished");
+       dbg("readurb init:");
+       s->bulk_in_buffer = kmalloc(_BULK_DATA_LEN, GFP_KERNEL);
+       if (!s->bulk_in_buffer) {
+               err("kmalloc %d bytes for bulk in buffer failed", _BULK_DATA_LEN);
+       }
+
+       FILL_BULK_URB(s->readurb, s->usbdev,
+                     usb_rcvbulkpipe(s->usbdev, _PLUSB_BULKINPIPE),
+                     s->bulk_in_buffer, _BULK_DATA_LEN,
+                     plusb_read_bulk_complete, s);
+
+       /* The write urb will be initialized inside the network
+          interrupt.
+       */
+
+       /* get the bulk read going */
+       submit_read_urb("plusb_alloc", s);
+
+       dbg ("plusb_alloc: finished. readurb=%p writeurb=%p inturb=%p",
+               s->readurb, s->writeurb, s->inturb);
        
        return 0;
 
@@ -404,8 +773,11 @@ static int plusb_net_open(struct net_device *dev)
                return -ENOMEM;
 
        s->opened=1;
-       MOD_INC_USE_COUNT;
        
+       MOD_INC_USE_COUNT;
+
+       netif_start_queue(dev);
+
        dbg("plusb_net_open: success");
        
        return 0;
@@ -417,11 +789,14 @@ static int plusb_net_open(struct net_device *dev)
 static int plusb_net_stop(struct net_device *dev)
 {
        plusb_t *s=dev->priv;
+
+       netif_stop_queue(dev);
        
        dbg("plusb_net_stop");  
        
-       plusb_free_all(s);
        s->opened=0;
+       plusb_free_all(s);
+
        MOD_DEC_USE_COUNT;
        dbg("plusb_net_stop:finished");
        return 0;
@@ -459,7 +834,6 @@ static void plusb_disconnect (struct usb_device *usbdev, void *ptr)
        plusb_t *s = ptr;
 
        dbg("plusb_disconnect");
-       s->connected = 0;
        
        plusb_free_all(s);
 
@@ -467,6 +841,11 @@ static void plusb_disconnect (struct usb_device *usbdev, void *ptr)
                dbg("unregistering netdev: %s",s->net_dev.name);
                unregister_netdev(&s->net_dev);
                s->net_dev.name[0] = '\0';
+#if (LINUX_VERSION_CODE < 0x020300)
+               dbg("plusb_disconnect: About to free name");
+               kfree (s->net_dev.name);
+               s->net_dev.name = NULL;
+#endif 
        }
        
        dbg("plusb_disconnect: finished");
@@ -475,6 +854,22 @@ static void plusb_disconnect (struct usb_device *usbdev, void *ptr)
 
 /* --------------------------------------------------------------------- */
 
+static int plusb_change_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < 68) || (new_mtu > _BULK_DATA_LEN))
+               return -EINVAL;
+
+       printk("plusb: changing mtu to %d\n", new_mtu);
+       dev->mtu = new_mtu;
+       
+       /* NOTE: Could we change the size of the READ URB here dynamically
+          to save kernel memory?
+       */
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
 int plusb_net_init(struct net_device *dev)
 {
        dbg("plusb_net_init");
@@ -484,7 +879,14 @@ int plusb_net_init(struct net_device *dev)
        dev->hard_start_xmit=plusb_net_xmit;
        dev->get_stats  = plusb_net_get_stats;
        ether_setup(dev);
-       dev->tx_queue_len = 0;
+       dev->change_mtu = plusb_change_mtu;
+       /* Setting the default MTU to 16K gives good performance for
+          me, and keeps the ping latency low too.  Setting it up
+          to 32K made performance go down. -EZA
+          Pavel says it would be best not to do this...
+       */
+       /*dev->mtu=16384; */
+       dev->tx_queue_len = 0;  
        dev->flags = IFF_POINTOPOINT|IFF_NOARP;
 
        
@@ -524,6 +926,42 @@ static void *plusb_probe (struct usb_device *usbdev, unsigned int ifnum)
                return NULL;
        }
 
+#if (LINUX_VERSION_CODE < 0x020300)
+       {
+               int i;
+               
+               /* For Kernel version 2.2, the driver is responsible for
+                  allocating this memory. For version 2.4, the rules
+                  have apparently changed, but there is a nifty function
+                  'init_netdev' that might make this easier...  It's in 
+                  ../net/net_init.c - but can we get there from here?  (no)
+                  -EZA
+               */
+               
+               /* Find the device number... we seem to have lost it... -EZA */
+               for (i=0; i<NRPLUSB; i++) {
+                       if (&plusb[i] == s)
+                               break;
+               }
+       
+               if(!s->net_dev.name) {
+                       s->net_dev.name = kmalloc(strlen("plusbXXXX"), GFP_KERNEL);
+                       sprintf (s->net_dev.name, "plusb%d", i);
+                       s->net_dev.init=plusb_net_init;
+                       s->net_dev.priv=s;
+                       
+                       printk ("plusb_probe: Registering Device\n");   
+                       if(!register_netdev(&s->net_dev))
+                               info("registered: %s", s->net_dev.name);
+                       else {
+                               err("register_netdev failed");
+                               s->net_dev.name[0] = '\0';
+                       }
+                       dbg ("plusb_probe: Connected!");
+               }
+       }
+#else
+       /* Kernel version 2.3+ works a little bit differently than 2.2 */
        if(!s->net_dev.name[0]) {
                strcpy(s->net_dev.name, "plusb%d");
                s->net_dev.init=plusb_net_init;
@@ -535,7 +973,8 @@ static void *plusb_probe (struct usb_device *usbdev, unsigned int ifnum)
                        s->net_dev.name[0] = '\0';
                }
        }
-               
+#endif
+       
        s->connected = 1;
 
        if(s->opened) {
@@ -567,8 +1006,6 @@ static int __init plusb_init (void)
        for (u = 0; u < NRPLUSB; u++) {
                plusb_t *s = &plusb[u];
                memset (s, 0, sizeof (plusb_t));
-               s->bh.routine = (void (*)(void *))plusb_bh;
-               s->bh.data = s;
                INIT_LIST_HEAD (&s->tx_skb_list);
                INIT_LIST_HEAD (&s->free_skb_list);
                spin_lock_init (&s->lock);
@@ -591,10 +1028,21 @@ static void __exit plusb_cleanup (void)
        dbg("plusb_cleanup");
        for (u = 0; u < NRPLUSB; u++) {
                plusb_t *s = &plusb[u];
+#if (LINUX_VERSION_CODE < 0x020300)
+               if(s->net_dev.name) {
+                       dbg("unregistering netdev: %s",s->net_dev.name);
+                       unregister_netdev(&s->net_dev);
+                       s->net_dev.name[0] = '\0';
+                       kfree (s->net_dev.name);
+                       s->net_dev.name = NULL;         
+               }               
+#else
                if(s->net_dev.name[0]) {
                        dbg("unregistering netdev: %s",s->net_dev.name);
                        unregister_netdev(&s->net_dev);
+                       s->net_dev.name[0] = '\0';
                }
+#endif
        }
        usb_deregister (&plusb_driver);
        dbg("plusb_cleanup: finished");
diff --git a/drivers/usb/plusb.h b/drivers/usb/plusb.h
deleted file mode 100644 (file)
index a77ae0f..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#define _PLUSB_INTPIPE         0x1
-#define _PLUSB_BULKOUTPIPE     0x2
-#define _PLUSB_BULKINPIPE      0x3
-
-#define _SKB_NUM               1000
-//  7  6  5  4  3  2  1  0
-//  tx rx 1  0
-// 1110 0000 rxdata
-// 1010 0000 idle
-// 0010 0000 tx over
-// 0110      tx over + rxd
-
-#define _PLUSB_RXD             0x40
-#define _PLUSB_TXOK            0x80
-
-#ifdef __KERNEL__
-#define _BULK_DATA_LEN         16384
-
-typedef struct
-{
-       struct list_head skb_list;
-       struct sk_buff *skb;
-       int state;
-} skb_list_t,*pskb_list_t;
-
-typedef struct
-{
-       struct usb_device *usbdev;
-
-       int status;
-       int connected;
-       int in_bh;
-       int opened;
-
-       spinlock_t lock;
-
-       urb_t *inturb;
-       urb_t *bulkurb; 
-
-       struct list_head tx_skb_list;
-       struct list_head free_skb_list;
-       struct tq_struct bh;
-
-       struct net_device net_dev;
-       struct net_device_stats net_stats;
-} plusb_t,*pplusb_t;
-
-#endif
index 7e59346aa0ceedbcfe4ef1f8d515d894f9c23ff6..a37a71f753ee6a76f89976fb45d22736ed924451 100644 (file)
@@ -968,6 +968,11 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
 }
 
 /*-------------------------------------------------------------------*/
+/* usb_control_msg() -  builds control urb, and waits for completion */
+/* Synchronous behavior - don't use this function  from within an    */
+/* interrupt context, (like a bottom half handler.)  In this case,   */
+/* use usb_submit_urb() directly instead.                            */
+
 int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
                         __u16 value, __u16 index, void *data, __u16 size, int timeout)
 {
@@ -993,8 +998,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
 }
 
 /*-------------------------------------------------------------------*/
-/* compatibility wrapper, builds bulk urb, and waits for completion */
-/* synchronous behavior */
+/* usb_bulk_msg() Builds a bulk urb, and waits for completion.       */
+/* Synchronous behavior - don't use this function  from within an    */
+/* interrupt context, (like a bottom half handler.)  In this case,   */
+/* use usb_submit_urb() directly instead.                            */
 
 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
                        void *data, int len, int *actual_length, int timeout)
index 688f576cfecc5fa056a2588483029a5d5bf65eb8..331343d15799dd96c0d161dd62bbd4e1092b6024 100644 (file)
@@ -89,7 +89,6 @@ obj-$(CONFIG_FB_TCX)              += tcxfb.o sbusfb.o
 obj-$(CONFIG_FB_CGFOURTEEN)       += cgfourteenfb.o sbusfb.o
 obj-$(CONFIG_FB_P9100)            += p9100fb.o sbusfb.o
 obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
-obj-$(CONFIG_FB_SIS)              += sisfb.o
 
 ifeq ($(CONFIG_FB_MATROX),y)
 SUB_DIRS                         += matrox
@@ -110,6 +109,16 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_FB_SIS),y)
+SUB_DIRS                         += sis
+obj-y                            += sis/sisfb.o
+else
+  ifeq ($(CONFIG_FB_SIS),m)
+  MOD_SUB_DIRS                   += sis
+  endif
+endif
+
+
 obj-$(CONFIG_FB_SUN3)             += sun3fb.o
 obj-$(CONFIG_FB_BWTWO)            += bwtwofb.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o  
diff --git a/drivers/video/sis/Makefile b/drivers/video/sis/Makefile
new file mode 100644 (file)
index 0000000..2e657f1
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the SiS framebuffer device driver
+#
+
+O_TARGET := sisfb.o
+O_OBJS   := sis_main.o sis_300.o sis_301.o
+#O_OBJS   := sis_300.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
+
+
diff --git a/drivers/video/sis/initdef.h b/drivers/video/sis/initdef.h
new file mode 100644 (file)
index 0000000..e0ab914
--- /dev/null
@@ -0,0 +1,138 @@
+#include "sis.h"
+
+#define PRIMARY_VGA      1     //1: SiS is primary vga 0:SiS is secondary vga 
+#define ModeInfoFlag      0x07
+#define MemoryInfoFlag    0x1E0
+#define MemorySizeShift   0x05
+#define ModeText          0x00
+#define ModeCGA           0x01
+#define ModeEGA           0x02
+#define ModeVGA           0x03
+#define Mode15Bpp         0x04
+#define Mode16Bpp         0x05
+#define Mode24Bpp         0x06
+#define Mode32Bpp         0x07
+#define CRT1Len           17
+#define DoubleScanMode    0x8000
+#define ADR_CRT2PtrData   0x20E //address of CRT2PtrData in ROM image 
+#define offset_Zurac      0x210
+#define ADR_LVDSDesPtrData      0x212
+#define ADR_LVDSCRT1DataPtr     0x214
+
+#define SoftDRAMType      0x80  //5/19/2000,Mars,for soft setting dram type
+#define SoftSettingAddr   0x52 
+#define ModeSettingAddr   0x53
+
+#define InterlaceMode     0x80
+#define HalfDCLK          0x1000
+#define DACInfoFlag       0x18
+#define LineCompareOff    0x400
+#define ActivePAL        0x20
+#define ActivePALShift   5
+
+                
+#define SelectCRT2Rate          0x4
+#define ProgrammingCRT2         0x1
+#define CRT2DisplayFlag         0x2000
+#define SetCRT2ToRAMDAC         0x0040
+#define Charx8Dot               0x0200
+#define LCDDataLen              8
+#define SetCRT2ToLCD            0x0020
+#define SetCRT2ToHiVisionTV     0x0080
+#define HiTVDataLen             12
+#define TVDataLen               16
+#define SetPALTV                0x0100
+#define SetInSlaveMode          0x0200
+#define SetCRT2ToTV             0x009C
+#define SetNotSimuTVMode        0x0400
+#define SetSimuScanMode         0x0001
+#define DriverMode              0x4000
+#define CRT2Mode                0x0800
+//#define ReIndexEnhLCD           4
+#define HalfDCLK                0x1000
+//#define HiVisionTVHT            2100
+//#define HiVisionTVVT            2100
+#define NTSCHT                  1716
+#define NTSCVT                  525
+#define PALHT                   1728
+#define PALVT                   625
+
+#define VCLKStartFreq           25      
+//Freq of first item in VCLKTable 
+
+#define SoftDramType            0x80
+#define VCLK65                  0x09
+#define VCLK108_2               0x14
+//#define LCDIs1280x1024Panel     0x04
+//#define HiVisionVCLK            0x22
+#define TVSimuMode              0x02
+#define SetCRT2ToSVIDEO         0x08
+//#define LCDRGB18Bit             0x20
+#define LCDRGB18Bit             0x01
+#define Panel1280x1024          0x03
+#define Panel1024x768           0x02
+#define Panel800x600            0x01
+#define RPLLDIV2XO              0x04 
+#define LoadDACFlag             0x1000
+#define AfterLockCRT2           0x4000
+#define SupportRAMDAC2          0x0040
+#define SupportLCD              0x0020
+//#define Support1024x768LCD      0x0020
+//#define Support1280x1024LCD     0x0040
+#define SetCRT2ToAVIDEO         0x0004
+#define SetCRT2ToSCART          0x0010
+//#define NoSupportSimuTV         0x0100
+#define NoSupportSimuTV         0x2000
+#define Ext2StructSize          5
+#define SupportTV               0x0008
+//#define TVVCLKDIV2              0x020
+//#define TVVCLK                  0x021
+#define TVVCLKDIV2              0x021
+#define TVVCLK                  0x022
+#define SwitchToCRT2            0x0002
+#define LCDVESATiming           0x08
+#define SetSCARTOutput          0x01
+#define SCARTSense              0x04
+#define Monitor1Sense           0x20
+#define Monitor2Sense           0x10
+#define SVIDEOSense             0x02
+#define AVIDEOSense             0x01
+#define LCDSense                0x08
+#define BoardTVType             0x02
+#define HotPlugFunction         0x08
+#define StStructSize            0x06
+
+#define ExtChip301              0x02
+#define ExtChipLVDS             0x04
+#define ExtChipTrumpion         0x06
+#define LCDNonExpanding         0x10
+#define LCDNonExpandingShift    4
+#define LVDSDataLen             6
+#define EnableLVDSDDA           0x10
+#define LCDSync                 0x20
+#define SyncPP                  0x0000
+#define LCDSyncBit              0xE0
+#define LVDSDesDataLen          3
+#define LVDSCRT1Len             15
+#define ActiveNonExpanding     0x40
+#define ActiveNonExpandingShift        6
+#define ModeSwitchStatus       0x0F
+#define SoftTVType             0x40
+       
+#define PanelType00             0x00    
+#define PanelType01             0x08
+#define PanelType02             0x10
+#define PanelType03             0x18
+#define PanelType04             0x20
+#define PanelType05             0x28
+#define PanelType06             0x30
+#define PanelType07             0x38
+#define PanelType08             0x40
+#define PanelType09             0x48
+#define PanelType0A             0x50
+#define PanelType0B             0x58
+#define PanelType0C             0x60
+#define PanelType0D             0x68
+#define PanelType0E             0x70
+#define PanelType0F             0x78
+
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
new file mode 100644 (file)
index 0000000..3f4843a
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _SISFB_LOCAL
+#define _SISFB_LOCAL
+#include <linux/types.h>
+
+#undef NOBIOS
+#undef CONFIG_FB_SIS_LINUXBIOS
+
+#ifdef NOBIOS
+#undef CONFIG_FB_SIS_LINUXBIOS
+#endif
+
+#define TRUE  1
+#define FALSE 0
+#define NO_ERROR 0
+
+/* Data type conversion */
+#define UCHAR   unsigned char
+#define USHORT  unsigned short
+#define ULONG   unsigned long
+#define SHORT   short
+#define BOOLEAN int
+#define VOID void
+
+#define IND_SIS_CRT2_PORT_04        0x04 - 0x30
+#define IND_SIS_CRT2_PORT_10        0x10 - 0x30
+#define IND_SIS_CRT2_PORT_12        0x12 - 0x30
+#define IND_SIS_CRT2_PORT_14        0x14 - 0x30
+
+#define ClearALLBuffer(x)  ClearBuffer(x)
+
+/* Data struct for setmode codes */
+typedef enum _CHIP_TYPE {
+    SIS_GENERIC = 0,
+    SIS_Glamour,       //300
+    SIS_Trojan,                //630
+    SIS_Spartan,       //540
+    SIS_730,
+    MAX_SIS_CHIP
+} CHIP_TYPE;
+
+typedef enum _LCD_TYPE {
+    LCD1024 = 1,
+    LCD1280,
+    LCD2048,
+    LCD1920,
+    LCD1600,
+    LCD800,
+    LCD640
+} LCD_TYPE;
+
+
+typedef struct _HW_DEVICE_EXTENSION
+{
+       unsigned long VirtualRomBase;
+       char *VirtualVideoMemoryAddress;
+       unsigned short IOAddress;
+       CHIP_TYPE jChipID;
+       int bIntegratedMMEnabled;
+       LCD_TYPE usLCDType;
+       u8 revision_id;
+       u8 uVBChipID;
+} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
+
+#endif
diff --git a/drivers/video/sis/sis_300.c b/drivers/video/sis/sis_300.c
new file mode 100644 (file)
index 0000000..3a3a223
--- /dev/null
@@ -0,0 +1,1523 @@
+/* Recently Update by v1.09.50 */
+#include "sis_300.h"
+
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(PAGE,SiSSetMode)
+#pragma alloc_text(PAGE,SiSInit300)
+#endif
+
+
+#ifdef NOBIOS
+BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       ULONG   ROMAddr  = (ULONG)HwDeviceExtension->VirtualRomBase;
+       ULONG   FBAddr  = (ULONG)HwDeviceExtension->VirtualVideoMemoryAddress;
+       USHORT  BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
+       UCHAR   i,temp,AGP;
+       ULONG   j,k,ulTemp;
+       UCHAR   SR07,SR11,SR19,SR1A,SR1F,SR21,SR22,SR23,SR24,SR25,SR32;
+       UCHAR   SR14;
+       ULONG   Temp;
+
+       if(ROMAddr==0)  return (FALSE);
+       if(FBAddr==0)    return (FALSE);
+       if(BaseAddr==0)  return (FALSE);
+       if(HwDeviceExtension->jChipID >= SIS_Trojan)
+               if(!HwDeviceExtension->bIntegratedMMEnabled)  return (FALSE);
+
+       P3c4=BaseAddr+0x14;
+       P3d4=BaseAddr+0x24;
+       P3c0=BaseAddr+0x10;
+       P3ce=BaseAddr+0x1e;
+       P3c2=BaseAddr+0x12;
+       P3ca=BaseAddr+0x1a;
+       P3c6=BaseAddr+0x16;
+       P3c7=BaseAddr+0x17;
+       P3c8=BaseAddr+0x18;
+       P3c9=BaseAddr+0x19;
+       P3da=BaseAddr+0x2A;
+       Set_LVDS_TRUMPION();
+
+       SetReg1(P3c4,0x05,0x86);        // 1.Openkey
+       SR14 = (UCHAR)GetReg1(P3c4,0x14);
+       SR19 = (UCHAR)GetReg1(P3c4,0x19);
+       SR1A = (UCHAR)GetReg1(P3c4,0x1A);
+       for(i=0x06;i< 0x20;i++) SetReg1(P3c4,i,0);      // 2.Reset Extended register
+       for(i=0x21;i<=0x27;i++) SetReg1(P3c4,i,0);      //      Reset Extended register
+       for(i=0x31;i<=0x3D;i++) SetReg1(P3c4,i,0);
+       for(i=0x30;i<=0x37;i++) SetReg1(P3d4,i,0);
+
+       if(HwDeviceExtension->jChipID >= SIS_Trojan)
+               temp=(UCHAR)SR1A;               // 3.Set Define Extended register
+       else
+       {
+               temp=*((UCHAR *)(ROMAddr+SoftSettingAddr));
+               if((temp&SoftDRAMType)==0){                                     
+                       temp=(UCHAR)GetReg1(P3c4,0x3A); // 3.Set Define Extended register
+               }
+       } 
+       RAMType=temp&0x07;
+       SetMemoryClock(ROMAddr);
+       for(k=0; k<5; k++)
+       {
+               for(j=0; j<0xffff; j++)
+               {
+                       ulTemp = (ULONG)GetReg1(P3c4, 0x05);
+               }
+       }
+       Temp = (ULONG)GetReg1(P3c4, 0x3C);
+       Temp = Temp | 0x01;
+       SetReg1(P3c4, 0x3C, (USHORT)Temp);
+       for(k=0; k<5; k++)
+       {
+               for(j=0; j<0xffff; j++)
+               {
+                       Temp = (ULONG)GetReg1(P3c4, 0x05);
+               }
+       }
+       Temp = (ULONG)GetReg1(P3c4, 0x3C);
+       Temp = Temp & 0xFE;
+       SetReg1(P3c4, 0x3C, (USHORT)Temp);
+       for(k=0; k<5; k++)
+       {
+               for(j=0; j<0xffff; j++)
+               {
+                       Temp = (ULONG)GetReg1(P3c4, 0x05);
+               }
+       }
+
+       SR07=*((UCHAR *)(ROMAddr+0xA4));
+       SetReg1(P3c4,0x07,SR07);
+       if (HwDeviceExtension->jChipID == SIS_Glamour )
+       {
+               for(i=0x15;i<=0x1C;i++) 
+               {
+                       temp=*((UCHAR *)(ROMAddr+0xA5+((i-0x15)*8)+RAMType));
+                       SetReg1(P3c4,i,temp);
+               }
+       }
+
+       SR1F=*((UCHAR *)(ROMAddr+0xE5));
+       SetReg1(P3c4,0x1F,SR1F);
+
+       AGP=1;                                                  // Get AGP
+       temp=(UCHAR)GetReg1(P3c4,0x3A);
+       temp=temp&0x30;
+       if(temp==0x30) AGP=0;                   // PCI
+
+       SR21=*((UCHAR *)(ROMAddr+0xE6));
+       if(AGP==0) SR21=SR21&0xEF;              // PCI
+       SetReg1(P3c4,0x21,SR21);
+
+       SR22=*((UCHAR *)(ROMAddr+0xE7));
+       if(AGP==1) SR22=SR22&0x20;              // AGP
+       SetReg1(P3c4,0x22,SR22);
+
+       SR23=*((UCHAR *)(ROMAddr+0xE8));
+       SetReg1(P3c4,0x23,SR23);
+
+       SR24=*((UCHAR *)(ROMAddr+0xE9));
+       SetReg1(P3c4,0x24,SR24);
+
+       SR25=*((UCHAR *)(ROMAddr+0xEA));
+       SetReg1(P3c4,0x25,SR25);
+
+       SR32=*((UCHAR *)(ROMAddr+0xEB));
+       SetReg1(P3c4,0x32,SR32);
+
+       SR11=0x0F;
+       SetReg1(P3c4,0x11,SR11);
+
+       if(IF_DEF_LVDS==1){                             //LVDS
+               temp=ExtChipLVDS;
+       }else if(IF_DEF_TRUMPION==1){   //Trumpion
+               temp=ExtChipTrumpion;
+       }else{                  //301
+               temp=ExtChip301;
+       }
+       SetReg1(P3d4,0x37,temp);
+
+       //For SiS 630/540 Chip
+       //Restore SR14, SR19 and SR1A
+       SetReg1(P3c4,0x14,SR14);
+       SetReg1(P3c4,0x19,SR19);
+       SetReg1(P3c4,0x1A,SR1A);
+
+       SetReg3(P3c6,0xff);             // Reset register
+       ClearDAC(P3c8);                 // Reset register
+       DetectMonitor(HwDeviceExtension);        //sense CRT1
+       GetSenseStatus(HwDeviceExtension,BaseAddr,ROMAddr);//sense CRT2         
+       
+       return(TRUE);
+}
+
+VOID Set_LVDS_TRUMPION(VOID)
+{
+       IF_DEF_LVDS=0;
+       IF_DEF_TRUMPION=0;       
+}
+
+VOID SetMemoryClock(ULONG ROMAddr)
+{
+       UCHAR data,i;
+
+       MCLKData=*((USHORT *)(ROMAddr+0x20C));          // MCLKData Table
+       MCLKData=MCLKData+RAMType*5;
+       ECLKData=MCLKData+0x28;
+
+       for(i=0x28;i<=0x2A;i++) {                                       // Set MCLK
+               data=*((UCHAR *)(ROMAddr+MCLKData));
+               SetReg1(P3c4,i,data);
+               MCLKData++;
+       }
+
+       for(i=0x2E;i<=0x30;i++) {                                       // Set ECLK
+               data=*((UCHAR *)(ROMAddr+ECLKData));
+               SetReg1(P3c4,i,data);
+               ECLKData++;
+       }
+}
+#endif   /* NOBIOS */
+
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       ULONG   ROMAddr  = 0;
+       USHORT  BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
+       UCHAR   i,temp,AGP;
+       ULONG   j,k,ulTemp;
+       UCHAR   SR07,SR11,SR19,SR1A,SR1F,SR21,SR22,SR23,SR24,SR25,SR32;
+       UCHAR   SR14;
+       ULONG   Temp;
+
+       if(BaseAddr==0)  return (FALSE);
+       if(HwDeviceExtension->jChipID >= SIS_Trojan)
+               if(!HwDeviceExtension->bIntegratedMMEnabled)  return (FALSE);
+
+       P3c4=BaseAddr+0x14;
+       P3d4=BaseAddr+0x24;
+       P3c0=BaseAddr+0x10;
+       P3ce=BaseAddr+0x1e;
+       P3c2=BaseAddr+0x12;
+       P3ca=BaseAddr+0x1a;
+       P3c6=BaseAddr+0x16;
+       P3c7=BaseAddr+0x17;
+       P3c8=BaseAddr+0x18;
+       P3c9=BaseAddr+0x19;
+       P3da=BaseAddr+0x2A;
+
+       SetReg1(P3c4,0x05,0x86);        // 1.Openkey
+
+       SR14 = (UCHAR)GetReg1(P3c4,0x14);
+       SR19 = (UCHAR)GetReg1(P3c4,0x19);
+       SR1A = (UCHAR)GetReg1(P3c4,0x1A);
+
+       for(i=0x06;i< 0x20;i++) SetReg1(P3c4,i,0);      // 2.Reset Extended register
+       for(i=0x21;i<=0x27;i++) SetReg1(P3c4,i,0);      //      Reset Extended register
+       for(i=0x31;i<=0x3D;i++) SetReg1(P3c4,i,0);
+       for(i=0x30;i<=0x37;i++) SetReg1(P3d4,i,0);
+
+       temp=(UCHAR)SR1A;               // 3.Set Define Extended register
+
+       RAMType=temp&0x07;
+       SetMemoryClock(ROMAddr);
+       for(k=0; k<5; k++)
+               for(j=0; j<0xffff; j++)
+                       ulTemp = (ULONG)GetReg1(P3c4, 0x05);
+
+       Temp = (ULONG)GetReg1(P3c4, 0x3C);
+       Temp = Temp | 0x01;
+       SetReg1(P3c4, 0x3C, (USHORT)Temp);
+
+       for(k=0; k<5; k++)
+               for(j=0; j<0xffff; j++)
+                       Temp = (ULONG)GetReg1(P3c4, 0x05);
+
+       Temp = (ULONG)GetReg1(P3c4, 0x3C);
+       Temp = Temp & 0xFE;
+       SetReg1(P3c4, 0x3C, (USHORT)Temp);
+
+       for(k=0; k<5; k++)
+               for(j=0; j<0xffff; j++)
+                       Temp = (ULONG)GetReg1(P3c4, 0x05);
+
+       SR07=SRegsInit[0x07];
+       SetReg1(P3c4,0x07,SR07);
+
+       SR1F=SRegsInit[0x1F];
+       SetReg1(P3c4,0x1F,SR1F);
+
+       AGP=1;                                                  // Get AGP
+       temp=(UCHAR)GetReg1(P3c4,0x3A);
+       temp=temp&0x30;
+       if(temp==0x30) AGP=0;                   // PCI
+
+       SR21=SRegsInit[0x21];
+       if(AGP==0) SR21=SR21&0xEF;              // PCI
+       SetReg1(P3c4,0x21,SR21);
+
+       SR22=SRegsInit[0x22];
+       if(AGP==1) SR22=SR22&0x20;              // AGP
+       SetReg1(P3c4,0x22,SR22);
+
+       SR23=SRegsInit[0x23];
+       SetReg1(P3c4,0x23,SR23);
+
+       SR24=SRegsInit[0x24];
+       SetReg1(P3c4,0x24,SR24);
+
+       SR25=SRegsInit[0x25];
+       SetReg1(P3c4,0x25,SR25);
+
+       SR32=SRegsInit[0x32];
+       SetReg1(P3c4,0x32,SR32);
+
+       SR11=0x0F;
+       SetReg1(P3c4,0x11,SR11);
+
+       temp=ExtChip301;
+       SetReg1(P3d4,0x37,temp);
+
+       SetReg1(P3c4,0x14,SR14);
+       SetReg1(P3c4,0x19,SR19);
+       SetReg1(P3c4,0x1A,SR1A);
+
+       SetReg3(P3c6,0xff);             // Reset register
+       ClearDAC(P3c8);                 // Reset register
+       DetectMonitor(HwDeviceExtension);        //sense CRT1
+       
+       return(TRUE);
+}
+
+VOID SetMemoryClock(ULONG ROMAddr)
+{
+       UCHAR  i;
+       USHORT idx;
+
+       u8 MCLK[] = {
+               0x5A, 0x64, 0x80, 0x66, 0x00,   // SDRAM
+               0xB3, 0x45, 0x80, 0x83, 0x00,   // SGRAM
+               0x37, 0x61, 0x80, 0x00, 0x01,   // ESDRAM
+               0x37, 0x22, 0x80, 0x33, 0x01,
+               0x37, 0x61, 0x80, 0x00, 0x01,
+               0x37, 0x61, 0x80, 0x00, 0x01,
+               0x37, 0x61, 0x80, 0x00, 0x01,
+               0x37, 0x61, 0x80, 0x00, 0x01
+       };
+
+       u8 ECLK[] = {
+               0x54, 0x43, 0x80, 0x00, 0x01,
+               0x53, 0x43, 0x80, 0x00, 0x01,
+               0x55, 0x43, 0x80, 0x00, 0x01,
+               0x52, 0x43, 0x80, 0x00, 0x01,
+               0x3f, 0x42, 0x80, 0x00, 0x01,
+               0x54, 0x43, 0x80, 0x00, 0x01,
+               0x54, 0x43, 0x80, 0x00, 0x01,
+               0x54, 0x43, 0x80, 0x00, 0x01
+       };
+
+       idx = RAMType * 5;
+
+       for (i = 0x28; i <= 0x2A; i++) {        // Set MCLK
+               SetReg1(P3c4, i, MCLK[idx]);
+               idx++;
+       }
+
+       idx = RAMType * 5;
+       for (i = 0x2E; i <= 0x30; i++) {        // Set ECLK
+               SetReg1(P3c4, i, ECLK[idx]);
+               idx++;
+       }
+
+}
+
+#endif   /* CONFIG_FB_SIS_LINUXBIOS */
+
+// =========================================
+// ======== SiS SetMode Function  ==========
+// =========================================
+
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
+                                                USHORT ModeNo)
+{
+       ULONG   i;
+       USHORT  cr30flag,cr31flag;
+       ULONG   ROMAddr  = (ULONG)HwDeviceExtension->VirtualRomBase;
+       USHORT  BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
+
+       P3c4=BaseAddr+0x14;
+       P3d4=BaseAddr+0x24;
+       P3c0=BaseAddr+0x10;
+       P3ce=BaseAddr+0x1e;
+       P3c2=BaseAddr+0x12;
+       P3ca=BaseAddr+0x1a;
+       P3c6=BaseAddr+0x16;
+       P3c7=BaseAddr+0x17;
+       P3c8=BaseAddr+0x18;
+       P3c9=BaseAddr+0x19;
+       P3da=BaseAddr+0x2A;
+
+       cr30flag=(UCHAR)GetReg1(P3d4,0x30);
+
+       if(((cr30flag&0x01)==1)||((cr30flag&0x02)==0)){
+               SetReg1(P3d4,0x34,ModeNo); 
+               //SetSeqRegs(ROMAddr);
+               {
+                       UCHAR SRdata;
+                       SRdata = SRegs[0x01] | 0x20;
+                       SetReg1(P3c4, 0x01, SRdata);
+
+                       for (i = 02; i <= 04; i++)
+                               SetReg1(P3c4, i, SRegs[i]);
+               }
+
+               //SetMiscRegs(ROMAddr);
+               {
+                       SetReg3(P3c2, 0x23);
+               }
+
+               //SetCRTCRegs(ROMAddr);
+               {
+                       UCHAR CRTCdata;
+
+                       CRTCdata = (UCHAR) GetReg1(P3d4, 0x11);
+                       SetReg1(P3d4, 0x11, CRTCdata);
+
+                       for (i = 0; i <= 0x18; i++)
+                               SetReg1(P3d4, i, CRegs[i]);
+               }
+
+               //SetATTRegs(ROMAddr);
+               {
+                       for (i = 0; i <= 0x13; i++) {
+                               GetReg2(P3da);
+                               SetReg3(P3c0, i);
+                               SetReg3(P3c0, ARegs[i]);
+                       }
+                       GetReg2(P3da);
+                       SetReg3(P3c0, 0x14);
+                       SetReg3(P3c0, 0x00);
+                       GetReg2(P3da);
+                       SetReg3(P3c0, 0x20);
+               }
+
+               //SetGRCRegs(ROMAddr);
+               {
+                       for (i = 0; i <= 0x08; i++)
+                               SetReg1(P3ce, i, GRegs[i]);
+               }
+
+               //ClearExt1Regs();
+               {
+                       for (i = 0x0A; i <= 0x0E; i++)
+                               SetReg1(P3c4, i, 0x00);
+               }
+
+
+               //SetSync(ROMAddr);
+               {
+                       SetReg3(P3c2, MReg);
+               }
+
+               //SetCRT1CRTC(ROMAddr);
+               {
+                       UCHAR data;
+
+                       data = (UCHAR) GetReg1(P3d4, 0x11);
+                       data = data & 0x7F;
+                       SetReg1(P3d4, 0x11, data);
+
+                       for (i = 0; i <= 0x07; i++)
+                               SetReg1(P3d4, i, CRegs[i]);
+                       for (i = 0x10; i <= 0x12; i++)
+                               SetReg1(P3d4, i, CRegs[i]);
+                       for (i = 0x15; i <= 0x16; i++)
+                               SetReg1(P3d4, i, CRegs[i]);
+                       for (i = 0x0A; i <= 0x0C; i++)
+                               SetReg1(P3c4, i, SRegs[i]);
+
+                       data = SRegs[0x0E] & 0xE0;
+                       SetReg1(P3c4, 0x0E, data);
+
+                       SetReg1(P3d4, 0x09, CRegs[0x09]);
+               }
+
+               //SetCRT1Offset(ROMAddr);
+               {
+                       SetReg1(P3c4, 0x0E, SRegs[0x0E]);
+                       SetReg1(P3c4, 0x10, SRegs[0x10]);
+               }
+
+               //SetCRT1VCLK(HwDeviceExtension, ROMAddr);
+               {
+                       SetReg1(P3c4, 0x31, 0);
+
+                       for (i = 0x2B; i <= 0x2C; i++)
+                               SetReg1(P3c4, i, SRegs[i]);
+                       SetReg1(P3c4, 0x2D, 0x80);
+               }
+
+               //SetVCLKState(HwDeviceExtension, ROMAddr, ModeNo);
+               {
+                       SetReg1(P3c4, 0x32, SRegs[0x32]);
+                       SetReg1(P3c4, 0x07, SRegs[0x07]);
+               }
+
+               //SetCRT1FIFO2(ROMAddr);
+               {
+                       SetReg1(P3c4, 0x15, SRegs[0x15]);
+
+                       SetReg4(0xcf8, 0x80000050);
+                       SetReg4(0xcfc, 0xc5041e04);
+
+                       SetReg1(P3c4, 0x08, SRegs[0x08]);
+                       SetReg1(P3c4, 0x0F, SRegs[0x0F]);
+                       SetReg1(P3c4, 0x3b, 0x00);
+                       SetReg1(P3c4, 0x09, SRegs[0x09]);
+               }
+
+               //SetCRT1ModeRegs(ROMAddr, ModeNo);
+               {
+                       SetReg1(P3c4, 0x06, SRegs[0x06]);
+                       SetReg1(P3c4, 0x01, SRegs[0x01]);
+                       SetReg1(P3c4, 0x0F, SRegs[0x0F]);
+                       SetReg1(P3c4, 0x21, SRegs[0x21]);
+               }
+
+               if(HwDeviceExtension->jChipID >= SIS_Trojan)
+               {
+                       //SetInterlace(ROMAddr,ModeNo);
+                       SetReg1(P3d4, 0x19, CRegs[0x19]);
+                       SetReg1(P3d4, 0x1A, CRegs[0x1A]);
+               }
+
+               LoadDAC(ROMAddr);
+
+               ClearBuffer(HwDeviceExtension);
+       }
+
+       cr31flag=(UCHAR)GetReg1(P3d4,0x31);
+       DisplayOn();    // 16.DisplayOn
+       return(NO_ERROR);
+}
+
+VOID LoadDAC(ULONG ROMAddr)
+{
+       USHORT data,data2;
+       USHORT time,i,j,k;
+       USHORT m,n,o;
+       USHORT si,di,bx,dl;
+       USHORT al,ah,dh;
+       USHORT *table=VGA_DAC;
+
+       time=256;
+       table=VGA_DAC;
+       j=16;
+
+       SetReg3(P3c6,0xFF);
+       SetReg3(P3c8,0x00);
+
+       for(i=0;i<j;i++) {
+               data=table[i];
+               for(k=0;k<3;k++) {
+                       data2=0;
+                       if(data&0x01) data2=0x2A;
+                       if(data&0x02) data2=data2+0x15;
+                       SetReg3(P3c9,data2);
+                       data=data>>2;
+               }
+       }
+
+       if(time==256) {
+               for(i=16;i<32;i++) {
+                       data=table[i];
+                       for(k=0;k<3;k++) SetReg3(P3c9,data);
+               }
+               si=32;
+               for(m=0;m<9;m++) {
+                       di=si;
+                       bx=si+0x04;
+                       dl=0;
+                       for(n=0;n<3;n++) {
+                               for(o=0;o<5;o++) {
+                                       dh=table[si];
+                                       ah=table[di];
+                                       al=table[bx];
+                                       si++;
+                                       WriteDAC(dl,ah,al,dh);
+                               }       
+                               si=si-2;
+                               for(o=0;o<3;o++) {
+                                       dh=table[bx];
+                                       ah=table[di];
+                                       al=table[si];
+                                       si--;
+                                       WriteDAC(dl,ah,al,dh);
+                               }       
+                               dl++;
+                       }
+                       si=si+5;
+               }
+       }
+}
+
+VOID WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh)
+{
+       USHORT temp;
+       USHORT bh,bl;
+
+       bh=ah;
+       bl=al;
+       if(dl!=0) {
+               temp=bh;
+               bh=dh;
+               dh=temp;
+               if(dl==1) {
+                       temp=bl;
+                       bl=dh;
+                       dh=temp;
+               }
+               else {
+                       temp=bl;
+                       bl=bh;
+                       bh=temp;
+               }
+       }
+       SetReg3(P3c9,(USHORT)dh);
+       SetReg3(P3c9,(USHORT)bh);
+       SetReg3(P3c9,(USHORT)bl);
+}
+
+
+VOID DisplayOn()
+{
+       USHORT data;
+
+       data=GetReg1(P3c4,0x01);
+       data=data&0xDF;
+       SetReg1(P3c4,0x01,data);
+}
+
+
+#else
+BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
+                                                USHORT ModeNo)
+{
+       ULONG   temp;
+       USHORT  cr30flag,cr31flag;
+       ULONG   ROMAddr  = (ULONG)HwDeviceExtension->VirtualRomBase;
+       USHORT  BaseAddr = (USHORT)HwDeviceExtension->IOAddress;
+
+       P3c4=BaseAddr+0x14;
+       P3d4=BaseAddr+0x24;
+       P3c0=BaseAddr+0x10;
+       P3ce=BaseAddr+0x1e;
+       P3c2=BaseAddr+0x12;
+       P3ca=BaseAddr+0x1a;
+       P3c6=BaseAddr+0x16;
+       P3c7=BaseAddr+0x17;
+       P3c8=BaseAddr+0x18;
+       P3c9=BaseAddr+0x19;
+       P3da=BaseAddr+0x2A;
+       if(ModeNo&0x80){
+         ModeNo=ModeNo&0x7F;
+         flag_clearbuffer=0;             
+       }else{
+         flag_clearbuffer=1;
+       }
+
+       PresetScratchregister(P3d4,HwDeviceExtension); //add for CRT2
+
+       SetReg1(P3c4,0x05,0x86);                                // 1.Openkey
+       temp=SearchModeID(ROMAddr,ModeNo);              // 2.Get ModeID Table
+       if(temp==0)  return(0);
+       
+       SetTVSystem(HwDeviceExtension,ROMAddr); //add for CRT2
+       GetLCDDDCInfo(HwDeviceExtension);               //add for CRT2
+       GetVBInfo(BaseAddr,ROMAddr);                    //add for CRT2
+       GetLCDResInfo(ROMAddr,P3d4);                    //add for CRT2
+
+       temp=CheckMemorySize(ROMAddr);                  // 3.Check memory size
+       if(temp==0) return(0);
+       cr30flag=(UCHAR)GetReg1(P3d4,0x30);
+       if(((cr30flag&0x01)==1)||((cr30flag&0x02)==0)){
+               // if cr30 d[0]=1 or d[1]=0 set crt1  
+               SetReg1(P3d4,0x34,ModeNo); 
+               // set CR34->CRT1 ModeNofor CRT2 FIFO
+               GetModePtr(ROMAddr,ModeNo);                     // 4.GetModePtr
+               SetSeqRegs(ROMAddr);                            // 5.SetSeqRegs
+               SetMiscRegs(ROMAddr);                           // 6.SetMiscRegs
+               SetCRTCRegs(ROMAddr);                           // 7.SetCRTCRegs
+               SetATTRegs(ROMAddr);                            // 8.SetATTRegs
+               SetGRCRegs(ROMAddr);                            // 9.SetGRCRegs
+               ClearExt1Regs();                                        // 10.Clear Ext1Regs
+               temp=GetRatePtr(ROMAddr,ModeNo);        // 11.GetRatePtr
+               if(temp) {
+                       SetSync(ROMAddr);                               // 12.SetSync
+                       SetCRT1CRTC(ROMAddr);                   // 13.SetCRT1CRTC
+                       SetCRT1Offset(ROMAddr);                 // 14.SetCRT1Offset
+                       SetCRT1VCLK(HwDeviceExtension, ROMAddr);        // 15.SetCRT1VCLK
+                       SetVCLKState(HwDeviceExtension, ROMAddr, ModeNo);
+                       if(HwDeviceExtension->jChipID >= SIS_Trojan)
+                               SetCRT1FIFO2(ROMAddr);
+                       else
+                               SetCRT1FIFO(ROMAddr);
+               }
+               SetCRT1ModeRegs(ROMAddr, ModeNo);
+               if(HwDeviceExtension->jChipID >= SIS_Trojan)
+                       SetInterlace(ROMAddr,ModeNo);
+               LoadDAC(ROMAddr);
+               if(flag_clearbuffer) ClearBuffer(HwDeviceExtension);
+       }
+
+       cr31flag=(UCHAR)GetReg1(P3d4,0x31);
+       if(((cr30flag&0x01)==1)||((cr30flag&0x03)==0x02)
+         ||(((cr30flag&0x03)==0x00)&&((cr31flag&0x20)==0x20))){
+               //if CR30 d[0]=1 or d[1:0]=10, set CRT2 or cr30 cr31== 0x00 0x20        
+               SetCRT2Group(BaseAddr,ROMAddr,ModeNo, HwDeviceExtension); //CRT2
+       }
+       DisplayOn();    // 16.DisplayOn
+       return(NO_ERROR);
+}
+
+BOOLEAN SearchModeID(ULONG ROMAddr, USHORT ModeNo)
+{
+       UCHAR ModeID;
+       USHORT  usIDLength;
+
+       ModeIDOffset=*((USHORT *)(ROMAddr+0x20A));              // Get EModeIDTable
+       ModeID=*((UCHAR *)(ROMAddr+ModeIDOffset));              // Offset 0x20A
+       usIDLength = GetModeIDLength(ROMAddr, ModeNo);
+       while(ModeID!=0xff && ModeID!=ModeNo) {
+               ModeIDOffset=ModeIDOffset+usIDLength;
+               ModeID=*((UCHAR *)(ROMAddr+ModeIDOffset));
+       }
+       if(ModeID==0xff) return(FALSE);
+       else return(TRUE);
+}
+
+BOOLEAN CheckMemorySize(ULONG ROMAddr)
+{
+       USHORT memorysize;
+       USHORT modeflag;
+       USHORT temp;
+
+       modeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));      // si+St_ModeFlag
+       ModeType=modeflag&ModeInfoFlag;                         // Get mode type
+
+       memorysize=modeflag&MemoryInfoFlag;
+       memorysize=memorysize>MemorySizeShift;
+       memorysize++;                                                           // Get memory size
+
+       temp=GetReg1(P3c4,0x14);                                        // Get DRAM Size
+       temp=temp&0x3F;
+       temp++;
+
+       if(temp<memorysize) return(FALSE);
+       else return(TRUE);
+}
+
+VOID GetModePtr(ULONG ROMAddr, USHORT ModeNo)
+{
+       UCHAR index;
+
+       StandTable=*((USHORT *)(ROMAddr+0x202));        // Get First  0x202
+                                                                                               // StandTable Offset
+       if(ModeNo<=13) {
+               index=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03));  // si+St_ModeFlag
+       }
+       else {
+               if(ModeType <= 0x02) index=0x1B;                // 02 -> ModeEGA
+               else index=0x0F;
+       }
+
+       StandTable=StandTable+64*index;                         // Get ModeNo StandTable
+
+}
+
+VOID SetSeqRegs(ULONG ROMAddr)
+{
+       UCHAR SRdata;
+       USHORT i;
+
+       SetReg1(P3c4,0x00,0x03);                                        // Set SR0
+       StandTable=StandTable+0x05;
+       SRdata=*((UCHAR *)(ROMAddr+StandTable));        // Get SR01 from file
+       if(IF_DEF_LVDS==1){
+               if(VBInfo&SetCRT2ToLCD){
+                       if(VBInfo&SetInSlaveMode){
+                               if(LCDInfo&LCDNonExpanding){
+                                       SRdata=SRdata|0x01;
+                               }
+                       }
+               }
+       }
+
+       SRdata=SRdata|0x20;
+       SetReg1(P3c4,0x01,SRdata);                                      // Set SR1
+       for(i=02;i<=04;i++) {
+               StandTable++;
+               SRdata=*((UCHAR *)(ROMAddr+StandTable));        // Get SR2,3,4 from file
+               SetReg1(P3c4,i,SRdata);                                 // Set SR2 3 4
+       }
+}
+
+VOID SetMiscRegs(ULONG ROMAddr)
+{
+       UCHAR Miscdata;
+
+       StandTable++;
+       Miscdata=*((UCHAR *)(ROMAddr+StandTable));      // Get Misc from file
+       SetReg3(P3c2,Miscdata);                                         // Set Misc(3c2)
+}
+
+VOID SetCRTCRegs(ULONG ROMAddr)
+{
+       UCHAR CRTCdata;
+       USHORT i;
+
+       CRTCdata=(UCHAR)GetReg1(P3d4,0x11);
+       CRTCdata=CRTCdata&0x7f;
+       SetReg1(P3d4,0x11,CRTCdata);                            // Unlock CRTC
+
+       for(i=0;i<=0x18;i++) {
+               StandTable++;
+               CRTCdata=*((UCHAR *)(ROMAddr+StandTable));              // Get CRTC from file
+               SetReg1(P3d4,i,CRTCdata);                               // Set CRTC(3d4)
+       }
+}
+
+VOID SetATTRegs(ULONG ROMAddr)
+{
+       UCHAR ARdata;
+       USHORT i;
+
+       for(i=0;i<=0x13;i++) {
+               StandTable++;
+               ARdata=*((UCHAR *)(ROMAddr+StandTable));          // Get AR for file
+               if(IF_DEF_LVDS==1){  //for LVDS
+                       if(VBInfo&SetCRT2ToLCD){
+                               if(VBInfo&SetInSlaveMode){
+                                       if(LCDInfo&LCDNonExpanding){
+                                               if(i==0x13){
+                                                       ARdata=0;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               GetReg2(P3da);                  // reset 3da
+               SetReg3(P3c0,i);                // set index
+               SetReg3(P3c0,ARdata);   // set data
+       }
+       if(IF_DEF_LVDS==1){  //for LVDS
+               if(VBInfo&SetCRT2ToLCD){
+                       if(VBInfo&SetInSlaveMode){
+                               if(LCDInfo&LCDNonExpanding){
+                               
+                               }
+                       }
+               }
+       }
+       GetReg2(P3da);                  // reset 3da
+       SetReg3(P3c0,0x14);             // set index
+       SetReg3(P3c0,0x00);             // set data
+
+       GetReg2(P3da);                  // Enable Attribute
+       SetReg3(P3c0,0x20);
+}
+
+VOID SetGRCRegs(ULONG ROMAddr)
+{
+       UCHAR GRdata;
+       USHORT i;
+
+       for(i=0;i<=0x08;i++) {
+               StandTable++;
+               GRdata=*((UCHAR *)(ROMAddr+StandTable));        // Get GR from file
+               SetReg1(P3ce,i,GRdata);                                         // Set GR(3ce)
+       }
+       if(ModeType>ModeVGA){
+               GRdata=(UCHAR)GetReg1(P3ce,0x05);
+               GRdata=GRdata&0xBF;
+               SetReg1(P3ce,0x05,GRdata); 
+       }
+}
+
+VOID ClearExt1Regs()
+{
+       USHORT i;
+
+       for(i=0x0A;i<=0x0E;i++) SetReg1(P3c4,i,0x00);   // Clear SR0A-SR0E
+}
+
+
+BOOLEAN GetRatePtr(ULONG ROMAddr, USHORT ModeNo)
+{
+       SHORT   index;
+       USHORT temp;
+       USHORT ulRefIndexLength;
+
+       if(ModeNo<0x14) return(FALSE);                          // Mode No <= 13h then return
+
+       index=GetReg1(P3d4,0x33);                                       // Get 3d4 CRTC33
+       index=index&0x0F;                                                       // Frame rate index
+       if(index!=0) index--;
+       REFIndex=*((USHORT *)(ROMAddr+ModeIDOffset+0x04));      // si+Ext_point
+
+       ulRefIndexLength = GetRefindexLength(ROMAddr, ModeNo);
+       do {
+               temp=*((USHORT *)(ROMAddr+REFIndex));   // di => REFIndex
+               if(temp==0xFFFF) break;
+               temp=temp&ModeInfoFlag;
+               if(temp<ModeType) break;
+
+               REFIndex=REFIndex+ulRefIndexLength;             // rate size
+               index--;
+       } while(index>=0);
+
+       REFIndex=REFIndex-ulRefIndexLength;                     // rate size
+       return(TRUE);
+}
+
+VOID SetSync(ULONG ROMAddr)
+{
+       USHORT sync;
+       USHORT temp;
+
+       sync=*((USHORT *)(ROMAddr+REFIndex));           // di+0x00
+       sync=sync&0xC0;
+       temp=0x2F;
+       temp=temp|sync;
+       SetReg3(P3c2,temp);                                                     // Set Misc(3c2)
+}
+
+VOID SetCRT1CRTC(ULONG ROMAddr)
+{
+       UCHAR  index;
+       UCHAR  data;
+       USHORT i;
+
+       index=*((UCHAR *)(ROMAddr+REFIndex+0x02));      // Get index
+       index=index&0x03F;
+       CRT1Table=*((USHORT *)(ROMAddr+0x204));         // Get CRT1Table
+       CRT1Table=CRT1Table+index*CRT1Len;
+
+       data=(UCHAR)GetReg1(P3d4,0x11);
+       data=data&0x7F;
+       SetReg1(P3d4,0x11,data);                                        // Unlock CRTC
+
+       CRT1Table--;
+       for(i=0;i<=0x05;i++) {
+               CRT1Table++;
+               data=*((UCHAR *)(ROMAddr+CRT1Table));
+               SetReg1(P3d4,i,data);
+       }
+       for(i=0x06;i<=0x07;i++) {
+               CRT1Table++;
+               data=*((UCHAR *)(ROMAddr+CRT1Table));
+               SetReg1(P3d4,i,data);
+       }
+       for(i=0x10;i<=0x12;i++) {
+               CRT1Table++;
+               data=*((UCHAR *)(ROMAddr+CRT1Table));
+               SetReg1(P3d4,i,data);
+       }
+       for(i=0x15;i<=0x16;i++) {
+               CRT1Table++;
+               data=*((UCHAR *)(ROMAddr+CRT1Table));
+               SetReg1(P3d4,i,data);
+       }
+       for(i=0x0A;i<=0x0C;i++) {
+               CRT1Table++;
+               data=*((UCHAR *)(ROMAddr+CRT1Table));
+               SetReg1(P3c4,i,data);
+       }
+
+       CRT1Table++;
+       data=*((UCHAR *)(ROMAddr+CRT1Table));
+       data=data&0xE0;
+       SetReg1(P3c4,0x0E,data);
+
+       data=(UCHAR)GetReg1(P3d4,0x09);
+       data=data&0xDF;
+       i=*((UCHAR *)(ROMAddr+CRT1Table));
+       i=i&0x01;
+       i=i<<5;
+       data=data|i;
+       i=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+       i=i&DoubleScanMode;
+       if(i) data=data|0x80;
+       SetReg1(P3d4,0x09,data);
+
+       if(ModeType>0x03) SetReg1(P3d4,0x14,0x4F);
+}
+
+VOID SetCRT1Offset(ULONG ROMAddr)
+{
+       USHORT temp,ah,al;
+       USHORT temp2,i;
+       USHORT DisplayUnit;
+
+       temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03));           // si+Ext_ModeInfo
+       temp=temp>>4;                                                                           // index
+       ScreenOffset=*((USHORT *)(ROMAddr+0x206));                      // ScreenOffset
+       temp=*((UCHAR *)(ROMAddr+ScreenOffset+temp));           // data
+
+       temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
+       temp2=temp2&InterlaceMode;
+       if(temp2) temp=temp<<1;
+       temp2=ModeType-ModeEGA;
+       switch (temp2) {
+               case 0 : temp2=1; break;
+               case 1 : temp2=2; break;
+               case 2 : temp2=4; break;
+               case 3 : temp2=4; break;
+               case 4 : temp2=6; break;
+               case 5 : temp2=8; break;
+       }
+       temp=temp*temp2;
+       DisplayUnit=temp;
+
+       temp2=temp;
+       temp=temp>>8;           
+       temp=temp&0x0F;
+       i=GetReg1(P3c4,0x0E);
+       i=i&0xF0;
+       i=i|temp;
+       SetReg1(P3c4,0x0E,i);
+
+       temp=(UCHAR)temp2;
+       temp=temp&0xFF;         
+       SetReg1(P3d4,0x13,temp);
+
+       temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
+       temp2=temp2&InterlaceMode;
+       if(temp2) DisplayUnit>>=1;
+
+       DisplayUnit=DisplayUnit<<5;
+       ah=(DisplayUnit&0xff00)>>8;
+       al=DisplayUnit&0x00ff;
+       if(al==0) ah=ah+1;
+       else ah=ah+2;
+       SetReg1(P3c4,0x10,ah);
+}
+
+
+VOID SetCRT1VCLK(PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG ROMAddr)
+{
+       USHORT i;
+       UCHAR  index,data;
+
+       index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+       index=index&0x03F;
+       CRT1VCLKLen=GetVCLKLen(ROMAddr);
+       data=index*CRT1VCLKLen;
+       VCLKData=*((USHORT *)(ROMAddr+0x208));
+       VCLKData=VCLKData+data;
+
+       SetReg1(P3c4,0x31,0);
+       for(i=0x2B;i<=0x2C;i++) {
+               data=*((UCHAR *)(ROMAddr+VCLKData));
+               SetReg1(P3c4,i,data);
+               VCLKData++;
+       }
+       SetReg1(P3c4,0x2D,0x80);
+}
+
+
+VOID SetCRT1ModeRegs(ULONG ROMAddr, USHORT ModeNo)
+{
+
+       USHORT data,data2,data3;
+
+       if(ModeNo>0x13) data=*((USHORT *)(ROMAddr+REFIndex+0x00));
+       else data=0;
+
+       data2=0;
+       if(ModeNo>0x13)
+               if(ModeType>0x02) {
+                       data2=data2|0x02;
+                       data3=ModeType-ModeVGA;
+                       data3=data3<<2;
+                       data2=data2|data3;
+               }
+
+       data=data&InterlaceMode;
+       if(data) data2=data2|0x20;
+       SetReg1(P3c4,0x06,data2);
+
+       data=GetReg1(P3c4,0x01);
+       data=data&0xF7;
+       data2=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+       data2=data2&HalfDCLK;
+       if(data2) data=data|0x08;
+       SetReg1(P3c4,0x01,data);
+
+       data=GetReg1(P3c4,0x0F);
+       data=data&0xF7;
+       data2=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+       data2=data2&LineCompareOff;
+       if(data2) data=data|0x08;
+       SetReg1(P3c4,0x0F,data);
+
+       data=GetReg1(P3c4,0x21);
+       data=data&0x1F;
+       if(ModeType==0x00) data=data|0x60;                      // Text Mode
+       else if(ModeType<=0x02) data=data|0x00;         // EGA Mode
+       else data=data|0xA0;                                            // VGA Mode
+       SetReg1(P3c4,0x21,data);
+}
+
+VOID SetVCLKState(PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG ROMAddr, USHORT ModeNo)
+{
+       USHORT data,data2;
+       USHORT VCLK;
+       UCHAR  index;
+
+       index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+       index=index&0x03F;
+       CRT1VCLKLen=GetVCLKLen(ROMAddr);
+       data=index*CRT1VCLKLen;
+       VCLKData=*((USHORT *)(ROMAddr+0x208));
+       VCLKData=VCLKData+data+(CRT1VCLKLen-2);
+       VCLK=*((USHORT *)(ROMAddr+VCLKData));
+       if(ModeNo<=0x13) VCLK=0;
+
+       data=GetReg1(P3c4,0x07);
+       data=data&0x7B;
+       if(VCLK>=150) data=data|0x80;   // VCLK > 150
+       SetReg1(P3c4,0x07,data);
+
+       data=GetReg1(P3c4,0x32);
+       data=data&0xD7;
+       if(VCLK>=150) data=data|0x08;   // VCLK > 150
+       SetReg1(P3c4,0x32,data);
+
+       data2=0x03;
+       if(VCLK>135) data2=0x02;
+       if(VCLK>160) data2=0x01;
+       if(VCLK>260) data2=0x00;
+       data=GetReg1(P3c4,0x07);
+       data=data&0xFC;
+       data=data|data2;
+       SetReg1(P3c4,0x07,data);
+}
+
+VOID LoadDAC(ULONG ROMAddr)
+{
+       USHORT data,data2;
+       USHORT time,i,j,k;
+       USHORT m,n,o;
+       USHORT si,di,bx,dl;
+       USHORT al,ah,dh;
+       USHORT *table=VGA_DAC;
+
+       data=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+       data=data&DACInfoFlag;
+       time=64;
+       if(data==0x00) table=MDA_DAC;
+       if(data==0x08) table=CGA_DAC;
+       if(data==0x10) table=EGA_DAC;
+       if(data==0x18) {
+               time=256;
+               table=VGA_DAC;
+       }
+       if(time==256) j=16;
+       else j=time;
+
+       SetReg3(P3c6,0xFF);
+       SetReg3(P3c8,0x00);
+
+       for(i=0;i<j;i++) {
+               data=table[i];
+               for(k=0;k<3;k++) {
+                       data2=0;
+                       if(data&0x01) data2=0x2A;
+                       if(data&0x02) data2=data2+0x15;
+                       SetReg3(P3c9,data2);
+                       data=data>>2;
+               }
+       }
+
+       if(time==256) {
+               for(i=16;i<32;i++) {
+                       data=table[i];
+                       for(k=0;k<3;k++) SetReg3(P3c9,data);
+               }
+               si=32;
+               for(m=0;m<9;m++) {
+                       di=si;
+                       bx=si+0x04;
+                       dl=0;
+                       for(n=0;n<3;n++) {
+                               for(o=0;o<5;o++) {
+                                       dh=table[si];
+                                       ah=table[di];
+                                       al=table[bx];
+                                       si++;
+                                       WriteDAC(dl,ah,al,dh);
+                               }       
+                               si=si-2;
+                               for(o=0;o<3;o++) {
+                                       dh=table[bx];
+                                       ah=table[di];
+                                       al=table[si];
+                                       si--;
+                                       WriteDAC(dl,ah,al,dh);
+                               }       
+                               dl++;
+                       }
+                       si=si+5;
+               }
+       }
+}
+
+VOID WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh)
+{
+       USHORT temp;
+       USHORT bh,bl;
+
+       bh=ah;
+       bl=al;
+       if(dl!=0) {
+               temp=bh;
+               bh=dh;
+               dh=temp;
+               if(dl==1) {
+                       temp=bl;
+                       bl=dh;
+                       dh=temp;
+               }
+               else {
+                       temp=bl;
+                       bl=bh;
+                       bh=temp;
+               }
+       }
+       SetReg3(P3c9,(USHORT)dh);
+       SetReg3(P3c9,(USHORT)bh);
+       SetReg3(P3c9,(USHORT)bl);
+}
+
+
+VOID DisplayOn()
+{
+       USHORT data;
+
+       data=GetReg1(P3c4,0x01);
+       data=data&0xDF;
+       SetReg1(P3c4,0x01,data);
+}
+
+USHORT GetModeIDLength(ULONG ROMAddr, USHORT ModeNo)
+{
+       USHORT modeidlength;
+       USHORT usModeIDOffset;
+       USHORT PreviousWord,CurrentWord;
+
+       modeidlength=0;
+       usModeIDOffset=*((USHORT *)(ROMAddr+0x20A));            // Get EModeIDTable
+       //      maybe = 2Exx or xx2E            
+       CurrentWord=*((USHORT *)(ROMAddr+usModeIDOffset));      // Offset 0x20A
+       PreviousWord=*((USHORT *)(ROMAddr+usModeIDOffset-2));   // Offset 0x20A
+       while((CurrentWord!=0x2E07)||(PreviousWord!=0x0801)) {
+               modeidlength++;
+               usModeIDOffset=usModeIDOffset+1;                                // 10 <= ExtStructSize
+               CurrentWord=*((USHORT *)(ROMAddr+usModeIDOffset));
+               PreviousWord=*((USHORT *)(ROMAddr+usModeIDOffset-2)); 
+       }
+       modeidlength++;
+       return(modeidlength);
+}
+
+USHORT GetRefindexLength(ULONG ROMAddr, USHORT ModeNo)
+{
+       UCHAR ModeID;
+       UCHAR temp;
+       USHORT refindexlength;
+       USHORT usModeIDOffset;
+       USHORT usREFIndex;
+       USHORT usIDLength;
+
+       usModeIDOffset=*((USHORT *)(ROMAddr+0x20A));    // Get EModeIDTable
+       ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset));    // Offset 0x20A
+       usIDLength = GetModeIDLength(ROMAddr, ModeNo);
+       while(ModeID!=0x40) {
+               usModeIDOffset=usModeIDOffset+usIDLength;       // 10 <= ExtStructSize
+               ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset));
+       }
+
+       refindexlength=1;
+       usREFIndex=*((USHORT *)(ROMAddr+usModeIDOffset+0x04));  // si+Ext_point
+       usREFIndex++;
+       temp=*((UCHAR *)(ROMAddr+usREFIndex));                  // di => REFIndex
+       while(temp!=0xFF) {
+               refindexlength++;
+               usREFIndex++;
+               temp=*((UCHAR *)(ROMAddr+usREFIndex));          // di => REFIndex
+       }
+       return(refindexlength);
+}
+
+VOID SetInterlace(ULONG ROMAddr, USHORT ModeNo)
+{
+       ULONG Temp;
+       USHORT data,Temp2;
+
+       Temp = (ULONG)GetReg1(P3d4, 0x01);
+       Temp++;
+       Temp=Temp*8;
+
+       if(Temp==1024) data=0x0035;
+       else if(Temp==1280) data=0x0048;
+       else data=0x0000;
+
+       Temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
+       Temp2 &= InterlaceMode;
+       if(Temp2 == 0) data=0x0000;
+
+       SetReg1(P3d4,0x19,data);
+
+       Temp = (ULONG)GetReg1(P3d4, 0x1A);
+       Temp2= (USHORT)(Temp & 0xFC);
+       SetReg1(P3d4,0x1A,(USHORT)Temp);
+
+       Temp = (ULONG)GetReg1(P3c4, 0x0f);
+       Temp2= (USHORT)Temp & 0xBF;
+       if(ModeNo==0x37) Temp2=Temp2|0x40;
+       SetReg1(P3d4,0x1A,(USHORT)Temp2);
+}
+
+VOID SetCRT1FIFO(ULONG ROMAddr)
+{
+       USHORT  colorth=0,index,data,VCLK,data2,MCLKOffset,MCLK;
+       USHORT  ah,bl,A,B;
+
+       index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+       index=index&0x03F;
+       CRT1VCLKLen=GetVCLKLen(ROMAddr);
+       data=index*CRT1VCLKLen;
+       VCLKData=*((USHORT *)(ROMAddr+0x208));
+       VCLKData=VCLKData+data+(CRT1VCLKLen-2);
+       VCLK=*((USHORT *)(ROMAddr+VCLKData));           // Get VCLK
+
+       MCLKOffset=*((USHORT *)(ROMAddr+0x20C));
+       index=GetReg1(P3c4,0x3A);
+       index=index&07;
+       MCLKOffset=MCLKOffset+index*5;
+       MCLK=*((UCHAR *)(ROMAddr+MCLKOffset+0x03));     // Get MCLK
+
+       data2=ModeType-0x02;
+       switch (data2) {
+               case 0 : colorth=1; break;
+               case 1 : colorth=2; break;
+               case 2 : colorth=4; break;
+               case 3 : colorth=4; break;
+               case 4 : colorth=6; break;
+               case 5 : colorth=8; break;
+        }
+
+       do{
+               B=(CalcDelay(ROMAddr,0)*VCLK*colorth);
+               B=B/(16*MCLK);
+               B++;
+
+               A=(CalcDelay(ROMAddr,1)*VCLK*colorth);
+               A=A/(16*MCLK);
+               A++;
+
+               if(A<4) A=0;
+               else A=A-4;
+
+               if(A>B) bl=A;
+               else bl=B;
+
+               bl++;
+               if(bl>0x13) {
+                       data=GetReg1(P3c4,0x16);
+                       data=data>>6;
+                       if(data!=0) {
+                               data--;
+                               data=data<<6;
+                               data2=GetReg1(P3c4,0x16);
+                               data2=(data2&0x3f)|data;
+                               SetReg1(P3c4,0x16,data2);
+                       }
+                       else bl=0x13;
+               }
+       } while(bl>0x13);
+
+       ah=bl;
+       ah=ah<<4;
+       ah=ah|0x0f;
+       SetReg1(P3c4,0x08,ah);
+
+       data=bl;
+       data=data&0x10;
+       data=data<<1;
+       data2=GetReg1(P3c4,0x0F);
+       data2=data2&0x9f;
+       data2=data2|data;
+       SetReg1(P3c4,0x0F,data2);
+
+       data=bl+3;
+       if(data>0x0f) data=0x0f;
+       SetReg1(P3c4,0x3b,0x00);
+       data2=GetReg1(P3c4,0x09);
+       data2=data2&0xF0;
+       data2=data2|data;
+       SetReg1(P3c4,0x09,data2);
+}
+
+static USHORT CalcDelay(ULONG ROMAddr,USHORT key)
+{
+       USHORT data,data2,temp0,temp1;
+       UCHAR  ThLowA[]={61,3,52,5,68,7,100,11,
+                                        43,3,42,5,54,7, 78,11,
+                                        34,3,37,5,47,7, 67,11};
+       UCHAR  ThLowB[]={81,4,72,6,88,8,120,12,
+                                        55,4,54,6,66,8, 90,12,
+                                        42,4,45,6,55,8, 75,12};
+       UCHAR  ThTiming[]= {1,2,2,3,0,1,1,2};
+
+       data=GetReg1(P3c4,0x16);
+       data=data>>6;
+       data2=GetReg1(P3c4,0x14);
+       data2=(data2>>4)&0x0C;
+       data=data|data2;
+       data=data<1;
+       if(key==0) {
+               temp0=(USHORT)ThLowA[data];
+               temp1=(USHORT)ThLowA[data+1];
+       }
+       else {
+               temp0=(USHORT)ThLowB[data];
+               temp1=(USHORT)ThLowB[data+1];
+       }
+
+       data2=0;
+       data=GetReg1(P3c4,0x18);
+       if(data&0x02) data2=data2|0x01;
+       if(data&0x20) data2=data2|0x02;
+       if(data&0x40) data2=data2|0x04;
+
+       data=temp1*ThTiming[data2]+temp0;
+       return(data);
+}
+
+VOID SetCRT1FIFO2(ULONG ROMAddr)
+{
+       USHORT  colorth=0,index,data,VCLK,data2,MCLKOffset,MCLK;
+       USHORT  ah,bl,B;
+       ULONG   eax;
+
+       index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+       index=index&0x03F;
+       CRT1VCLKLen=GetVCLKLen(ROMAddr);
+       data=index*CRT1VCLKLen;
+       VCLKData=*((USHORT *)(ROMAddr+0x208));
+       VCLKData=VCLKData+data+(CRT1VCLKLen-2);
+       VCLK=*((USHORT *)(ROMAddr+VCLKData));                   // Get VCLK
+
+       MCLKOffset=*((USHORT *)(ROMAddr+0x20C));
+       index=GetReg1(P3c4,0x1A);
+       index=index&07;
+       MCLKOffset=MCLKOffset+index*5;
+       MCLK=*((USHORT *)(ROMAddr+MCLKOffset+0x03));    // Get MCLK  
+
+       data2=ModeType-0x02;
+       switch (data2) {
+               case 0 : colorth=1; break;
+               case 1 : colorth=1; break;
+               case 2 : colorth=2; break;
+               case 3 : colorth=2; break;
+               case 4 : colorth=3; break;
+               case 5 : colorth=4; break;
+       }
+
+       do{
+               B=(CalcDelay2(ROMAddr,0)*VCLK*colorth);
+               if (B%(16*MCLK) == 0)
+               {
+                       B=B/(16*MCLK);
+                       bl=B+1;
+               }
+               else
+               {
+                       B=B/(16*MCLK);
+                       bl=B+2;
+               }
+
+               if(bl>0x13) {
+                       data=GetReg1(P3c4,0x15);
+                       data=data&0xf0;
+                       if(data!=0xb0) {
+                               data=data+0x20;
+                               if(data==0xa0) data=0x30;
+
+                               data2=GetReg1(P3c4,0x15);
+                               data2=(data2&0x0f)|data;
+                               SetReg1(P3c4,0x15,data2);
+                       }
+                       else bl=0x13;
+               }
+       } while(bl>0x13);
+
+       data2=GetReg1(P3c4,0x15);
+       data2=(data2&0xf0)>>4;
+       data2=data2<<24;
+
+       SetReg4(0xcf8,0x80000050);
+       eax=GetReg3(0xcfc);
+       eax=eax&0x0f0ffffff;
+       eax=eax|data2;
+       SetReg4(0xcfc,eax);
+
+       ah=bl;
+       ah=ah<<4;
+       ah=ah|0x0f;
+       SetReg1(P3c4,0x08,ah);
+
+       data=bl;
+       data=data&0x10;
+       data=data<<1;
+       data2=GetReg1(P3c4,0x0F);
+       data2=data2&0x9f;
+       data2=data2|data;
+       SetReg1(P3c4,0x0F,data2);
+
+       data=bl+3;
+       if(data>0x0f) data=0x0f;
+       SetReg1(P3c4,0x3b,0x00);
+       data2=GetReg1(P3c4,0x09);
+       data2=data2&0xF0;
+       data2=data2|data;
+       SetReg1(P3c4,0x09,data2);
+}
+
+USHORT CalcDelay2(ULONG ROMAddr,USHORT key)
+{
+       USHORT data,index;
+       UCHAR  LatencyFactor[]={88,80,78,72,70,00,
+                                                       00,79,77,71,69,49,
+                                                       88,80,78,72,70,00,
+                                                       00,72,70,64,62,44};
+
+       index=0;
+       data=GetReg1(P3c4,0x14);
+       if(data&0x80) index=index+12;
+
+       data=GetReg1(P3c4,0x15);
+       data=(data&0xf0)>>4;
+       if(data&0x01) index=index+6;
+
+       data=data>>1;
+       index=index+data;
+       data=LatencyFactor[index];
+
+       return(data);
+}
+
+#endif /* CONFIG_FB_SIS_LINUXBIOS */
\ No newline at end of file
diff --git a/drivers/video/sis/sis_300.h b/drivers/video/sis/sis_300.h
new file mode 100644 (file)
index 0000000..7200365
--- /dev/null
@@ -0,0 +1,162 @@
+#include "initdef.h"
+
+USHORT DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48},
+                     {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44},
+                     {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40},
+                     {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32},
+                     {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30},
+                     {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28},
+                     {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24},
+                     {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10},
+                     {0x09,0x08,0x01,0x01,0x00}};
+
+USHORT MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F};
+
+USHORT CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+
+USHORT EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+               0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+               0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+               0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+               0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+               0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+               0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+
+USHORT VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+               0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+
+               0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+               0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+               0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+               0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+               0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+               0x0B,0x0C,0x0D,0x0F,0x10};
+
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+unsigned char SRegsInit[] = { 
+       0x03, 0x00, 0x03, 0x00, 0x02, 0xa1, 0x00, 0x13,
+       0x2f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+       0x00, 0x0f, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 
+       0xa1, 0x76, 0xb2, 0xf6, 0x0d, 0x00, 0x00, 0x00,
+       0x37, 0x61, 0x80, 0x1b, 0xe1, 0x01, 0x55, 0x43, 
+       0x80, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff,
+       0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff
+};
+
+unsigned char SRegs[] = { 
+       0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13,
+       0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+       0x0B, 0x0F, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x40, 0x00,
+       0xA1, 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0xF8, 0xF0,
+       0x37, 0x61, 0x80, 0x1B, 0xE1, 0x80, 0x55, 0x43,
+       0x80, 0x00, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF,
+       0x8E, 0x40, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF
+};
+
+unsigned char CRegs[] = { 
+       0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
+       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
+       0xe9, 0x0b, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3,
+       0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff
+};     // clear CR11[7]
+
+unsigned char GRegs[] = { 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, 0x00
+};
+
+unsigned char ARegs[] = { 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char MReg = 0x6f;
+
+#endif
+
+USHORT      P3c4,P3d4,P3c0,P3ce,P3c2,P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
+USHORT  CRT1VCLKLen; //VCLKData table length of bytes of each entry
+USHORT   flag_clearbuffer; //0: no clear frame buffer 1:clear frame buffer
+int      RAMType;
+int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,VCLKData,MCLKData, ECLKData;
+int      REFIndex,ModeType;
+USHORT  IF_DEF_LVDS,IF_DEF_TRUMPION;
+USHORT   VBInfo,LCDResInfo,LCDTypeInfo,LCDInfo;
+
+//int    init300(int,int,int);
+VOID   SetMemoryClock(ULONG);
+VOID   SetDRAMSize(PHW_DEVICE_EXTENSION);
+//extern      "C"    int     ChkBUSWidth(int);
+
+//int    setmode(int,int,int,int);
+BOOLEAN  SearchModeID(ULONG, USHORT);
+BOOLEAN  CheckMemorySize(ULONG);
+VOID     GetModePtr(ULONG, USHORT);
+BOOLEAN  GetRatePtr(ULONG, USHORT);
+VOID     SetSeqRegs(ULONG);
+VOID     SetMiscRegs(ULONG);
+VOID     SetCRTCRegs(ULONG);
+VOID     SetATTRegs(ULONG);
+VOID     SetGRCRegs(ULONG);
+VOID     ClearExt1Regs(VOID);
+VOID     SetSync(ULONG);
+VOID     SetCRT1CRTC(ULONG);
+VOID     SetCRT1Offset(ULONG);
+VOID     SetCRT1FIFO(ULONG);
+VOID     SetCRT1FIFO2(ULONG);
+VOID     SetCRT1VCLK(PHW_DEVICE_EXTENSION, ULONG);
+VOID     LoadDAC(ULONG);
+VOID     DisplayOn(VOID);
+VOID     SetCRT1ModeRegs(ULONG, USHORT);
+VOID     SetVCLKState(PHW_DEVICE_EXTENSION, ULONG, USHORT);
+VOID     WriteDAC(USHORT, USHORT, USHORT, USHORT);
+VOID     ClearBuffer(PHW_DEVICE_EXTENSION);
+USHORT   ChkBUSWidth(ULONG);
+USHORT   GetModeIDLength(ULONG, USHORT);
+USHORT   GetRefindexLength(ULONG, USHORT);
+VOID     SetInterlace(ULONG, USHORT);
+USHORT   CalcDelay2(ULONG ,USHORT);
+void    Set_LVDS_TRUMPION(VOID);
+BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
+                   USHORT ModeNo);
+#ifndef CONFIG_FB_SIS_LINUXBIOS
+static USHORT   CalcDelay(ULONG ,USHORT);
+#endif
+
+extern BOOLEAN SetCRT2Group(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+extern VOID GetVBInfo(USHORT BaseAddr,ULONG ROMAddr);
+extern VOID PresetScratchregister(USHORT P3d4,PHW_DEVICE_EXTENSION HwDeviceExtension);
+extern BOOLEAN GetLCDResInfo(ULONG ROMAddr,USHORT P3d4);
+extern VOID SetTVSystem(PHW_DEVICE_EXTENSION HwDeviceExtension,ULONG ROMAddr);
+extern BOOLEAN GetLCDDDCInfo(PHW_DEVICE_EXTENSION HwDeviceExtension);
+extern BOOLEAN GetSenseStatus(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT BaseAddr,ULONG ROMAddr);
+extern BOOLEAN DetectMonitor(PHW_DEVICE_EXTENSION HwDeviceExtension);
+extern USHORT GetVCLKLen(ULONG ROMAddr);
+extern void SetReg1(u16 port, u16 index, u16 data);
+extern void SetReg3(u16 port, u16 data);
+extern void SetReg4(u16 port, unsigned long data);
+extern u8 GetReg1(u16 port, u16 index);
+extern u8 GetReg2(u16 port);
+extern u32 GetReg3(u16 port);
+extern void ClearDAC(u16 port);
\ No newline at end of file
diff --git a/drivers/video/sis/sis_301.c b/drivers/video/sis/sis_301.c
new file mode 100644 (file)
index 0000000..b249983
--- /dev/null
@@ -0,0 +1,2867 @@
+/* Recently Update by v1.09.50 */
+
+#include "sis_301.h"
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
+
+BOOLEAN SetCRT2Group(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+                       PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT temp;
+       
+       SetFlag=SetFlag|ProgrammingCRT2;
+       SearchModeID(ROMAddr,ModeNo);
+
+       temp=GetRatePtrCRT2(ROMAddr,ModeNo);
+       if(((temp&0x02)==0) && ((VBInfo&CRT2DisplayFlag)==0))
+               return(FALSE);
+       SaveCRT2Info(ModeNo);   
+       DisableBridge(BaseAddr);
+       UnLockCRT2(BaseAddr);
+       SetDefCRT2ExtRegs(BaseAddr);
+       SetCRT2ModeRegs(BaseAddr,ModeNo);
+       if(VBInfo&CRT2DisplayFlag){
+               LockCRT2(BaseAddr);
+               return 0;       
+       }
+       GetCRT2Data(ROMAddr,ModeNo);
+       if(IF_DEF_LVDS==1){     //LVDS
+               GetLVDSDesData(ROMAddr,ModeNo);
+       }
+       SetGroup1(BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+       if(IF_DEF_LVDS==0){
+               SetGroup2(BaseAddr,ROMAddr);            
+               SetGroup3(BaseAddr);
+               SetGroup4(BaseAddr,ROMAddr,ModeNo);
+               SetGroup5(BaseAddr,ROMAddr);
+       }else{  //LVDS
+               if(IF_DEF_TRUMPION==0){
+                       ModCRT1CRTC(ROMAddr,ModeNo);
+               }
+               SetCRT2ECLK(ROMAddr,ModeNo);
+       }
+
+       EnableCRT2();
+       EnableBridge(BaseAddr);
+       SetLockRegs();
+       LockCRT2(BaseAddr);
+       return 1;                               
+}
+
+VOID overwriteregs(ULONG ROMAddr,USHORT BaseAddr)
+{
+       int i;
+       USHORT  Part1Port; //reg data is for 1024x768 16bit 85hz
+       int p1reg[0x29]={0x84,0x76,0x4B,0x21,0x00,0x00,0x00,0x00,0x1F,0x51,
+                                        0x0C,0x10,0x44,0x90,0x1E,0xFF,0x00,0x34,0x13,0x10,
+                                        0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x97,0x16,
+                                        0xA3};
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       for(i=0;i<29;i++){
+               SetReg1(Part1Port,(USHORT)i,(USHORT)p1reg[i]);
+       }
+}
+
+VOID SetDefCRT2ExtRegs(USHORT BaseAddr)
+{
+       USHORT  Part1Port,Part2Port,Part4Port;
+       USHORT  temp;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
+       Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
+       SetReg1(Part1Port,0x02,0x40);
+       SetReg1(Part4Port,0x10,0x80);
+       temp=(UCHAR)GetReg1(P3c4,0x16);
+       temp=temp&0xC3;
+       SetReg1(P3d4,0x35,temp);
+}
+                       
+USHORT GetRatePtrCRT2(ULONG ROMAddr, USHORT ModeNo)
+{                                                              //return bit0=>0:standard mode 1:extended mode
+       SHORT   index;                          //               bit1=>0:crt2 no support this mode
+       USHORT  temp;                           //                         1:crt2 support this mode 
+       USHORT  ulRefIndexLength;
+       USHORT  temp1;
+       SHORT   LCDRefreshIndex[4]={0x0,0x0,0x03,0x01};
+                                                               // LCDPanel:no lcd,800x600,1024x768,1280x1024
+       if(ModeNo<0x14) return(0);      // Mode No <= 13h then return
+
+       index=GetReg1(P3d4,0x33);               // Get 3d4 CRTC33
+       index=index>>SelectCRT2Rate;    //For CRT2,cl=SelectCRT2Rate=4, shr ah,cl                
+       index=index&0x0F;                               // Frame rate index
+       if(index!=0) index--;
+       
+       if(IF_DEF_TRUMPION==1){
+               if(VBInfo&SetSimuScanMode){
+                       index=0;
+               }
+       }
+       if(SetFlag&ProgrammingCRT2){
+               if(VBInfo&SetCRT2ToLCD){
+                       if(IF_DEF_LVDS==0){
+                               temp=LCDResInfo;
+                               temp1=LCDRefreshIndex[temp];
+                               if(index>temp1){
+                                       index=temp1;
+                               }
+                       }else{
+                               index=0;
+                       }                       
+               }       
+       }
+       
+       REFIndex=*((USHORT *)(ROMAddr+ModeIDOffset+0x04));      // si+Ext_point
+
+       ulRefIndexLength =Ext2StructSize;
+       do {
+               temp=*((USHORT *)(ROMAddr+REFIndex));                   // di => REFIndex
+               if(temp==0xFFFF) break;
+               temp=temp&ModeInfoFlag;
+               if(temp<ModeType) break;
+
+               REFIndex=REFIndex+ulRefIndexLength;                             // rate size
+               index--;
+               if(index<0){
+                       if(!(VBInfo&SetCRT2ToRAMDAC)){
+                               if(VBInfo&SetInSlaveMode){
+                                       temp1=*((USHORT *)(ROMAddr+REFIndex+0-Ext2StructSize));
+                                       if(temp1&InterlaceMode){
+                                               index=0;         
+                                       }               
+                               }
+                       }
+               }       
+       } while(index>=0);
+
+       REFIndex=REFIndex-ulRefIndexLength;                                     // rate size
+       
+       if((SetFlag&ProgrammingCRT2)){
+               temp1=AjustCRT2Rate(ROMAddr);
+       }else{
+               temp1=0;
+       }
+
+       return(0x01|(temp1<<1));
+}
+
+BOOLEAN AjustCRT2Rate(ULONG ROMAddr)
+{
+       USHORT tempbx=0,tempax,temp;
+       USHORT tempextinfoflag;
+       tempax=0;
+
+       if(IF_DEF_LVDS==0){
+               if(VBInfo&SetCRT2ToRAMDAC){
+                       tempax=tempax|SupportRAMDAC2;
+               }
+               if(VBInfo&SetCRT2ToLCD){
+                       tempax=tempax|SupportLCD;
+                       if(LCDResInfo!=Panel1280x1024){
+                               temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
+                               if(temp>=9){
+                                       tempax=0;
+                               }
+                       }
+               }
+               if(VBInfo&(SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)){
+                       tempax=tempax|SupportTV;
+                       if(!(VBInfo&SetPALTV)){
+                               tempextinfoflag=*((USHORT *)(ROMAddr+REFIndex+0x0)); //di+Ext_InfoFlag
+                               if(tempextinfoflag&NoSupportSimuTV){
+                                       if(VBInfo&SetInSlaveMode){
+                                               if(!(VBInfo&SetNotSimuTVMode)){
+                                                       return 0;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               tempbx=*((USHORT *)(ROMAddr+ModeIDOffset+0x04));        // si+Ext_point
+       }else{  //for LVDS
+               if(VBInfo&SetCRT2ToLCD){
+                       tempax=tempax|SupportLCD;
+                       temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
+                       if(temp>0x08){ //1024x768
+                               return 0;
+                       }
+                       if(LCDResInfo<Panel1024x768){
+                               if(temp>0x07){ //800x600
+                                       return 0;
+                               }
+                               if(temp==0x04){ //512x384
+                                       return 0;
+                               }
+                       }
+               }
+       }
+
+       for(;REFIndex>tempbx;REFIndex-=Ext2StructSize){
+               tempextinfoflag=*((USHORT *)(ROMAddr+REFIndex+0x0)); //di+Ext_InfoFlag
+               if(tempextinfoflag&tempax){
+                       return 1;
+               }
+       } 
+       for(REFIndex=tempbx;;REFIndex+=Ext2StructSize){
+               tempextinfoflag=*((USHORT *)(ROMAddr+REFIndex+0x0)); //di+Ext_InfoFlag
+               if(tempextinfoflag==0x0FFFF){
+                       return 0;
+               }
+               if(tempextinfoflag&tempax){
+                       return 1;
+               }
+       }
+       return(FALSE);
+}
+
+VOID SaveCRT2Info(USHORT ModeNo){
+       USHORT temp1,temp2,temp3;
+       temp1=(VBInfo&SetInSlaveMode)>>8;
+       temp2=~(SetInSlaveMode>>8);
+       temp3=(UCHAR)GetReg1(P3d4,0x31);
+       temp3=((temp3&temp2)|temp1);
+       SetReg1(P3d4,0x31,(USHORT)temp3);
+       temp3=(UCHAR)GetReg1(P3d4,0x35);
+       temp3=temp3&0xF3;
+       SetReg1(P3d4,0x35,(USHORT)temp3);
+}
+
+VOID DisableLockRegs(){
+       UCHAR temp3;
+       temp3=(UCHAR)GetReg1(P3c4,0x32);
+       temp3=temp3&0xDF;
+       SetReg1(P3c4,0x32,(USHORT)temp3);
+}
+
+VOID DisableCRT2(){
+       UCHAR temp3;
+       temp3=(UCHAR)GetReg1(P3c4,0x1E);
+       temp3=temp3&0xDF;
+       SetReg1(P3c4,0x1E,(USHORT)temp3);
+}
+
+void DisableBridge(USHORT      BaseAddr)
+{
+       USHORT  Part2Port,Part1Port;
+       Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+
+       if(IF_DEF_LVDS==0){
+               SetRegANDOR(Part2Port,0x00,0xDF,0x00);  //Set Part2 Index0 D[5]=0
+               DisableLockRegs();      // SR 32 
+               DisableCRT2();  // SR 1E
+       }else{
+               DisableLockRegs();
+               DisableCRT2();
+               if(IF_DEF_TRUMPION==0){
+                       UnLockCRT2(BaseAddr);
+                       SetRegANDOR(Part1Port,0x02,0xFF,0x40); //set Part1Port ,index 2, D6=1,
+               }
+       }
+}
+
+VOID GetCRT2Data(ULONG ROMAddr,USHORT ModeNo)
+{
+       if(IF_DEF_LVDS==0){ //301
+               GetCRT2Data301(ROMAddr,ModeNo);
+               return;
+       }else{ //LVDS
+               GetCRT2DataLVDS(ROMAddr,ModeNo);
+               return;
+       }
+}
+
+VOID GetCRT2DataLVDS(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempax,tempbx,OldREFIndex;       
+
+       OldREFIndex=(USHORT)REFIndex;                   //push di
+       GetResInfo(ROMAddr,ModeNo);
+       GetCRT2Ptr(ROMAddr,ModeNo);
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex));
+       tempax=tempax&0x0FFF;
+       VGAHT=tempax;
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex+1));
+       tempax=tempax>>4;
+       tempax=tempax&0x07FF;
+       VGAVT=tempax;
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex+3));
+       tempax=tempax&0x0FFF;
+       tempbx=*((USHORT *)(ROMAddr+REFIndex+4));
+       tempbx=tempbx>>4;
+       tempbx=tempbx&0x07FF;
+
+       HT=tempax;
+       VT=tempbx;
+
+       if(IF_DEF_TRUMPION==0){
+               if(VBInfo&SetCRT2ToLCD){
+                       if(!(LCDInfo&LCDNonExpanding)){
+                               if(LCDResInfo==Panel800x600){
+                                       tempax=800;
+                                       tempbx=600;
+                               }else if(LCDResInfo==Panel1024x768){
+                                       tempax=1024;
+                                       tempbx=768;
+                               }else{
+                                       tempax=1280;
+                                       tempbx=1024;
+                               }
+                               HDE=tempax;
+                               VDE=tempbx;
+                       }
+               }
+       }
+       REFIndex=OldREFIndex;           //pop di
+       return;
+}
+
+VOID GetCRT2Data301(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempax,tempbx,modeflag1,OldREFIndex;
+       USHORT tempal,tempah,tempbl;
+       
+       OldREFIndex=(USHORT)REFIndex;                   //push di
+       RVBHRS=50;NewFlickerMode=0;RY1COE=0;
+       RY2COE=0;RY3COE=0;RY4COE=0;
+
+       GetResInfo(ROMAddr,ModeNo);
+       if(VBInfo&SetCRT2ToRAMDAC){
+               GetRAMDAC2DATA(ROMAddr,ModeNo);
+               REFIndex=OldREFIndex;                   //pop di
+               return;
+       }
+       GetCRT2Ptr(ROMAddr,ModeNo);
+
+       tempal=*((UCHAR *)(ROMAddr+REFIndex));
+       tempah=*((UCHAR *)(ROMAddr+REFIndex+4));
+       tempax=tempal|(((tempah<<8)>>7)&0xFF00);
+       RVBHCMAX=tempax;
+
+       tempal=*((UCHAR *)(ROMAddr+REFIndex+1));
+       RVBHCFACT=tempal;
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex+2));
+       VGAHT=(tempax&0x0FFF);
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex+3));
+       VGAVT=((tempax>>4)&0x07FF);
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex+5));
+       tempax=(tempax&0x0FFF);
+       tempbx=*((USHORT *)(ROMAddr+REFIndex+6));
+       tempbx=((tempbx>>4)&0x07FF);
+       tempbl=tempbx&0x00FF;
+
+       if(VBInfo&SetCRT2ToTV){
+               tempax=*((USHORT *)(ROMAddr+REFIndex+5));
+               tempax=(tempax&0x0FFF);
+               HDE=tempax;
+               tempax=*((USHORT *)(ROMAddr+REFIndex+6));
+               tempax=((tempax>>4)&0x07FF);
+               VDE=tempax;
+               //skipp something about hivisiontv
+               tempax=*((USHORT *)(ROMAddr+REFIndex+8));
+               tempbl=(tempax>>8);
+               tempax=tempax&0x0FFF;   
+               modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));     // si+St_ModeFlag
+               if(modeflag1&HalfDCLK){
+                       tempax=*((USHORT *)(ROMAddr+REFIndex+10));
+               }
+               RVBHRS=tempax;
+               NewFlickerMode=(tempbl&0x080);
+
+               tempax=*((USHORT *)(ROMAddr+REFIndex+12));
+               RY1COE=(tempax&0x00FF);
+               RY2COE=((tempax&0xFF00)>>8);
+               tempax=*((USHORT *)(ROMAddr+REFIndex+14));
+               RY3COE=(tempax&0x00FF);
+               RY4COE=((tempax&0xFF00)>>8);
+               if(!(VBInfo&SetPALTV)){ 
+                       tempax=NTSCHT;
+                       tempbx=NTSCVT;
+               }else{
+                       tempax=PALHT;
+                       tempbx=PALVT;
+               } 
+       }
+       HT=tempax;
+       VT=tempbx;
+       if(!(VBInfo&SetCRT2ToLCD)){
+               REFIndex=OldREFIndex;                   //pop di
+               return;
+       }
+
+       tempax=1024;
+       if(VGAVDE==350){                //cx->VGAVDE
+               tempbx=560;
+       }else if(VGAVDE==400){
+               tempbx=640;
+       }else{
+               tempbx=768;
+       }
+
+       if(LCDResInfo==Panel1280x1024){
+               tempax=1280;                    
+               if(VGAVDE==360){
+                       tempbx=768;
+               }else if(VGAVDE==375){
+                       tempbx=800;              
+               }else if(VGAVDE==405){
+                       tempbx=864;              
+               }else{
+                       tempbx=1024;
+               }       
+       }
+
+       HDE=tempax;
+       VDE=tempbx; 
+       REFIndex=OldREFIndex;           //pop di
+       return; 
+}
+
+VOID GetResInfo(ULONG ROMAddr,USHORT ModeNo)
+{ 
+       USHORT temp,xres,yres,modeflag1;
+       if(ModeNo<=0x13){
+               temp=(USHORT)*((UCHAR *)(ROMAddr+ModeIDOffset+0x05));   // si+St_ResInfo
+               xres=StResInfo[temp][0];
+               yres=StResInfo[temp][1];
+       }else{
+               temp=(USHORT)*((UCHAR *)(ROMAddr+ModeIDOffset+0x09));   // si+Ext_ResInfo
+               xres=ModeResInfo[temp][0];      //xres->ax
+               yres=ModeResInfo[temp][1];      //yres->bx
+               modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));     // si+St_ModeFlag
+               if(modeflag1&HalfDCLK){ xres=xres*2;}
+               if(modeflag1&DoubleScanMode){yres=yres*2;}
+       }
+       if(!(LCDResInfo==Panel1024x768)){
+               if(yres==400) yres=405;
+               if(yres==350) yres=360;
+               if(SetFlag&LCDVESATiming){
+                       if(yres==360) yres=375; 
+               }                               
+       }
+       VGAHDE=xres;
+       HDE=xres;
+       VGAVDE=yres;
+       VDE=yres;
+}
+
+VOID GetLVDSDesData(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT old_REFIndex,tempax;
+
+       old_REFIndex=(USHORT)REFIndex; //push di
+       REFIndex=GetLVDSDesPtr(ROMAddr,ModeNo);
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex));
+       tempax=tempax&0x0FFF;
+       LCDHDES=tempax;
+
+       if(LCDInfo&LCDNonExpanding){ //hw walk-a-round
+               if(LCDResInfo>=Panel1024x768){
+                       if(ModeNo<=0x13){
+                               LCDHDES=320;
+                       }
+               }
+       }
+
+       tempax=*((USHORT *)(ROMAddr+REFIndex+1));
+       tempax=tempax>>4;
+       tempax=tempax&0x07FF;
+       LCDVDES=tempax;
+
+       REFIndex=old_REFIndex; //pop di
+       return; 
+}
+
+
+VOID GetRAMDAC2DATA(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempax,tempbx,tempbh,modeflag1,t1=0,t2;
+       RVBHCMAX=1;RVBHCFACT=1;
+       if(ModeNo<=0x13){
+               tempax=*((UCHAR *)(ROMAddr+REFIndex+10)); 
+               tempbx=*((USHORT *)(ROMAddr+REFIndex+16));
+       }else{
+               t1=*((UCHAR *)(ROMAddr+REFIndex+0x2)); //Ext_CRT1CRTC=2
+               t1=t1&0x03F;    //[06/29/2000] fix bug for vbios >=v1.07.00
+               t1=t1*CRT1Len;
+               REFIndex=*((USHORT *)(ROMAddr+0x204));          // Get CRT1Table
+               REFIndex=REFIndex+t1;
+               t1=*((UCHAR *)(ROMAddr+REFIndex+0));
+               t2=*((UCHAR *)(ROMAddr+REFIndex+14));
+               tempax=(t1&0xFF)|((t2&0x03)<<8);
+               tempbx=*((USHORT *)(ROMAddr+REFIndex+6));
+               t1=*((UCHAR *)(ROMAddr+REFIndex+13));
+               t1=(t1&0x01)<<2;
+       }
+
+       tempbh=tempbx>>8;
+       tempbh=((tempbh&0x20)>>4)|(tempbh&0x01);
+       tempbh=tempbh|t1;
+       tempbx=(tempbx&0xFF)|(tempbh<<8);
+       tempax=tempax+5;
+       modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));     // si+St_ModeFlag
+       if(modeflag1&Charx8Dot){
+               tempax=tempax*8;
+       }else{
+               tempax=tempax*9;
+       }
+
+       VGAHT=tempax;
+       HT=tempax;
+       tempbx++;
+       VGAVT=tempbx;
+       VT=tempbx;
+
+}
+
+VOID GetCRT2Ptr(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempcl,tempbx,tempal,tempax,CRT2PtrData;
+
+       if(IF_DEF_LVDS==0){
+               if(VBInfo&SetCRT2ToLCD){                //LCD
+                       tempbx=0; //default tempbx=0 -> ExtLCD1Data
+                       tempcl=LCDDataLen;
+                       if(LCDResInfo==Panel1024x768){
+                               tempbx=0;
+                       }else if(LCDResInfo==Panel1280x1024){
+                               tempbx=1;
+                       }
+                       if(!(SetFlag&LCDVESATiming)) tempbx+=5;
+               }else if(VBInfo&SetPALTV){
+                       tempcl=TVDataLen;
+                       tempbx=3;
+               }else{
+                       tempbx=4;
+                       tempcl=TVDataLen;
+               }       
+               if(SetFlag&TVSimuMode){
+                       tempbx=tempbx+4;
+               }
+               if(ModeNo<=0x13){
+                       tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
+               }else{
+                       tempal=*((UCHAR *)(ROMAddr+REFIndex+4));         //di+Ext_CRT2CRTC
+               }
+               tempal=tempal&0x1F;
+
+               tempax=tempal*tempcl;
+               REFIndex=*((USHORT *)(ROMAddr+tempbx*2+0x20E));
+               REFIndex+=tempax;
+       }else{ //for LVDS
+
+               tempcl=LVDSDataLen;
+               tempbx=LCDResInfo-Panel800x600;
+               if(LCDInfo&LCDNonExpanding){
+                       tempbx=tempbx+3;
+               }
+               if(ModeNo<=0x13){
+                       tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
+               }else{
+                       tempal=*((UCHAR *)(ROMAddr+REFIndex+0x04));             // di+Ext_CRT2CRTC
+               }
+               tempal=tempal&0x1F;
+               tempax=tempal*tempcl;
+               CRT2PtrData=*((USHORT *)(ROMAddr+ADR_CRT2PtrData)); //ADR_CRT2PtrData is defined in init.def
+               REFIndex=*((USHORT *)(ROMAddr+CRT2PtrData+tempbx*2));
+               REFIndex+=tempax;
+       }
+}
+
+VOID UnLockCRT2(USHORT BaseAddr)
+{
+       UCHAR temp3;
+       USHORT  Part1Port;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       temp3=(UCHAR)GetReg1(Part1Port,0x24);
+       temp3=temp3|0x01;
+       SetReg1(Part1Port,0x24,(USHORT)temp3);
+}
+
+VOID SetCRT2ModeRegs(USHORT BaseAddr,USHORT ModeNo)
+{
+       USHORT i,j;
+       USHORT tempah=0,temp3;
+       SHORT   tempcl;
+       USHORT  Part4Port;
+       USHORT  Part1Port;
+       Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       for(i=0,j=4;i<3;i++,j++){
+               SetReg1(Part1Port,j,0);
+       }
+       
+       tempcl=(USHORT)ModeType;
+       if(ModeNo>0x13){
+               tempcl=tempcl-ModeVGA; 
+               if(tempcl>=0){
+                       tempah=((0x010>>tempcl)|0x080);
+               }
+       }else{
+               tempah=0x080;
+       }
+
+       if(VBInfo&SetInSlaveMode){
+               tempah=(tempah^0x0A0);
+       }
+       if(VBInfo&CRT2DisplayFlag){
+               tempah=0;
+       }
+       SetReg1(Part1Port,0,tempah);
+
+       if(IF_DEF_LVDS==0){ //301
+               tempah=0x01;
+               if(!(VBInfo&SetInSlaveMode)){
+                       tempah=(tempah|0x02);
+               }
+               if(!(VBInfo&SetCRT2ToRAMDAC)){
+                       tempah=(tempah^0x05);
+                       if(!(VBInfo&SetCRT2ToLCD)){
+                               tempah=(tempah^0x01);
+                       }
+               }
+               tempah=(tempah<<5)&0xFF;
+               if(VBInfo&CRT2DisplayFlag){
+                       tempah=0;
+               }
+               SetReg1(Part1Port,0x01,tempah);
+
+               tempah=tempah>>5;
+               if((ModeType==ModeVGA)&&(!(VBInfo&SetInSlaveMode))){
+                       tempah=tempah|0x010;
+               }
+               if(LCDResInfo!=Panel1024x768){
+                       tempah=tempah|0x080;
+               }
+               if(VBInfo&SetCRT2ToTV){
+                       if(VBInfo&SetInSlaveMode){
+                               tempah=tempah|0x020;
+                       }
+               }
+       
+               temp3=(UCHAR)GetReg1(Part4Port,0x0D);
+               temp3=temp3&(~0x0BF);
+               temp3=temp3|tempah;
+               SetReg1(Part4Port,0x0D,(USHORT)temp3);
+       }else{ //LVDS
+               tempah=0;
+               if(!(VBInfo&SetInSlaveMode)){
+                       tempah=tempah|0x02;
+               }
+               tempah=(tempah<<5)&0x0FF;
+               if(VBInfo&CRT2DisplayFlag){
+                       tempah=0;
+               }
+               SetReg1(Part1Port,0x01,tempah);
+       }
+}
+
+VOID SetGroup1(USHORT  BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+               PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       if(IF_DEF_LVDS==0){     //301
+               SetGroup1_301(BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+       }else{  //LVDS
+               SetGroup1_LVDS(BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+       }
+}
+VOID SetGroup1_LVDS(USHORT     BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+               PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT temp1,temp2,tempcl,tempch,tempbh,tempal,tempah,tempax,tempbx;
+       USHORT tempcx,OldREFIndex,lcdhdee;
+       USHORT  Part1Port;
+       USHORT temppush1,temppush2;
+       unsigned long int tempeax,tempebx,tempecx,templong;
+
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       OldREFIndex=(USHORT)REFIndex;           //push di
+
+       SetCRT2Offset(Part1Port,ROMAddr);
+       SetCRT2FIFO(Part1Port,ROMAddr,ModeNo,HwDeviceExtension);
+       SetCRT2Sync(BaseAddr,ROMAddr,ModeNo);
+
+       temp1=(VGAHT-1)&0x0FF;                          //BTVGA2HT 0x08,0x09
+       SetReg1(Part1Port,0x08,temp1);
+       temp1=(((VGAHT-1)&0xFF00)>>8)<<4;
+       SetRegANDOR(Part1Port,0x09,~0x0F0,temp1);
+       
+       temp1=(VGAHDE+12)&0x0FF;                        //BTVGA2HDEE 0x0A,0x0C
+       SetReg1(Part1Port,0x0A,temp1);
+       
+       temp1=VGAHDE+12;                        //bx    BTVGA@HRS 0x0B,0x0C
+       temp2=(VGAHT-VGAHDE)>>2;        //cx
+       temp1=temp1+temp2;
+       temp2=(temp2<<1)+temp1;
+       tempcl=temp2&0x0FF;
+                       //
+       SetReg1(Part1Port,0x0B,(USHORT)(temp1&0x0FF));
+       tempah=(temp1&0xFF00)>>8;
+       tempbh=((((VGAHDE+12)&0xFF00)>>8)<<4)&0x0FF;
+       tempah=tempah|tempbh;
+       SetReg1(Part1Port,0x0C,tempah);
+       SetReg1(Part1Port,0x0D,tempcl);         //BTVGA2HRE 0x0D
+       tempcx=(VGAVT-1);
+       tempah=tempcx&0x0FF;
+       SetReg1(Part1Port,0x0E,tempah);         //BTVGA2TV 0x0E,0x12
+       tempbx=VGAVDE-1;
+       tempah=tempbx&0x0FF;
+       SetReg1(Part1Port,0x0F,tempah);         //BTVGA2VDEE 0x0F,0x12
+       tempah=((tempbx&0xFF00)<<3)>>8;
+       tempah=tempah|((tempcx&0xFF00)>>8);
+       SetReg1(Part1Port,0x12,tempah);
+       
+       tempbx=(VGAVT+VGAVDE)>>1;                               //BTVGA2VRS             0x10,0x11
+       tempcx=((VGAVT-VGAVDE)>>4)+tempbx+1;    //BTVGA2VRE             0x11
+                       //
+       tempah=tempbx&0x0FF;
+       SetReg1(Part1Port,0x10,tempah);
+       tempbh=(tempbx&0xFF00)>>8;
+       tempah=((tempbh<<4)&0x0FF)|(tempcx&0x0F);
+       SetReg1(Part1Port,0x11,tempah);
+
+       SetRegANDOR(Part1Port,0x13,~0x03C,tempah);
+
+       tempax=LCDHDES;
+       tempbx=HDE;
+       tempcx=HT;
+       tempcx=tempcx-tempbx; //HT-HDE
+       tempax=tempax+tempbx; //lcdhdee
+       tempbx=HT;
+       if(tempax>=tempbx){
+               tempax=tempax-tempbx;
+       }
+
+       lcdhdee=tempax;
+       tempcx=tempcx>>2;               //temp
+       tempcx=tempcx+tempax;   //lcdhrs
+       if(tempcx>=tempbx){
+               tempcx=tempcx-tempbx;
+       }
+
+       tempax=tempcx;
+       tempax=tempax>>3;               //BPLHRS
+       tempah=tempax&0x0FF;
+       SetReg1(Part1Port,0x14,tempah); //Part1_14h
+       tempah=tempah+2;
+       tempah=tempah+0x01F;
+       tempcl=tempcx&0x0FF;
+       tempcl=tempcl&0x07;
+       tempcl=(tempcl<<5)&0xFF; //BPHLHSKEW
+       tempah=tempah|tempcl;
+       SetReg1(Part1Port,0x15,tempah); //Part1_15h
+       tempbx=lcdhdee;                 //lcdhdee
+       tempcx=LCDHDES;                 //lcdhdes
+       tempah=(tempcx&0xFF);
+       tempah=tempah&0x07;             //BPLHDESKEW
+       SetReg1(Part1Port,0x1A,tempah); //Part1_1Ah
+       tempcx=tempcx>>3;               //BPLHDES
+       tempah=(tempcx&0xFF);
+       SetReg1(Part1Port,0x16,tempah); //Part1_16h
+       tempbx=tempbx>>3;               //BPLHDEE
+       tempah=tempbx&0xFF;
+       SetReg1(Part1Port,0x17,tempah); //Part1_17h
+
+       tempcx=VGAVT;
+       tempbx=VGAVDE;
+       tempcx=tempcx-tempbx;           //VGAVT-VGAVDE
+       tempbx=LCDVDES;                         //VGAVDES
+       temppush1=tempbx;                       //push bx temppush1
+       if(IF_DEF_TRUMPION==0){
+               if(LCDResInfo==Panel800x600){
+                       tempax=600;
+               }else{
+                       tempax=768;
+               }
+       }else{
+               tempax=VGAVDE;
+       }
+       tempbx=tempbx+tempax;
+       tempax=VT;                              //VT
+       if(tempbx>=VT){
+               tempbx=tempbx-tempax;
+       }
+       temppush2=tempbx;               //push bx       temppush2
+       tempcx=tempcx>>1;
+       tempbx=tempbx+tempcx;
+       tempbx++;               //BPLVRS
+       if(tempbx>=tempax){
+               tempbx=tempbx-tempax;
+       }
+       tempah=tempbx&0xFF;
+       SetReg1(Part1Port,0x18,tempah); //Part1_18h
+       tempcx=tempcx>>3;
+       tempcx=tempcx+tempbx;
+       tempcx++;                                //BPLVRE
+       tempah=tempcx&0xFF;
+       tempah=tempah&0x0F;
+       tempah=tempah|0x030;
+       SetRegANDOR(Part1Port,0x19,~0x03F,tempah); //Part1_19h
+       tempbh=(tempbx&0xFF00)>>8;
+       tempbh=tempbh&0x07;
+       tempah=tempbh;
+       tempah=(tempah<<3)&0xFF;                //BPLDESKEW =0
+       tempbx=VGAVDE;
+       if(tempbx!=VDE){
+               tempah=tempah|0x40;
+       }
+       SetRegANDOR(Part1Port,0x1A,0x07,tempah); //Part1_1Ah
+       tempecx=VGAVT;
+       tempebx=VDE;
+       tempeax=VGAVDE;
+       tempecx=tempecx-tempeax;                //VGAVT-VGAVDE
+       tempeax=tempeax*64;
+       templong=tempeax/tempebx;
+       if(templong*tempebx<tempeax){
+               templong++;
+       }
+       tempebx=templong;               //BPLVCFACT
+       if(SetFlag&EnableLVDSDDA){
+               tempebx=tempebx&0x03F;
+       }
+       tempah=(USHORT)(tempebx&0x0FF);
+       SetReg1(Part1Port,0x1E,tempah); //Part1_1Eh
+       tempbx=temppush2;               //pop bx temppush2 BPLVDEE
+       tempcx=temppush1;               //pop cx temppush1 NPLVDES
+       tempbh=(tempbx&0xFF00)>>8;
+       tempah=tempah&0x07;
+       tempah=tempbh;
+       tempah=tempah<<3;
+       tempch=(tempcx&0xFF00)>>8;
+       tempch=tempah&0x07;
+       tempah=tempah|tempch;
+       SetReg1(Part1Port,0x1D,tempah); //Part1_1Dh
+       tempah=tempbx&0xFF;
+       SetReg1(Part1Port,0x1C,tempah); //Part1_1Ch
+       tempah=tempcx&0xFF;
+       SetReg1(Part1Port,0x1B,tempah); //Part1_1Bh
+       
+       tempecx=VGAHDE;
+       tempebx=HDE;
+       tempeax=tempecx;
+       tempeax=tempeax<<6;
+       tempeax=tempeax<<10;
+       tempeax=tempeax/tempebx;
+       if(tempebx==tempecx){
+               tempeax=65535;
+       }
+       tempecx=tempeax;
+       tempeax=VGAHT;
+       tempeax=tempeax<<6;
+       tempeax=tempeax<<10;
+       tempeax=tempeax/tempecx;
+       tempecx=tempecx<<16;
+       tempeax=tempeax-1;
+       tempax=(USHORT)(tempeax&0x00FFFF);
+       tempcx=tempax;
+       tempah=tempcx&0x0FF;
+       SetReg1(Part1Port,0x1F,tempah); //Part1_1Fh
+       tempbx=VDE;
+       tempbx--;                                //BENPLACCEND
+       if(SetFlag&EnableLVDSDDA){
+               tempbx=1;
+       }
+       tempah=(tempbx&0xFF00)>>8;
+       tempah=(tempah<<3)&0xFF;
+       tempch=(tempcx&0xFF00)>>8;
+       tempch=tempch&0x07;
+       tempah=tempah|tempch;
+       SetReg1(Part1Port,0x20,tempah); //Part1_20h
+       tempah=tempbx&0xFF;
+       SetReg1(Part1Port,0x21,tempah); //Part1_21h
+       tempecx=tempecx>>16;                     //BPLHCFACT
+       temp1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
+       if(temp1&HalfDCLK){
+               tempecx=tempecx>>1;
+       }
+       tempcx=(USHORT)(tempecx&0x0FFFF);
+       tempah=(tempcx&0xFF00)>>8;
+       SetReg1(Part1Port,0x22,tempah); //Part1_22h
+       tempah=tempcx&0x0FF;
+       SetReg1(Part1Port,0x23,tempah); //Part1_23h
+       if(IF_DEF_TRUMPION==1){
+               tempal=(USHORT)*((UCHAR *)(ROMAddr+ModeIDOffset+0x05)); // si+St_ResInfo
+               if(ModeNo>0x13){
+                       SetFlag=SetFlag|ProgrammingCRT2;
+                       GetRatePtrCRT2(ROMAddr,ModeNo);
+                       tempal=*((UCHAR *)(ROMAddr+REFIndex+0x04));             // di+Ext_CRT2CRTC
+                       tempal=tempal&0x1F;
+               }
+               tempah=0x80;
+               tempal=tempal*tempah;
+               REFIndex= offset_Zurac; //offset Zurac need added in rompost.asm
+               REFIndex=REFIndex+tempal;
+               SetTPData();    //this function not implemented yet
+               SetTPData();
+               SetTPData();
+               SetTPData();
+               SetTPData();
+               SetTPData();
+               SetTPData();
+               SetTPData();
+               SetTPData();
+       }
+       REFIndex=OldREFIndex;                   //pop di
+       return;
+}
+
+VOID SetTPData(VOID)
+{
+       return;
+}
+
+VOID SetGroup1_301(USHORT      BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+               PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT temp1,temp2,tempcl,tempch,tempbl,tempbh,tempal,tempah,tempax,tempbx;
+       USHORT tempcx,OldREFIndex;
+       USHORT  Part1Port;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       OldREFIndex=(USHORT)REFIndex;                   //push di
+
+       SetCRT2Offset(Part1Port,ROMAddr);
+       SetCRT2FIFO(Part1Port,ROMAddr,ModeNo,HwDeviceExtension);
+       SetCRT2Sync(BaseAddr,ROMAddr,ModeNo);
+
+       GetCRT1Ptr(ROMAddr);
+
+       temp1=(VGAHT-1)&0x0FF;                          //BTVGA2HT 0x08,0x09
+       SetReg1(Part1Port,0x08,temp1);
+       temp1=(((VGAHT-1)&0xFF00)>>8)<<4;
+       SetRegANDOR(Part1Port,0x09,~0x0F0,temp1);
+       temp1=(VGAHDE+12)&0x0FF;                                        //BTVGA2HDEE 0x0A,0x0C
+       SetReg1(Part1Port,0x0A,temp1);
+       
+       temp1=VGAHDE+12;                        //bx    BTVGA@HRS 0x0B,0x0C
+       temp2=(VGAHT-VGAHDE)>>2;        //cx
+       temp1=temp1+temp2;
+       temp2=(temp2<<1)+temp1;
+       tempcl=temp2&0x0FF;
+       if(VBInfo&SetCRT2ToRAMDAC){
+               tempbl=*((UCHAR *)(ROMAddr+REFIndex+4));        //di+4
+               tempbh=*((UCHAR *)(ROMAddr+REFIndex+14));       //di+14
+               temp1=((tempbh>>6)<<8)|tempbl;                          //temp1->bx
+               temp1=(temp1-1)<<3;                                             
+               tempcl=*((UCHAR *)(ROMAddr+REFIndex+5));        //di+5
+               tempch=*((UCHAR *)(ROMAddr+REFIndex+15));       //di+15
+               tempcl=tempcl&0x01F;
+               tempch=(tempch&0x04)<<(6-2);
+               tempcl=((tempcl|tempch)-1)<<3;   
+       }
+       SetReg1(Part1Port,0x0B,(USHORT)(temp1&0x0FF));
+       tempah=(temp1&0xFF00)>>8;
+       tempbh=((((VGAHDE+12)&0xFF00)>>8)<<4)&0x0FF;
+       tempah=tempah|tempbh;
+       SetReg1(Part1Port,0x0C,tempah);
+       SetReg1(Part1Port,0x0D,tempcl);         //BTVGA2HRE 0x0D
+       tempcx=(VGAVT-1);
+       tempah=tempcx&0x0FF;
+       SetReg1(Part1Port,0x0E,tempah);         //BTVGA2TV 0x0E,0x12
+       tempbx=VGAVDE-1;
+       tempah=tempbx&0x0FF;
+       SetReg1(Part1Port,0x0F,tempah);         //BTVGA2VDEE 0x0F,0x12
+       tempah=((tempbx&0xFF00)<<3)>>8;
+       tempah=tempah|((tempcx&0xFF00)>>8);
+       SetReg1(Part1Port,0x12,tempah);
+       
+       tempbx=(VGAVT+VGAVDE)>>1;                               //BTVGA2VRS             0x10,0x11
+       tempcx=((VGAVT-VGAVDE)>>4)+tempbx+1;    //BTVGA2VRE             0x11
+       if(VBInfo&SetCRT2ToRAMDAC){
+               tempbx=*((UCHAR *)(ROMAddr+REFIndex+8));         //di+8
+               temp1=*((UCHAR *)(ROMAddr+REFIndex+7));  //di+7
+               if(temp1&0x04){
+                       tempbx=tempbx|0x0100;
+               }
+               if(temp1&0x080){
+                       tempbx=tempbx|0x0200;
+               }
+               temp1=*((UCHAR *)(ROMAddr+REFIndex+13));         //di+13
+               if(temp1&0x08){
+                       tempbx=tempbx|0x0400;
+               }
+               tempcl= *((UCHAR *)(ROMAddr+REFIndex+9));        //di+9
+               tempcx=(tempcx&0xFF00)|(tempcl&0x00FF);
+       }
+       tempah=tempbx&0x0FF;
+       SetReg1(Part1Port,0x10,tempah);
+       tempbh=(tempbx&0xFF00)>>8;
+       tempah=((tempbh<<4)&0x0FF)|(tempcx&0x0F);
+       SetReg1(Part1Port,0x11,tempah);
+
+       if(HwDeviceExtension->jChipID == SIS_Glamour)
+       {
+               tempah=0x10;
+               if((LCDResInfo!=Panel1024x768)&&(LCDResInfo==Panel1280x1024)){
+                       tempah=0x20;            
+               }       
+       }else{
+               tempah=0x20;
+       }
+       if(VBInfo&SetCRT2ToTV){
+               tempah=0x08;
+       }
+       
+       SetRegANDOR(Part1Port,0x13,~0x03C,tempah);
+
+       if(!(VBInfo&SetInSlaveMode)){
+               REFIndex=OldREFIndex;
+               return;
+       }
+       if(VBInfo&SetCRT2ToTV){
+               tempax=0xFFFF;          
+       }else{
+               tempax=GetVGAHT2();
+       }
+       tempcl=0x08;                                            //Reg 0x03 Horozontal Total
+       temp1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); // si+St_ModeFlag
+       if(!(temp1&Charx8Dot)){                                                         //temp1->St_ModeFlag
+               tempcl=0x09;
+       }
+       if(tempax>=VGAHT){
+               tempax=VGAHT;
+       }
+       if(temp1&HalfDCLK){
+               tempax=tempax>>1;
+       }
+       tempax=(tempax/tempcl)-5;
+       tempbl=tempax;
+       tempah=0xFF;                    //set MAX HT
+       SetReg1(Part1Port,0x03,tempah);
+
+       tempax=VGAHDE;                  //0x04 Horizontal Display End
+       if(temp1&HalfDCLK){
+               tempax=tempax>>1;
+       }
+       tempax=(tempax/tempcl)-1;
+       tempbh=tempax;
+       SetReg1(Part1Port,0x04,tempax);
+       
+       tempah=tempbh;
+       if(VBInfo&SetCRT2ToTV){
+               tempah=tempah+2;
+       }
+       SetReg1(Part1Port,0x05,tempah); //0x05 Horizontal Display Start
+       SetReg1(Part1Port,0x06,0x03);   //0x06 Horizontal Blank end
+                                                                                        //0x07 horizontal Retrace Start
+       tempcx=(tempbl+tempbh)>>1;
+       tempah=(tempcx&0xFF)+2;
+
+       if(VBInfo&SetCRT2ToTV){
+               tempah=tempah-1;        
+               if(!(temp1&HalfDCLK)){
+                       if((temp1&Charx8Dot)){
+                               tempah=tempah+4;
+                               if(VGAHDE>=800){
+                                       tempah=tempah-6;
+                               }
+                       }
+               }
+       }else{
+               if(!(temp1&HalfDCLK)){
+                       tempah=tempah-4;
+                       if(VGAHDE>=800){
+                               tempah=tempah-7;
+                               if(ModeType==ModeEGA){
+                                       if(VGAVDE==1024){
+                                               tempah=tempah+15;
+                                               if(LCDResInfo!=Panel1280x1024){
+                                                       tempah=tempah+7;
+                                               }       
+                                       }        
+                               }
+                               if(VGAHDE>=1280){
+                                       tempah=tempah+28;
+                               }
+                       }
+               }
+       }
+       
+       SetReg1(Part1Port,0x07,tempah);//0x07 Horizontal Retrace Start 
+       
+       SetReg1(Part1Port,0x08,0);       //0x08 Horizontal Retrace End
+       SetReg1(Part1Port,0x18,0x03); //0x18 SR08
+       SetReg1(Part1Port,0x19,0); //0x19 SR0C
+       SetReg1(Part1Port,0x09,0xFF); //0x09 Set Max VT
+       
+       tempcx=0x121;
+       tempcl=0x21;
+       tempch=0x01;
+       tempbx=VGAVDE;                                   //0x0E Virtical Display End
+       if(tempbx==360) tempbx=350;
+       if(tempbx==375) tempbx=350;
+       if(tempbx==405) tempbx=400;     
+       tempbx--;
+       tempah=tempbx&0x0FF;
+       SetReg1(Part1Port,0x0E,tempah);
+       SetReg1(Part1Port,0x10,tempah);//0x10 vertical Blank Start
+       tempbh=(tempbx&0xFF00)>>8;
+       if(tempbh&0x01){
+               tempcl=tempcl|0x0A;
+       }
+       tempah=0;tempal=0x0B;
+       if(temp1&DoubleScanMode){
+               tempah=tempah|0x080;
+       }
+       if(tempbh&0x02){
+               tempcl=tempcl|0x040;
+               tempah=tempah|0x020;
+       }
+       SetReg1(Part1Port,0x0B,tempah);
+       if(tempbh&0x04){
+               tempch=tempch|0x06; 
+       }
+
+       SetReg1(Part1Port,0x11,0);      //0x11 Vertival Blank End
+       
+       tempax=VGAVT-tempbx;            //0x0C Vertical Retrace Start 
+       tempax=tempax>>2;
+       temp2=tempax;                           //push ax
+       tempax=tempax<<1;
+       tempbx=tempax+tempbx;
+       if((SetFlag&TVSimuMode)&&(VBInfo&SetPALTV)&&(VGAHDE==800)){
+               tempbx=tempbx+40;
+       }
+       tempah=(tempbx&0x0FF);
+       SetReg1(Part1Port,0x0C,tempah);
+       tempbh=(tempbx&0xFF00)>>8;
+       if(tempbh&0x01){
+               tempcl=tempcl|0x04;
+       }
+       if(tempbh&0x02){
+               tempcl=tempcl|0x080;
+       }
+       if(tempbh&0x04){
+               tempch=tempch|0x08;
+       }
+
+       tempax=temp2;                   //pop ax
+       tempax=(tempax>>2)+1;
+       tempbx=tempbx+tempax;
+       tempah=(tempbx&0x0FF)&0x0F;
+       SetReg1(Part1Port,0x0D,tempah); //0x0D vertical Retrace End
+       tempbl=tempbx&0x0FF;
+       if(tempbl&0x10){
+               tempch=tempch|0x020;
+       }
+       
+       tempah=tempcl;
+       SetReg1(Part1Port,0x0A,tempah); //0x0A CR07
+       tempah=tempch;
+       SetReg1(Part1Port,0x17,tempah); //0x17 SR0A
+       tempax=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));        // si+St_ModeFlag
+       tempah=(tempax&0xFF00)>>8;
+       tempah=(tempah>>1)&0x09;
+       SetReg1(Part1Port,0x16,tempah); //0x16 SR01
+       SetReg1(Part1Port,0x0F,0);              //0x0F CR14
+       SetReg1(Part1Port,0x12,0);              //0x12 CR17
+       SetReg1(Part1Port,0x1A,0);              //0x1A SR0E
+       
+       REFIndex=OldREFIndex;                   //pop di
+}
+
+VOID SetCRT2Offset(USHORT Part1Port,ULONG ROMAddr)
+{
+       USHORT offset;
+       if(VBInfo&SetInSlaveMode){
+        return;
+       }
+       offset=GetOffset(ROMAddr);
+       SetReg1(Part1Port,0x07,(USHORT)(offset&0xFF));
+       SetReg1(Part1Port,0x09,(USHORT)((offset&0xFF00)>>8));
+       SetReg1(Part1Port,0x03,(USHORT)(((offset>>3)&0xFF)+1));
+}
+
+USHORT GetOffset(ULONG ROMAddr)
+{
+       USHORT tempal,temp1,colordepth;
+       tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03)); // si+Ext_ModeInfo
+       tempal=(tempal>>4)&0xFF;
+       ScreenOffset=*((USHORT *)(ROMAddr+0x206));              // Get ScreeOffset table
+       tempal=*((UCHAR *)(ROMAddr+ScreenOffset+tempal));               // get ScreenOffset
+       tempal=tempal&0xFF;
+       temp1=*((UCHAR *)(ROMAddr+REFIndex));    //di+Ext_InfoFlag      
+       if(temp1&InterlaceMode){
+               tempal=tempal<<1;
+       }
+       colordepth=GetColorDepth(ROMAddr);
+       return(tempal*colordepth); 
+}
+
+USHORT GetColorDepth(ULONG ROMAddr)
+{
+       USHORT ColorDepth[6]={1,2,4,4,6,8};
+       USHORT temp;
+       int temp1;
+       temp=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));          // si+St_ModeFlag
+       temp1=(temp&ModeInfoFlag)-ModeEGA;
+       if(temp1<0) temp1=0;
+       return(ColorDepth[temp1]);
+}
+
+VOID SetCRT2FIFO(USHORT        Part1Port,ULONG ROMAddr,USHORT ModeNo,
+                       PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT temp,temp1,temp2,temp3,flag;
+       USHORT vclk2ptr,latencyindex;
+       USHORT oldREFIndex,CRT1ModeNo,oldModeIDOffset;
+       long int longtemp;
+
+       USHORT LatencyFactor[48]={ 88, 80, 78, 72, 70, 00,                       // 64  bit      BQ=2
+                                                          00, 79, 77, 71, 69, 49,                       // 64  bit      BQ=1
+                                                          88, 80, 78, 72, 70, 00,                       // 128 bit      BQ=2
+                                                          00, 72, 70, 64, 62, 44,                       // 128 bit      BQ=1
+                                                          73, 65, 63, 57, 55, 00,                       // 64  bit      BQ=2
+                                                          00, 64, 62, 56, 54, 34,                       // 64  bit      BQ=1
+                                                          78, 70, 68, 62, 60, 00,                       // 128 bit      BQ=2
+                                                          00, 62, 60, 54, 52, 34};                      // 128 bit      BQ=1
+
+       oldREFIndex=(USHORT)REFIndex;                   //push REFIndex(CRT2 now)
+       oldModeIDOffset=(USHORT)ModeIDOffset;   //push ModeIDOffset
+       
+       CRT1ModeNo=(UCHAR)GetReg1(P3d4,0x34);   //get CRT1 ModeNo
+       SearchModeID(ROMAddr,CRT1ModeNo);               //Get ModeID Table
+        
+       GetRatePtr(ROMAddr,CRT1ModeNo);                 //Set REFIndex-> for crt1 refreshrate   
+       temp1=GetVCLK(ROMAddr,CRT1ModeNo,HwDeviceExtension);
+       temp2=GetColorTh(ROMAddr);
+       temp3=GetMCLK(ROMAddr);
+       temp=((USHORT)(temp1*temp2)/temp3);             //temp->bx
+       temp1=(UCHAR)GetReg1(P3c4,0x14);                //SR_14
+       temp1=temp1>>6;
+       temp1=temp1<<1;
+       if(temp1==0) temp1=1;
+       temp1=temp1<<2;                                 //temp1->ax
+
+       longtemp=temp1-temp;
+       
+       temp2=(USHORT)((28*16)/(int)longtemp);  //temp2->cx
+       if(!((temp2*(int)longtemp)==(28*16))) temp2++;
+
+       if( HwDeviceExtension->jChipID == SIS_Glamour ){                
+               temp1=CalcDelay();
+       }else{ //for Trojan and Spartan
+               flag=(UCHAR)GetReg1(P3c4,0x14); //SR_14
+               if(flag&0x80){
+                       latencyindex=12;        //128 bit
+               }else{
+                       latencyindex=0; //64 bit
+               }
+               flag=GetQueueConfig();
+               if(!(flag&0x01)){
+                       latencyindex+=24; //GUI timing =0
+               }
+               if(flag&0x10){
+                       latencyindex+=6;        //BQ =2
+               }
+               latencyindex=latencyindex + (flag>>5);
+               temp1= LatencyFactor[latencyindex];
+               temp1=temp1+15;
+               flag=(UCHAR)GetReg1(P3c4,0x14); //SR_14
+               if(!(flag&0x80)){
+                       temp1=temp1+5;   //64 bit
+               }
+       }       
+                       
+       temp2=temp2+temp1;
+       REFIndex=oldREFIndex;                   //pop REFIndex(CRT2)
+       ModeIDOffset=oldModeIDOffset;   //pop ModeIDOffset
+       
+       vclk2ptr=GetVCLK2Ptr(ROMAddr,ModeNo);
+       temp1=*((USHORT *)(ROMAddr+vclk2ptr+(VCLKLen-2)));
+       temp3=GetColorTh(ROMAddr);
+       longtemp=temp1*temp2*temp3;
+       temp3=GetMCLK(ROMAddr);
+       temp3=temp3<<4;
+       temp2=(int)(longtemp/temp3);
+       if((long int)temp2*(long int)temp3<(long int)longtemp) temp2++; //temp2->cx
+
+       temp1=(UCHAR)GetReg1(Part1Port,0x01);                   //part1port index 01
+
+
+       if( (HwDeviceExtension->jChipID == SIS_Trojan ) && 
+           ((HwDeviceExtension->revision_id & 0xf0) == 0x30) ) /* 630s */
+       {
+               temp1=(temp1&(~0x1F))|0x19;
+       }else
+       {
+               temp1=(temp1&(~0x1F))|0x16;
+       }
+       SetReg1(Part1Port,0x01,temp1);
+
+       if(temp2<=6) temp2=6;
+       if(temp2>0x14) temp2=0x14;
+       temp1=(UCHAR)GetReg1(Part1Port,0x02);                   //part1port index 02
+       temp1=(temp1&(~0x1F))|temp2;
+       SetReg1(Part1Port,0x02,temp1);
+}
+
+USHORT GetVCLK(ULONG ROMAddr,USHORT ModeNo,
+                       PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT tempptr;
+       USHORT temp1;    
+       tempptr=GetVCLKPtr(ROMAddr,ModeNo);
+       temp1=*((USHORT *)(ROMAddr+tempptr+(VCLKLen-2)));
+
+       return temp1;
+}
+
+USHORT GetQueueConfig(void)
+{
+       USHORT tempal,tempbl;
+       ULONG tempeax;
+       
+       SetReg4(0xcf8,0x80000050);
+       tempeax=GetReg3(0xcfc);
+       tempeax=(tempeax>>24)&0x0f;
+       tempbl=(USHORT)tempeax;
+       tempbl=tempbl<<4;
+       
+       SetReg4(0xcf8,0x800000A0);
+       tempeax=GetReg3(0xcfc);
+       tempeax=(tempeax>>24)&0x0f;
+       tempal=(USHORT)tempeax;
+       tempbl=tempbl|tempal;
+       
+       return(tempbl);
+}
+
+USHORT GetVCLKPtr(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempal;
+       tempal=(UCHAR)GetReg2((USHORT)(P3ca+0x02));             //      Port 3cch
+       tempal=((tempal>>2)&0x03);
+       if(ModeNo>0x13){
+               tempal=*((UCHAR *)(ROMAddr+REFIndex+0x03));     //di+Ext_CRTVCLK
+               tempal=tempal&0x03F;
+       }
+       VCLKLen=GetVCLKLen(ROMAddr);
+       tempal=tempal*VCLKLen;
+       tempal=tempal+(*((USHORT *)(ROMAddr+0x208)));   // VCLKData
+       return ((USHORT)tempal);
+}
+
+USHORT GetColorTh(ULONG ROMAddr)
+{
+       USHORT temp;
+       temp=GetColorDepth(ROMAddr);
+       temp=temp>>1;
+       if(temp==0) temp++;
+       return temp;
+}
+
+USHORT GetMCLK(ULONG ROMAddr)
+{
+       USHORT tempmclkptr;
+       USHORT tempmclk;
+       tempmclkptr=GetMCLKPtr(ROMAddr);
+       tempmclk=*((USHORT *)(ROMAddr+tempmclkptr+0x03));       //di+3
+       return tempmclk;
+}
+
+USHORT GetMCLKPtr(ULONG ROMAddr)
+{
+       USHORT tempdi;
+       USHORT tempdramtype,tempax;
+
+       tempdi=*((USHORT *)(ROMAddr+0x20C));    // MCLKData
+       tempdramtype=GetDRAMType(ROMAddr);
+       tempax=5*tempdramtype;
+       tempdi=tempdi+tempax;
+       return (tempdi); 
+}
+
+USHORT GetDRAMType(ULONG ROMAddr)
+{
+       USHORT tsoftsetting,temp3;
+
+       tsoftsetting=*((UCHAR *)(ROMAddr+0x52));
+       if(!(tsoftsetting&SoftDramType)){
+               temp3=(UCHAR)GetReg1(P3c4,0x3A);
+               tsoftsetting=temp3;     
+       }
+       tsoftsetting=tsoftsetting&0x07;
+       return(tsoftsetting);
+}
+
+static USHORT CalcDelay()
+{
+       USHORT tempal,tempah,temp1,tempbx;
+       USHORT ThTiming[8]={1,2,2,3,0,1,1,2};
+       USHORT ThLowB[24]={81,4,72,6,88,8,120,12,
+                                          55,4,54,6,66,8,90,12,
+                                          42,4,45,6,55,8,75,12};
+
+       tempah=(UCHAR)GetReg1(P3c4,0x18);       //SR_18
+       tempah=tempah&0x62;
+       tempah=tempah>>1;
+       tempal=tempah;
+       tempah=tempah>>3;
+       tempal=tempal|tempah;
+       tempal=tempal&0x07;
+
+       temp1=ThTiming[tempal];                         //temp1->cl
+
+       tempbx=(UCHAR)GetReg1(P3c4,0x16);       //SR_16
+       tempbx=tempbx>>6;
+       tempah=(UCHAR)GetReg1(P3c4,0x14);       //SR_14
+       tempah=((tempah>>4)&0x0C);
+       tempbx=((tempbx|tempah)<<1);
+       
+       tempal=ThLowB[tempbx+1]*temp1;
+       tempbx=ThLowB[tempbx];
+       tempbx=tempal+tempbx;
+
+       return(tempbx); 
+}
+
+USHORT GetVCLK2Ptr(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempal;
+       USHORT LCDXlat1VCLK[4]={VCLK65,VCLK65,VCLK65,VCLK65};
+       USHORT LCDXlat2VCLK[4]={VCLK108_2,VCLK108_2,VCLK108_2,VCLK108_2};
+
+       if(ModeNo<=0x13){
+               tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
+       }else{
+               tempal=*((UCHAR *)(ROMAddr+REFIndex+0x04));             // di+Ext_CRT2CRTC
+       }
+       tempal=tempal>>6;
+       if(LCDResInfo!=Panel1024x768){
+               tempal=LCDXlat2VCLK[tempal];
+       }else{
+               tempal=LCDXlat1VCLK[tempal];
+       }
+       
+       if(VBInfo&SetCRT2ToLCD){
+               tempal=tempal;
+       }else if(VBInfo&SetCRT2ToTV){
+               if(SetFlag&RPLLDIV2XO){
+                       tempal=TVVCLKDIV2;
+               }else{
+                       tempal=TVVCLK;
+               }
+       }else{
+               tempal=(UCHAR)GetReg2((USHORT)(P3ca+0x02)); //  Port 3cch
+               tempal=((tempal>>2)&0x03);
+               if(ModeNo>0x13){
+                       tempal=*((UCHAR *)(ROMAddr+REFIndex+0x03));      //di+Ext_CRTVCLK
+                       tempal=tempal&0x03F;
+               }
+       }
+       VCLKLen=GetVCLKLen(ROMAddr);
+       tempal=tempal*VCLKLen;
+       tempal=tempal+(*((USHORT *)(ROMAddr+0x208)));   // VCLKData
+       return ((USHORT)tempal);
+}
+
+USHORT GetVCLKLen(ULONG ROMAddr)
+{
+       USHORT VCLKDataStart,vclklabel,temp;
+       VCLKDataStart=*((USHORT *)(ROMAddr+0x208));
+       for(temp=0;;temp++){
+               vclklabel=*((USHORT *)(ROMAddr+VCLKDataStart+temp));
+               if(vclklabel==VCLKStartFreq){
+                       temp=temp+2;
+                       return(temp);    
+               }
+       }
+       return(0);
+}
+
+
+VOID SetCRT2Sync(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT temp1,tempah=0;
+       USHORT temp;    
+       USHORT  Part1Port;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       if(IF_DEF_LVDS==1){     //LVDS
+               if(VBInfo&SetCRT2ToLCD){
+                       tempah=LCDInfo;
+                       if(!(tempah&LCDSync)){
+                               temp=*((USHORT *)(ROMAddr+REFIndex));    //di+Ext_InfoFlag
+                               tempah=(temp>>8)&0x0C0;
+                       }else{
+                               tempah=tempah&0x0C0;
+                       }
+               }
+       }else{
+               temp=*((USHORT *)(ROMAddr+REFIndex));    //di+Ext_InfoFlag
+               tempah=(temp>>8)&0x0C0;
+       }
+       temp1=(UCHAR)GetReg1(Part1Port,0x19);                   //part1port index 02
+       temp1=(temp1&(~0x0C0))|tempah;
+       SetReg1(Part1Port,0x19,temp1);
+}
+
+VOID GetCRT1Ptr(ULONG ROMAddr)
+{
+       USHORT temprefcrt1;
+       USHORT temp;
+       temp=*((UCHAR *)(ROMAddr+REFIndex+0x02));       //di+Ext_CRT1CRTC
+       temp=temp&0x03F;
+       temp=temp*CRT1Len;
+       temprefcrt1=*((USHORT *)(ROMAddr+0x204));       // Get CRT1Table
+       REFIndex=temprefcrt1+temp;                      // di->CRT1Table+Ext_CRT1CRTC*CRT1Len
+}
+
+USHORT GetVGAHT2()
+{
+       long int temp1,temp2;
+
+       temp1=(VGAVT-VGAVDE)*RVBHCMAX;
+       temp1=temp1&0x0FFFF;
+       temp2=(VT-VDE)*RVBHCFACT;
+       temp2=temp2&0x0FFFF;
+       temp2=temp2*HT;
+       temp2=temp2/temp1;
+       return((USHORT)temp2);
+}
+
+VOID SetGroup2(USHORT  BaseAddr,ULONG ROMAddr)
+{
+       USHORT tempah,tempbl,tempbh,tempcl,i,j,tempcx,pushcx,tempbx,tempax;
+       USHORT tempmodeflag,tempflowflag;
+       UCHAR *temp1;
+       USHORT *temp2;
+       USHORT pushbx;
+       USHORT  Part2Port;
+       long int longtemp;
+
+       Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
+
+       tempcx=VBInfo;
+       tempah=VBInfo&0x0FF;
+       tempbl=VBInfo&0x0FF;
+       tempbh=VBInfo&0x0FF;
+       tempbx=(tempbl&0xFF)|(tempbh<<8);
+       tempbl=tempbl&0x10;
+       tempbh=(tempbh&0x04)<<1;
+       tempah=(tempah&0x08)>>1;
+       tempah=tempah|tempbh;
+       tempbl=tempbl>>3;
+       tempah=tempah|tempbl;
+       tempah=tempah^0x0C;
+       
+       if(VBInfo&SetPALTV){
+               temp1=(UCHAR *)(ROMAddr+0x0F1);         //PALPhase
+               temp2=PALTiming;
+       }else{
+               tempah=tempah|0x10;
+               temp1=(UCHAR *)(ROMAddr+0x0ED);         //NTSCPhase
+               temp2=NTSCTiming;
+       } 
+
+       SetReg1(Part2Port,0x0,tempah);
+       for(i=0x31;i<=0x34;i++,temp1++){
+               SetReg1(Part2Port,i,*(UCHAR *)temp1);
+       }
+       for(i=0x01,j=0;i<=0x2D;i++,j++){
+               SetReg1(Part2Port,i,temp2[j]);
+       }
+       for(i=0x39;i<=0x45;i++,j++){
+               SetReg1(Part2Port,i,temp2[j]);  //di->temp2[j]
+       }
+
+       tempah=GetReg1(Part2Port,0x0A);
+       tempah=tempah|NewFlickerMode;
+       SetReg1(Part2Port,0x0A,tempah);
+
+       SetReg1(Part2Port,0x35,RY1COE);
+       SetReg1(Part2Port,0x36,RY2COE);
+       SetReg1(Part2Port,0x37,RY3COE);
+       SetReg1(Part2Port,0x38,RY4COE);
+
+       tempcx=HT-1;
+       tempah=tempcx&0xFF;
+       SetReg1(Part2Port,0x1B,tempah);
+       tempah=(tempcx&0xFF00)>>8;
+       SetRegANDOR(Part2Port,0x1D,~0x0F,(UCHAR)tempah);
+
+       tempcx=HT>>1;
+       pushcx=tempcx;
+
+       tempcx=tempcx+7;
+       tempah=(tempcx&0xFF);
+       tempah=(tempah<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x22,~0x0F0,tempah);
+
+       
+       tempbx=temp2[j];
+       tempbx=tempbx+tempcx;
+       tempah=tempbx&0xFF;
+       SetReg1(Part2Port,0x24,tempah);
+       tempah=(tempbx&0xFF00)>>8;
+       tempah=(tempah<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x25,~0x0F0,tempah);
+
+       tempbx=tempbx+8;
+
+       tempah=((tempbx&0xFF)<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x29,~0x0F0,tempah);
+
+       tempcx=tempcx+temp2[++j];
+       tempah=tempcx&0xFF;
+       SetReg1(Part2Port,0x27,tempah);
+       tempah=(((tempcx&0xFF00)>>8)<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x28,~0x0F0,tempah);
+
+       tempcx=tempcx+8;
+
+       tempah=tempcx&0xFF;
+       tempah=(tempah<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x2A,~0x0F0,tempah);
+
+       tempcx=pushcx;  //pop cx
+       tempcx=tempcx-temp2[++j];
+       tempah=tempcx&0xFF;
+       tempah=(tempah<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x2D,~0x0F0,tempah);
+
+       tempcx=tempcx-11;
+       if(!(VBInfo&SetCRT2ToTV)){
+               tempax=GetVGAHT2(); 
+               tempcx=tempax-1;
+       }
+       tempah=tempcx&0xFF;
+       SetReg1(Part2Port,0x2E,tempah);
+
+       tempbx=VDE;
+       if(VGAVDE==360){
+               tempbx=746;
+       } 
+       if(VGAVDE==375){
+               tempbx=746;
+       }
+       if(VGAVDE==405){
+               tempbx=853;
+       }
+       if((VBInfo&SetCRT2ToTV)){
+        tempbx=tempbx>>1;
+       }
+       
+       tempbx=tempbx-2;
+       tempah=tempbx&0xFF;
+       SetReg1(Part2Port,0x2F,tempah);
+
+       tempah=(tempcx&0xFF00)>>8;
+       tempbh=(tempbx&0xFF00)>>8;
+       tempbh=(tempbh<<6)&0xFF;
+       tempah=tempah|tempbh;
+       //assuming <<ifndef>> hivisiontv
+       tempah=tempah|0x10;
+       if(!(VBInfo&SetCRT2ToSVIDEO)){
+               tempah=tempah|0x20; 
+       }
+       SetReg1(Part2Port,0x30,tempah);
+       tempbh=0;
+       tempbx=tempbx&0xFF;
+       
+       tempmodeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));          // si+St_ModeFlag
+       tempflowflag=0;
+       if(!(tempmodeflag&HalfDCLK)){
+               tempcx=VGAHDE;
+               if(tempcx>=HDE){
+                       tempbh=tempbh|0x20;
+                       tempbx=(tempbh<<8)|(tempbx&0xFF);
+                       tempah=0;
+               }
+       }
+       tempcx=0x0101;
+       if(!(tempbh&0x20)){             
+               if(tempmodeflag&HalfDCLK){
+                       tempcl=((tempcx&0xFF)<<1)&0xFF;
+                       tempcx=(tempcx&0xFF00)|tempcl; 
+               }
+               pushbx=tempbx;
+               tempax=VGAHDE;
+               tempbx=(tempcx&0xFF00)>>8;
+               longtemp=tempax*tempbx;
+               tempcx=tempcx&0xFF;
+               longtemp=longtemp/tempcx;
+               longtemp=longtemp*8*1024;
+               tempax=(USHORT)((longtemp)/HDE);
+               if(tempax*HDE<longtemp){
+                       tempax=tempax+1;
+               }else{
+                       tempax=tempax;
+               }
+               tempbx=pushbx;
+               tempah=((tempax&0xFF00)>>8)&0x01F;
+               tempbh=tempbh|tempah;
+               tempah=tempax&0xFF;
+       }
+
+       SetReg1(Part2Port,0x44,tempah);
+       tempah=tempbh;
+       SetRegANDOR(Part2Port,0x45,~0x03F,tempah);
+       
+       if(VBInfo&SetCRT2ToTV){
+               return;
+       }
+
+       tempah=0x01;
+       if(LCDResInfo==Panel1280x1024){
+               if(ModeType==ModeEGA){          
+                       if(VGAHDE>=1024){
+                               tempah=0x02; 
+                       }
+               }
+       } 
+       SetReg1(Part2Port,0x0B,tempah);
+       
+       tempbx=HDE-1;                   //RHACTE=HDE-1
+       tempah=tempbx&0xFF;
+       SetReg1(Part2Port,0x2C,tempah);
+       tempah=(tempbx&0xFF00)>>8;
+       tempah=(tempah<<4)&0xFF;
+       SetRegANDOR(Part2Port,0x2B,~0x0F0,tempah);
+       
+       tempbx=VDE-1;                   //RTVACTEO=(VDE-1)&0xFF
+       tempah=tempbx&0xFF;
+       SetReg1(Part2Port,0x03,tempah);
+       tempah=((tempbx&0xFF00)>>8)&0x07;
+       SetRegANDOR(Part2Port,0x0C,~0x07,tempah);
+
+       tempcx=VT-1;
+       tempah=tempcx&0xFF;     //RVTVT=VT-1
+       SetReg1(Part2Port,0x19,tempah);
+       tempah=(tempcx&0xFF00)>>8;
+       tempah=(tempah<<5)&0xFF;
+       if(LCDInfo&LCDRGB18Bit){
+               tempah=tempah|0x10;
+       }
+       SetReg1(Part2Port,0x1A,tempah);
+       
+       tempcx++;
+       if(LCDResInfo==Panel1024x768){
+               tempbx=768;
+       }else{
+               tempbx=1024;
+       }
+       
+       if(tempbx==VDE){
+               tempax=1;
+       }else{
+               tempax=tempbx;
+               tempax=(tempax-VDE)>>1;
+       }
+       tempcx=tempcx-tempax; //lcdvdes
+       tempbx=tempbx-tempax; //lcdvdee
+
+       tempah=tempcx&0xFF;     //RVEQ1EQ=lcdvdes
+       SetReg1(Part2Port,0x05,tempah);
+       tempah=tempbx&0xFF;     //RVEQ2EQ=lcdvdee
+       SetReg1(Part2Port,0x06,tempah);
+
+       tempah=(tempbx&0xFF00)>>8;
+       tempah=(tempah<<3)&0xFF;
+       tempah=tempah|((tempcx&0xFF00)>>8); 
+                       //RTVACTSE=(lcdvdes&0x700>>8)+(lcdvdee&0x700>>5);
+       SetReg1(Part2Port,0x02,tempah);
+       
+       tempcx=(VT-VDE)>>4;     //(VT-VDE)>>4
+       tempbx=(VT+VDE)>>1;
+       tempah=tempbx&0xFF;     //RTVACTEE=lcdvrs
+       SetReg1(Part2Port,0x04,tempah);
+
+       tempah=(tempbx&0xFF00)>>8;
+       tempah=(tempah<<4)&0xFF;
+       tempbx=tempbx+tempcx+1;
+       tempbl=(tempbx&0x0F);
+       tempah=tempah|tempbl;   //RTVACTSO=lcdvrs&0x700>>4+lcdvre
+       SetReg1(Part2Port,0x01,tempah);
+
+       tempah=GetReg1(Part2Port,0x09);
+       tempah=tempah&0xF0;
+       SetReg1(Part2Port,0x09,tempah);
+
+       tempah=GetReg1(Part2Port,0x0A);
+       tempah=tempah&0xF0;
+       SetReg1(Part2Port,0x0A,tempah);
+
+       tempcx=(HT-HDE)>>2;      //(HT-HDE)>>2
+       tempbx=(HDE+7);                 //lcdhdee
+       tempah=tempbx&0xFF;      //RHEQPLE=lcdhdee
+       SetReg1(Part2Port,0x23,tempah);
+       tempah=(tempbx&0xFF00)>>8;
+       SetRegANDOR(Part2Port,0x25,~0x0F,tempah);
+
+       SetReg1(Part2Port,0x1F,0x07);   //RHBLKE=lcdhdes
+       tempah=GetReg1(Part2Port,0x20);
+       tempah=tempah&0x0F;
+       SetReg1(Part2Port,0x20,tempah);
+
+       tempbx=tempbx+tempcx;
+       tempah=tempbx&0xFF;                             //RHBURSTS=lcdhrs
+       SetReg1(Part2Port,0x1C,tempah);
+       tempah=(tempbx&0xFF00)>>8;
+       tempah=(tempah<<4)&0xFF; 
+       SetRegANDOR(Part2Port,0x1D,~0x0F0,tempah);
+
+       tempbx=tempbx+tempcx;
+       tempah=tempbx&0xFF;                             //RHSYEXP2S=lcdhre
+       SetReg1(Part2Port,0x21,tempah);
+
+       tempah=GetReg1(Part2Port,0x17);
+       tempah=tempah&0xFB;
+       SetReg1(Part2Port,0x17,tempah);
+
+       tempah=GetReg1(Part2Port,0x18);
+       tempah=tempah&0xDF;
+       SetReg1(Part2Port,0x18,tempah);
+       return;
+}
+
+VOID SetGroup3(USHORT  BaseAddr)
+{
+       USHORT i;
+       USHORT *tempdi;
+       USHORT  Part3Port;
+       Part3Port=BaseAddr+IND_SIS_CRT2_PORT_12;
+       if(VBInfo&SetPALTV){
+               tempdi=PALGroup3Data;                                   
+       }else{
+               tempdi=NTSCGroup3Data;
+       }
+
+       for(i=0;i<=0x3E;i++){
+               SetReg1(Part3Port,i,tempdi[i]);
+       }
+       return;
+}
+
+VOID SetGroup4(USHORT  BaseAddr,ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT  Part4Port;
+       USHORT tempax,tempah,tempcx,tempbx,tempbh,tempch,tempmodeflag;
+       long int tempebx,tempeax,templong;      
+       Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
+
+       tempax=0x0c;
+       if(VBInfo&SetCRT2ToTV){
+               if(VBInfo&SetInSlaveMode){
+                       if(!(SetFlag&TVSimuMode)){
+                               SetFlag=SetFlag|RPLLDIV2XO;
+                               tempax=tempax|0x04000;  
+                       }
+               }else{
+                       SetFlag=SetFlag|RPLLDIV2XO;
+                       tempax=tempax|0x04000;   
+               }
+       }
+
+       if(LCDResInfo!=Panel1024x768){
+               tempax=tempax|0x08000;
+       }
+       tempah=(tempax&0xFF00)>>8;
+       SetReg1(Part4Port,0x0C,tempah);
+       
+       tempah=RVBHCFACT;
+       SetReg1(Part4Port,0x13,tempah);
+       
+       tempbx=RVBHCMAX;
+       tempah=tempbx&0xFF;
+       SetReg1(Part4Port,0x14,tempah);
+       tempbh=(((tempbx&0xFF00)>>8)<<7)&0xFF;
+
+       tempcx=VGAHT-1;
+       tempah=tempcx&0xFF;
+       SetReg1(Part4Port,0x16,tempah);
+       tempch=(((tempcx&0xFF00)>>8)<<3)&0xFF;
+       tempbh=tempbh|tempch;
+       
+       tempcx=VGAVT-1;
+       if(!(VBInfo&SetCRT2ToTV)){
+               tempcx=tempcx-5;
+       }
+       tempah=tempcx&0xFF;
+       SetReg1(Part4Port,0x17,tempah);
+       tempbh=tempbh|((tempcx&0xFF00)>>8);
+       tempah=tempbh;
+       SetReg1(Part4Port,0x15,tempah);
+       
+       tempcx=VBInfo;
+       tempbx=VGAHDE;
+       tempmodeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));          // si+St_ModeFlag
+       if(tempmodeflag&HalfDCLK){
+               tempbx=tempbx>>1;                               
+       }
+       if(VBInfo&SetCRT2ToLCD){
+               tempah=0;
+               if(tempbx>800){
+                       tempah=0x60; 
+               }
+       }else{
+               tempah=0x080;
+       }
+       if(LCDResInfo!=Panel1280x1024){
+               tempah=tempah|0x0A;
+       }
+
+       SetRegANDOR(Part4Port,0x0E,~0xEF,tempah);
+
+       tempebx=VDE;
+       
+       tempcx=RVBHRS;
+       tempah=tempcx&0xFF;
+       SetReg1(Part4Port,0x18,tempah);
+
+       tempeax=VGAVDE;
+       tempcx=tempcx|0x04000;
+       tempeax=tempeax-tempebx;
+       if(tempeax<0){
+               tempcx=tempcx^(0x04000);
+               tempeax=VGAVDE;
+       }
+
+       templong=(tempeax*256*1024)/tempebx;
+       if(tempeax*256*1024-templong*tempebx>0){
+               tempebx=templong+1;
+       }else{
+               tempebx=templong;
+       } 
+       
+
+       tempah=(USHORT)(tempebx&0xFF);
+       SetReg1(Part4Port,0x1B,tempah);
+       tempah=(USHORT)((tempebx&0xFF00)>>8);
+       SetReg1(Part4Port,0x1A,tempah);
+       tempebx=tempebx>>16;
+       tempah=(USHORT)(tempebx&0xFF);
+       tempah=(tempah<<4)&0xFF;
+       tempah=tempah|((tempcx&0xFF00)>>8);
+       SetReg1(Part4Port,0x19,tempah);
+       
+       SetCRT2VCLK(BaseAddr,ROMAddr,ModeNo);
+}
+
+VOID SetCRT2VCLK(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT vclk2ptr;
+       USHORT tempah,temp1;
+       USHORT  Part4Port;
+       Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
+       vclk2ptr=GetVCLK2Ptr(ROMAddr,ModeNo);
+       SetReg1(Part4Port,0x0A,0x01);
+       tempah=*((UCHAR *)(ROMAddr+vclk2ptr+0x01));     //di+1
+       SetReg1(Part4Port,0x0B,tempah);
+       tempah=*((UCHAR *)(ROMAddr+vclk2ptr+0x00));     //di
+       SetReg1(Part4Port,0x0A,tempah);
+       SetReg1(Part4Port,0x12,0x00);
+       tempah=0x08;
+       if(VBInfo&SetCRT2ToRAMDAC){
+               tempah=tempah|0x020;
+       }
+       temp1=GetReg1(Part4Port,0x12);
+       tempah=tempah|temp1;
+       SetReg1(Part4Port,0x12,tempah);
+}
+
+VOID SetGroup5(USHORT  BaseAddr,ULONG ROMAddr)
+{
+       USHORT  Part5Port;
+       USHORT Pindex,Pdata;
+       Part5Port=BaseAddr+IND_SIS_CRT2_PORT_14+2;
+       Pindex=Part5Port;
+       Pdata=Part5Port+1;
+       if(ModeType==ModeVGA){
+               if(!(VBInfo&(SetInSlaveMode|LoadDACFlag|CRT2DisplayFlag))){
+                       EnableCRT2();
+                       LoadDAC2(ROMAddr,Part5Port);
+               }
+       }
+       return;
+}
+
+VOID EnableCRT2()
+{
+       USHORT temp1;
+       temp1=GetReg1(P3c4,0x1E);
+       temp1=temp1|0x20;
+       SetReg1(P3c4,0x1E,temp1);               //SR 1E
+}
+
+VOID LoadDAC2(ULONG ROMAddr,USHORT Part5Port)
+{
+       USHORT data,data2;
+       USHORT time,i,j,k;
+       USHORT m,n,o;
+       USHORT si,di,bx,dl;
+       USHORT al,ah,dh;
+       USHORT *table=VGA_DAC;
+       USHORT Pindex,Pdata;
+       Pindex=Part5Port;
+       Pdata=Part5Port+1;
+       data=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+       data=data&DACInfoFlag;
+       time=64;
+       if(data==0x00) table=MDA_DAC;
+       if(data==0x08) table=CGA_DAC;
+       if(data==0x10) table=EGA_DAC;
+       if(data==0x18) {
+               time=256;
+               table=VGA_DAC;
+       }
+       if(time==256) j=16;
+       else j=time;
+
+       //SetReg3(P3c6,0xFF);
+       SetReg3(Pindex,0x00);
+
+       for(i=0;i<j;i++) {
+               data=table[i];
+               for(k=0;k<3;k++) {
+                       data2=0;
+                       if(data&0x01) data2=0x2A;
+                       if(data&0x02) data2=data2+0x15;
+                       SetReg3(Pdata,data2);
+                       data=data>>2;
+               }
+       }
+
+       if(time==256) {
+               for(i=16;i<32;i++) {
+                       data=table[i];
+                       for(k=0;k<3;k++) SetReg3(Pdata,data);
+               }
+               si=32;
+               for(m=0;m<9;m++) {
+                       di=si;
+                       bx=si+0x04;
+                       dl=0;
+                       for(n=0;n<3;n++) {
+                               for(o=0;o<5;o++) {
+                                       dh=table[si];
+                                       ah=table[di];
+                                       al=table[bx];
+                                       si++;
+                                       WriteDAC2(Pdata,dl,ah,al,dh);
+                               }                       // for 5
+                               si=si-2;
+                               for(o=0;o<3;o++) {
+                                       dh=table[bx];
+                                       ah=table[di];
+                                       al=table[si];
+                                       si--;
+                                       WriteDAC2(Pdata,dl,ah,al,dh);
+                               }                       // for 3
+                               dl++;
+                       }                               // for 3
+                       si=si+5;
+               }                                       // for 9
+       }
+}
+
+VOID WriteDAC2(USHORT Pdata,USHORT dl, USHORT ah, USHORT al, USHORT dh)
+{
+       USHORT temp;
+       USHORT bh,bl;
+
+       bh=ah;
+       bl=al;
+       if(dl!=0) {
+               temp=bh;
+               bh=dh;
+               dh=temp;
+               if(dl==1) {
+                       temp=bl;
+                       bl=dh;
+                       dh=temp;
+               }
+               else {
+                       temp=bl;
+                       bl=bh;
+                       bh=temp;
+               }
+       }
+       SetReg3(Pdata,(USHORT)dh);
+       SetReg3(Pdata,(USHORT)bh);
+       SetReg3(Pdata,(USHORT)bl);
+}
+
+VOID LockCRT2(USHORT BaseAddr)
+{
+       USHORT  Part1Port;
+       USHORT  Part4Port;
+       USHORT temp1;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
+       temp1=GetReg1(Part1Port,0x24);
+       temp1=temp1&0xFE;
+       SetReg1(Part1Port,0x24,temp1);
+}
+
+VOID SetLockRegs()
+{
+       USHORT temp1;
+
+       if((VBInfo&SetInSlaveMode)&&(!(VBInfo&SetCRT2ToRAMDAC))){
+               VBLongWait();
+               temp1=GetReg1(P3c4,0x32);
+               temp1=temp1|0x20;
+               SetReg1(P3c4,0x32,temp1);
+               VBLongWait();
+       }
+}
+
+VOID EnableBridge(USHORT BaseAddr)
+{
+       USHORT part2_02,part2_05;
+       USHORT  Part2Port,Part1Port;
+       Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+
+       if(IF_DEF_LVDS==0){
+               part2_02=(UCHAR)GetReg1(Part2Port,0x02);
+               part2_05=(UCHAR)GetReg1(Part2Port,0x05);
+               SetReg1(Part2Port,0x02,0x38);
+               SetReg1(Part2Port,0x05,0xFF);
+               LongWait();
+               SetRegANDOR(Part2Port,0x00,~0x0E0,0x020);
+               WaitVBRetrace(BaseAddr);
+               SetReg1(Part2Port,0x02,part2_02);
+               SetReg1(Part2Port,0x05,part2_05);
+       }else{
+               EnableCRT2();
+               UnLockCRT2(BaseAddr);
+               SetRegANDOR(Part1Port,0x02,~0x040,0x0);
+       }
+}
+
+USHORT GetLockInfo(USHORT pattern)
+{
+       USHORT temp1;
+       temp1=GetReg1(P3d4,0x36);
+       return(temp1&pattern);
+}      
+
+VOID GetVBInfo(USHORT BaseAddr,ULONG ROMAddr)
+{
+       USHORT flag1,tempbx,tempbl,tempbh,tempah;
+       
+       SetFlag=0;
+       tempbx=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));                // si+St_ModeFlag
+       tempbl=tempbx&ModeInfoFlag;
+       ModeType=tempbl;
+       tempbx=0;
+       flag1=GetReg1(P3c4,0x38);               //call BridgeisOn
+       if(!(flag1&0x20)){
+               VBInfo=CRT2DisplayFlag;
+               return;
+       }
+       tempbl=GetReg1(P3d4,0x30);      
+       tempbh=GetReg1(P3d4,0x31);
+       if(!(tempbl&0x07C)){
+               VBInfo=CRT2DisplayFlag;
+               return;
+       }
+       if(IF_DEF_LVDS==1){     //for LVDS
+               if(!(tempbl&SetCRT2ToLCD)){
+                       VBInfo=CRT2DisplayFlag;
+                       return;
+               }
+       }
+       if(IF_DEF_LVDS==0){ //for 301
+               if(tempbl&SetCRT2ToRAMDAC){
+                       tempbl=tempbl&(SetCRT2ToRAMDAC|SwitchToCRT2|SetSimuScanMode);
+               }else if(tempbl&SetCRT2ToLCD){
+                       tempbl=tempbl&(SetCRT2ToLCD|SwitchToCRT2|SetSimuScanMode);
+               }else if(tempbl&SetCRT2ToSCART){
+                       tempbl=tempbl&(SetCRT2ToSCART|SwitchToCRT2|SetSimuScanMode);
+               }else if(tempbl&SetCRT2ToHiVisionTV){
+                       tempbl=tempbl&(SetCRT2ToHiVisionTV|SwitchToCRT2|SetSimuScanMode);
+               }
+       }else{ //for LVDS
+               if(tempbl&SetCRT2ToLCD){
+                       tempbl=tempbl&(SetCRT2ToLCD|SwitchToCRT2|SetSimuScanMode);
+               }
+       }
+       tempah=GetReg1(P3d4,0x31);
+       if(tempah&(CRT2DisplayFlag>>8)){
+               if(!(tempbl&(SwitchToCRT2|SetSimuScanMode))){
+                       tempbx=SetSimuScanMode|CRT2DisplayFlag;
+                       tempbh=((tempbx&0xFF00)>>8);
+                       tempbl=tempbx&0xFF;
+               }
+       }
+       if(!(tempbh&(DriverMode>>8))){
+               tempbl=tempbl|SetSimuScanMode;
+       }
+       VBInfo=tempbl|(tempbh<<8);
+       if(!(VBInfo&SetSimuScanMode)){
+               if(!(VBInfo&SwitchToCRT2)){
+                       if(BridgeIsEnable(BaseAddr)){
+                               if(BridgeInSlave()){
+                                       VBInfo=VBInfo|SetSimuScanMode;
+                               }       
+                       }
+               }
+       }
+       if(!((VBInfo&(SetSimuScanMode|SwitchToCRT2)))){
+               return;
+       }
+       if(!(VBInfo&DriverMode)){
+               VBInfo=VBInfo|SetInSlaveMode;
+               if((VBInfo&SetCRT2ToTV)&&(!(VBInfo&SetNotSimuTVMode))){
+                       SetFlag=SetFlag|TVSimuMode;
+               }
+               return;
+       }
+       flag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));         // si+St_ModeFlag
+       if(!(flag1&(CRT2Mode|CRT2DisplayFlag))){
+               VBInfo=VBInfo|SetInSlaveMode;
+               if((VBInfo&SetCRT2ToTV)&&(!(VBInfo&SetNotSimuTVMode))){
+                       SetFlag=SetFlag|TVSimuMode;
+               }
+       }
+}
+
+BOOLEAN BridgeIsEnable(USHORT BaseAddr)
+{
+       USHORT flag1;
+       USHORT  Part1Port;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+
+       if(IF_DEF_LVDS==1){
+               return 1;
+       }
+       flag1=GetReg1(P3c4,0x38);               //call BridgeisOn
+       if(!(flag1&0x20)){ return 0;}
+       flag1=GetReg1(Part1Port,0x0);
+       if(flag1&0x0a0){
+               return 1;
+       }else{
+               return 0;
+       }
+}
+
+BOOLEAN BridgeInSlave()
+{
+       USHORT flag1;
+       flag1=GetReg1(P3d4,0x31);
+       if(flag1&(SetInSlaveMode>>8)){
+               return 1;
+       }else{
+               return 0;
+       }
+}
+
+BOOLEAN GetLCDResInfo(ULONG ROMAddr,USHORT P3d4)
+{
+       USHORT tempah,tempbh,tempflag;                  
+       
+       tempah=(UCHAR)GetReg1(P3d4,0x36);
+       tempbh=tempah;
+       tempah=tempah&0x0F;
+       if(tempah>Panel1280x1024) tempah=Panel1024x768;
+       LCDResInfo=tempah;
+       tempbh=tempbh>>4;
+       LCDTypeInfo=tempbh;
+       
+       tempah=(UCHAR)GetReg1(P3d4,0x37);
+       LCDInfo=tempah;
+       if(IF_DEF_TRUMPION){
+               LCDInfo=LCDInfo&(~LCDNonExpanding);
+       }
+       if(IF_DEF_LVDS==1){
+               tempflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));              // si+St_ModeFlag
+               if(tempflag&HalfDCLK){
+                       if(IF_DEF_TRUMPION==0){
+                               if(!(LCDInfo&LCDNonExpanding)){
+                                       if(LCDResInfo==Panel1024x768){
+                                               tempflag=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo
+                                               if(tempflag==4){ //512x384
+                                                       SetFlag=SetFlag|EnableLVDSDDA;
+                                               }
+                                       }else{
+                                               if(LCDResInfo==Panel800x600){
+                                                       tempflag=*((UCHAR *)(ROMAddr+ModeIDOffset+0x09)); //si+Ext_ResInfo      
+                                                       if(tempflag==3){ //400x300
+                                                               SetFlag=SetFlag|EnableLVDSDDA;
+                                                       } 
+                                               }
+                                       }
+                               }else{
+                                       SetFlag=SetFlag|EnableLVDSDDA;
+                               }
+                       }else{
+                               SetFlag=SetFlag|EnableLVDSDDA;
+                       }
+               }
+       }
+
+       if(!(VBInfo&SetCRT2ToLCD)){
+               return 1;                               
+       }
+       if(!(VBInfo&(SetSimuScanMode|SwitchToCRT2))){
+               return 1;       
+       }
+       if(VBInfo&SetInSlaveMode){
+               if(VBInfo&SetNotSimuTVMode){
+                       SetFlag=SetFlag|LCDVESATiming;   
+               }       
+       }else{
+               SetFlag=SetFlag|LCDVESATiming;          
+       }
+       return 1;               
+}
+
+VOID PresetScratchregister(USHORT P3d4,PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       SetReg1(P3d4,0x37,0x00);                
+}
+
+BOOLEAN GetLCDDDCInfo(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT tempah;
+       tempah=(HwDeviceExtension->usLCDType);// set in sisv.c
+                                                                                       //0:no lcd 1:1024x768 2:1280x1024
+       if(tempah>0) tempah++; // usLCDType: 
+                                                               // 0:no lcd 1:800x600 2:1024x768 3:1280x1024
+       SetReg1(P3d4,0x36,tempah);//cr 36 0:no LCD 1:800x600 2:1024x768 3:1280x1024
+       if(tempah>0) return 1;
+       else return 0;                  
+}
+
+VOID SetTVSystem(PHW_DEVICE_EXTENSION HwDeviceExtension,ULONG ROMAddr)
+{
+       USHORT tempah,temp;
+
+       if(IF_DEF_LVDS==0){ //301
+               if(PRIMARY_VGA==1){ //primary vga
+                       if(HwDeviceExtension->jChipID >= SIS_Trojan){
+                               tempah=GetReg1(P3c4,0x17);
+                               if(tempah&ModeSwitchStatus){
+                                       tempah=GetReg1(P3c4,0x16);
+                                       tempah=tempah&ActivePAL;
+                                       tempah=tempah>>ActivePALShift;
+                               }else{
+                                       temp=*((UCHAR *)(ROMAddr+SoftSettingAddr));
+                                       if(temp&SoftTVType){
+                                               tempah=*((UCHAR *)(ROMAddr+ModeSettingAddr));
+                                       }else{
+                                               tempah=GetReg1(P3c4,0x38);      //SR 38
+                                       }
+                               }
+                       }else{
+                               temp=*((UCHAR *)(ROMAddr+SoftSettingAddr));
+                               if(temp&SoftTVType){
+                                       tempah=*((UCHAR *)(ROMAddr+ModeSettingAddr));
+                               }else{
+                                       tempah=GetReg1(P3c4,0x38);      //SR 38
+                               }
+                       }
+                       tempah=tempah&0x01;             //get SR 38 D0 TV Type Selection
+                                                                       //0:NTSC 1:PAL
+                       SetRegANDOR(P3d4,0x31,~0x01,tempah);//set CR 31 D0= SR 38 D0
+               }
+               else{ //Secondary 
+                       tempah=GetReg1(P3c4,0x38);      //SR 38
+                       tempah=tempah&0x01;                     //get SR 38 D0 TV Type Selection
+                                                                               //0:NTSC 1:PAL
+                       SetRegANDOR(P3d4,0x31,~0x01,tempah);//set CR 31 D0= SR 38 D0
+               }
+               return;
+       }else{ //LVDS
+               tempah=GetReg1(P3c4,0x16);      //SR 16
+               tempah=tempah&ActiveNonExpanding;
+               tempah=tempah>>ActiveNonExpandingShift;
+               tempah=tempah&0x01;     
+               tempah=tempah<<LCDNonExpandingShift;
+               SetRegANDOR(P3d4,0x37,~LCDNonExpanding,tempah);
+               return;
+       }               
+}
+
+BOOLEAN GetSenseStatus(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT BaseAddr,ULONG ROMAddr)
+{
+       USHORT flag1,tempbx,tempal,tempah,tempcx,i;      
+       USHORT Part2Port,Part4Port;
+       USHORT RGBSenseData,YCSenseData,VideoSenseData;
+       USHORT P2reg0,SenseModeNo,OutputSelect;
+       Part2Port=BaseAddr+IND_SIS_CRT2_PORT_10;
+       Part4Port=BaseAddr+IND_SIS_CRT2_PORT_14;
+       RGBSenseData=*((USHORT *)(ROMAddr+0xF8)); //0:F8 in rompost.asm
+       YCSenseData=*((USHORT *)(ROMAddr+0xFA)); //0:FA in rompost.asm
+       VideoSenseData=*((USHORT *)(ROMAddr+0xFC)); //0:FC in rompost.asm
+
+       if(IF_DEF_LVDS==1){
+               GetPanelID();
+               tempah=LCDSense;
+               SetRegANDOR(P3d4,0x32,~0x5F,tempah); //Set CR 32
+               return 0;
+       }
+        
+       flag1=GetReg1(P3c4,0x38);               //call BridgeisOn
+       if(!(flag1&0x20)){ return 0;}
+       P2reg0=GetReg1(Part2Port,0x00); //save Part2 Reg index 0
+       
+       if(!(BridgeIsEnable(BaseAddr))){
+               SenseModeNo=0x2E;
+               ModeType=ModeVGA;
+               VBInfo=SetCRT2ToRAMDAC;
+               SetFlag=0;
+               SetCRT2Group(BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
+               //here perform I/O delay ,read SR 05                    
+               for(i=0;i<0x7FFF;i++){
+                       flag1=GetReg1(P3c4,0x05);                       
+               }
+       }               
+       
+       SetReg1(Part2Port,0x00,0x1C);   //Set part2 index 0= 0x1C
+       tempah=0;
+       
+       OutputSelect=*((UCHAR *)(ROMAddr+0xFE));        //OutputSelect 0:FE in Rompost.asm
+       if(OutputSelect&SetSCARTOutput){
+               tempal=SCARTSense;      
+       }else{
+               tempal=Monitor2Sense;
+       }
+       tempbx=RGBSenseData;
+       tempcx=0x0E08;
+       if(Sense(Part4Port,tempbx,tempcx)){
+               if(Sense(Part4Port,tempbx,tempcx)){
+                       tempah=tempah|tempal; 
+               }               
+       }
+       tempbx=YCSenseData;
+       tempcx=0x0604;
+       if(Sense(Part4Port,tempbx,tempcx)){
+               if(Sense(Part4Port,tempbx,tempcx)){
+                       tempah=tempah|SVIDEOSense;
+                       //Skipped lines about HiTVSense, assuming not HiTV      
+               }
+       }
+
+       //Assuming not HiTV ,below is of ifndef HiVisionTV
+       if(OutputSelect&BoardTVType){
+               tempbx=VideoSenseData;
+               tempcx=0x0804;
+               if(Sense(Part4Port,tempbx,tempcx)){
+                       if(Sense(Part4Port,tempbx,tempcx)){
+                               tempah=tempah|AVIDEOSense;
+                       }                       
+               }       
+       }else{
+               if(!(tempah&SVIDEOSense)){
+                       tempbx=VideoSenseData;
+                       tempcx=0x0804;
+                       if(Sense(Part4Port,tempbx,tempcx)){
+                               if(Sense(Part4Port,tempbx,tempcx)){
+                                       tempah=tempah|AVIDEOSense; 
+                               }               
+                       }
+               }
+       }
+       //end of ifndef HivisionTv
+       if(SenseLCD(HwDeviceExtension,Part4Port,ROMAddr)){
+               if(SenseLCD(HwDeviceExtension,Part4Port,ROMAddr)){
+                       tempah=tempah|LCDSense;
+               }               
+       }
+       
+       tempbx=0; 
+       tempcx=0;
+       Sense(Part4Port,tempbx,tempcx);
+       
+       SetRegANDOR(P3d4,0x32,~0x5F,tempah); //Set CR 32
+       SetReg1(Part2Port,0x00,P2reg0);         //recover Part2 reg index 0
+       
+       //here skipped lines about DisableCRT2Display 
+       return 0;       
+}
+
+BOOLEAN Sense(USHORT Part4Port,USHORT inputbx,USHORT inputcx)
+{
+       USHORT tempah,tempcl,tempch;
+       
+       tempah=inputbx&0xFF;
+       SetReg1(Part4Port,0x11,tempah);//Part4 index 11
+       tempah=(inputbx&0xFF00)>>8;
+       tempcl=inputcx&0xFF;
+       tempah=tempah|tempcl;
+       SetRegANDOR(Part4Port,0x10,~0x1F,tempah);//Part4 index 10
+       
+       tempch=(inputcx&0xFF00)>>8;
+       tempch=tempch&0x7F;
+       //here skipped lines about call Delay
+       tempah=GetReg1(Part4Port,0x03);         //Part4 index 03
+       tempah=tempah^(0x0E);
+       tempah=tempah&tempch;
+       if(tempah>0) return 1;
+       else return 0;                  
+}
+
+BOOLEAN SenseLCD(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT Part4Port,ULONG ROMAddr)
+{
+       USHORT SoftSetting;
+       USHORT tempah;                  
+       SoftSetting=*((UCHAR *)(ROMAddr+0x52));//0:52 in rompost.asm
+       if(GetLCDDDCInfo(HwDeviceExtension)){
+               return 1;       
+       }
+       if(SoftSetting&HotPlugFunction){
+               tempah=GetReg1(Part4Port,0x0F);
+               tempah=tempah&0x3F;
+               SetReg1(Part4Port,0x0F,tempah); //Part4 index 0F
+               if(Sense(Part4Port,0x0,0x9010)){
+                       return 1; 
+               }else{
+                       return 0;
+               }       
+       }else{
+               return 0;
+       }               
+}
+#endif
+
+VOID SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR)
+{
+       USHORT temp1;
+       temp1=GetReg1(Port,Index);              //part1port index 02
+       temp1=(temp1&(DataAND))|DataOR;
+       SetReg1(Port,Index,temp1);
+}
+
+BOOLEAN DetectMonitor(PHW_DEVICE_EXTENSION HwDeviceExtension)
+{
+       USHORT flag1    ;
+       USHORT DAC_TEST_PARMS[3]={0x0F,0x0F,0x0F};
+       USHORT DAC_CLR_PARMS[3]={0x00,0x00,0x00};
+       
+       flag1=GetReg1(P3c4,0x38);               //call BridgeisOn
+       if((flag1&0x20)){
+               SetReg1(P3d4,0x30,0x41);
+       }
+       
+       SiSSetMode(HwDeviceExtension,0x2E); //set mode to 0x2E instead of 0x3
+       ClearDAC(P3c8);
+       ClearALLBuffer(HwDeviceExtension);
+       
+       LongWait();     //wait vertical retrace
+       LongWait();
+       
+       flag1=TestMonitorType(DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],
+                       DAC_TEST_PARMS[2]);
+       if(flag1==0){
+               flag1=TestMonitorType(DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],
+                       DAC_TEST_PARMS[2]);             
+       }               
+       if(flag1==1){
+               SetRegANDOR(P3d4,0x32,~Monitor1Sense,Monitor1Sense);                                     
+       }else{
+               SetRegANDOR(P3d4,0x32,~Monitor1Sense,0x0);
+       }
+       TestMonitorType(DAC_CLR_PARMS[0],DAC_CLR_PARMS[1],DAC_CLR_PARMS[2]);
+                       
+       SetReg1(P3d4,0x34,0x4A);        //Preset default CRT1 ModeNo =0x4A
+                                                               //which is used in SetCRT2FIFO()
+       return 1;               
+}
+
+BOOLEAN TestMonitorType(USHORT d1,USHORT d2,USHORT d3)
+{
+       USHORT temp;    
+       SetReg3(P3c6,0xFF);
+       SetReg3(P3c8,0x00);
+       SetReg3(P3c9,d1);
+       SetReg3(P3c9,d2);
+       SetReg3(P3c9,d3);
+       WaitDisplay();                  //wait horizontal retrace
+       temp=GetReg2(P3c2);
+       if(temp&0x10) return 1;
+       else return 0;                  
+}
+
+VOID WaitDisplay(void)
+{
+       USHORT temp;
+       for(temp=0;temp==0;){
+               temp=GetReg2(P3da);
+               temp=temp&0x01;  
+       }
+       for(;temp==1;){
+               temp=GetReg2(P3da);
+               temp=temp&0x01;  
+       }               
+}
+
+VOID LongWait(void)
+{
+       USHORT temp;
+       
+       for(temp=1;temp>0;){
+               temp=GetReg2(P3da);
+               temp=temp&0x08;  
+       }
+       for(;temp==0;){
+               temp=GetReg2(P3da);
+               temp=temp&0x08;  
+       }               
+}
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
+
+VOID VBLongWait(VOID)
+{
+       USHORT regsr1f,tempah,temp;
+
+       regsr1f=GetReg1(P3c4,0x1F);
+       tempah=regsr1f&(~0xC0);
+       SetReg1(P3c4,0x1F,tempah);
+
+       for(temp=1;temp>0;){
+               temp=GetReg2(P3da);
+               temp=temp&0x08;  
+       }
+       for(;temp==0;){
+               temp=GetReg2(P3da);
+               temp=temp&0x08;  
+       }
+
+       SetReg1(P3c4,0x1F,regsr1f);
+       return; 
+}
+
+BOOLEAN WaitVBRetrace(USHORT BaseAddr)
+{
+       USHORT temp;
+       USHORT Part1Port;
+       Part1Port=BaseAddr+IND_SIS_CRT2_PORT_04;
+       temp=GetReg1(Part1Port,0x00);
+       if(!(temp&0x80)){
+               return 0;
+       }
+
+       for(temp=0;temp==0;){
+               temp=GetReg1(Part1Port,0x25);
+               temp=temp&0x01;  
+       }
+       for(;temp>0;){
+               temp=GetReg1(Part1Port,0x25);
+               temp=temp&0x01;  
+       }
+       return 1; 
+}
+
+BOOLEAN GetPanelID(VOID)
+{
+       USHORT PanelTypeTable[16]={ SyncPP|Panel800x600|PanelType00,
+                                                               SyncPP|Panel1024x768|PanelType01,
+                                                               SyncPP|Panel1024x768|PanelType02,
+                                                               SyncPP|Panel1024x768|PanelType03,
+                                                               SyncPP|Panel1024x768|PanelType04,
+                                                               SyncPP|Panel1024x768|PanelType05,
+                                                               SyncPP|Panel1024x768|PanelType06,
+                                                               SyncPP|Panel1024x768|PanelType07,
+                                                               SyncPP|Panel1024x768|PanelType08,
+                                                               SyncPP|Panel1024x768|PanelType09,
+                                                               SyncPP|Panel800x600|PanelType0A,
+                                                               SyncPP|Panel1024x768|PanelType0B,
+                                                               SyncPP|Panel1024x768|PanelType0C,
+                                                               SyncPP|Panel1024x768|PanelType0D,
+                                                               SyncPP|Panel1024x768|PanelType0E,
+                                                               SyncPP|Panel1024x768|PanelType0F};
+       // Bit 15 BPLVSPLTY
+       // Bit 14 BPLHSPLTY
+       // Bit 6-3 Panel Type
+       // Bit 2-0 Display Resolution(001:800x600 010:1024x768 011:1280x1024)
+       USHORT tempah,tempbx;
+       USHORT return_flag;
+
+       tempah=GetReg1(P3c4,0x18);
+       tempbx=tempah&0x0F;
+       if(tempah&0x10){
+               return_flag=1;
+       }else{
+               return_flag=0;
+       }
+
+       if(return_flag==0){
+               if(IF_DEF_LVDS==1){
+                       tempbx=0;
+                       tempah=GetReg1(P3c4,0x38);
+                       if(tempah&0x40) tempbx=tempbx|0x08;
+                       if(tempah&0x20) tempbx=tempbx|0x02;
+                       if(tempah&0x01) tempbx=tempbx|0x01;
+                       tempah=GetReg1(P3c4,0x39);
+                       if(tempah&0x80) tempbx=tempbx|0x04;
+               }else{
+                       return 0;
+               }
+       }
+
+       if(IF_DEF_TRUMPION==1){
+               tempbx=1;
+       }
+       tempbx=PanelTypeTable[tempbx]; //LVDS table entry
+       tempbx=tempbx|(USHORT)(LCDSync<<8);
+
+       tempah=tempbx&0x0FF;
+       SetReg1(P3d4,0x36,tempah);
+       tempah=(tempbx&0xFF00)>>8;
+       SetRegANDOR(P3d4,0x37,~LCDSyncBit,tempah);
+       return 1;
+}
+
+VOID ModCRT1CRTC(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT OldREFIndex,temp,tempah,i,modeflag1;
+
+       OldREFIndex=(USHORT)REFIndex;
+       temp=GetLVDSCRT1Ptr(ROMAddr,ModeNo);
+       if(temp==0){
+               REFIndex=OldREFIndex;
+               return;
+       }
+       tempah=(UCHAR)GetReg1(P3d4,0x11);//unlock cr0-7
+       tempah=tempah&0x7F;
+       SetReg1(P3d4,0x11,tempah);
+       tempah=*((UCHAR *)(ROMAddr+REFIndex));
+       SetReg1(P3d4,0x0,tempah);
+       REFIndex++;
+       for(i=0x02;i<=0x05;REFIndex++){
+               tempah=*((UCHAR *)(ROMAddr+REFIndex));
+               SetReg1(P3d4,i,tempah); 
+       }
+       for(i=0x06;i<=0x07;REFIndex++){
+               tempah=*((UCHAR *)(ROMAddr+REFIndex));
+               SetReg1(P3d4,i,tempah); 
+       }
+       for(i=0x10;i<=0x11;REFIndex++){
+               tempah=*((UCHAR *)(ROMAddr+REFIndex));
+               SetReg1(P3d4,i,tempah); 
+       }
+       for(i=0x15;i<=0x16;REFIndex++){
+               tempah=*((UCHAR *)(ROMAddr+REFIndex));
+               SetReg1(P3d4,i,tempah); 
+       }
+
+       for(i=0x0A;i<=0x0C;REFIndex++){
+               tempah=*((UCHAR *)(ROMAddr+REFIndex));
+               SetReg1(P3c4,i,tempah); 
+       }
+       tempah=*((UCHAR *)(ROMAddr+REFIndex));
+       tempah=tempah&0x0E0;
+       SetReg1(P3c4,0x0E,tempah);
+
+       tempah=*((UCHAR *)(ROMAddr+REFIndex));
+       tempah=tempah&0x01;
+       tempah=tempah<<5;
+       modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));     // si+St_ModeFlag
+       if(modeflag1&DoubleScanMode){
+               tempah=tempah|0x080;
+       }
+       SetRegANDOR(P3d4,0x09,~0x020,tempah);
+       REFIndex=OldREFIndex;
+       return; 
+}
+
+VOID SetCRT2ECLK(ULONG ROMAddr, USHORT ModeNo)
+{
+       USHORT OldREFIndex,tempah,tempal;
+       USHORT P3cc=P3c9+3;
+       OldREFIndex=(USHORT)REFIndex;
+       if(IF_DEF_TRUMPION==0){ //no trumpion
+               tempal=GetReg2(P3cc);
+               tempal=tempal&0x0C;
+               SetReg3(P3c2,tempal);
+               REFIndex=GetVCLKPtr(ROMAddr,ModeNo);
+       }else{  //trumpion
+               SetFlag=SetFlag&(~ProgrammingCRT2);
+               tempal=*((UCHAR *)(ROMAddr+REFIndex+0x03));      //di+Ext_CRTVCLK
+               tempal=tempal&0x03F;
+               if(tempal==0x02){ //31.5MHz
+                       REFIndex=REFIndex-Ext2StructSize;
+               }
+               REFIndex=GetVCLKPtr(ROMAddr,ModeNo);
+               SetFlag=SetFlag|ProgrammingCRT2;
+       }
+       tempal=0x02B;
+       if(!(VBInfo&SetInSlaveMode)){
+               tempal=tempal+3;
+       }
+       tempah=*((UCHAR *)(ROMAddr+REFIndex));  
+       SetReg1(P3c4,tempal,tempah);
+       tempah=*((UCHAR *)(ROMAddr+REFIndex+1));
+       tempal++; 
+       SetReg1(P3c4,tempal,tempah);
+       REFIndex=OldREFIndex;
+       return;
+}
+
+USHORT GetLVDSDesPtr(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempcl,tempbx,tempal,tempptr,LVDSDesPtrData;
+       tempcl=LVDSDesDataLen;
+       tempbx=LCDTypeInfo;
+       if(LCDInfo&LCDNonExpanding){
+               tempbx=tempbx+16;
+       }
+       if(ModeNo<=0x13){
+               tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
+       }else{
+               tempal=*((UCHAR *)(ROMAddr+REFIndex+4));         //di+Ext_CRT2CRTC
+       }
+       tempal=tempal&0x1F;
+       tempal=tempal*tempcl;
+       tempbx=tempbx<<1;
+       LVDSDesPtrData=*((USHORT *)(ROMAddr+ADR_LVDSDesPtrData));
+       tempptr=*((USHORT *)(ROMAddr+LVDSDesPtrData+tempbx));
+       tempptr=tempptr+tempal;
+       return(tempptr);
+       
+}
+
+BOOLEAN GetLVDSCRT1Ptr(ULONG ROMAddr,USHORT ModeNo)
+{
+       USHORT tempal,tempbx,modeflag1; 
+       USHORT LVDSCRT1DataPtr; 
+
+       if(!(VBInfo&SetInSlaveMode)){
+               return 0;
+       }
+       if(ModeNo<=0x13){
+               tempal=*((UCHAR *)(ROMAddr+ModeIDOffset+0x04)); // si+St_CRT2CRTC
+       }else{
+               tempal=*((UCHAR *)(ROMAddr+REFIndex+4));         //di+Ext_CRT2CRTC
+       }
+       tempal=tempal&0x3F;
+
+       tempbx=LCDResInfo;
+       tempbx=tempbx-Panel800x600;
+       if(LCDInfo&LCDNonExpanding){
+               tempbx=tempbx+6;
+       }
+       modeflag1=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));     // si+St_ModeFlag
+       if(modeflag1&HalfDCLK){
+               tempbx=tempbx+3;
+       }
+       tempbx=tempbx<<1;
+       LVDSCRT1DataPtr=*((USHORT *)(ROMAddr+ADR_LVDSCRT1DataPtr));
+       REFIndex=*((USHORT *)(ROMAddr+LVDSCRT1DataPtr+tempbx));
+       tempal=tempal*LVDSCRT1Len;
+       REFIndex=REFIndex+tempal;
+       return 1;
+}
+
+#endif
\ No newline at end of file
diff --git a/drivers/video/sis/sis_301.h b/drivers/video/sis/sis_301.h
new file mode 100644 (file)
index 0000000..0f38590
--- /dev/null
@@ -0,0 +1,223 @@
+#include "initdef.h"
+
+USHORT SetFlag,RVBHCFACT,RVBHCMAX,VGAVT,VGAHT,VT,HT,VGAVDE,VGAHDE;
+USHORT VDE,HDE,RVBHRS,NewFlickerMode,RY1COE,RY2COE,RY3COE,RY4COE;                
+;USHORT LCDResInfo,LCDTypeInfo,LCDInfo;
+USHORT VCLKLen;
+USHORT LCDHDES,LCDVDES;
+
+USHORT StResInfo[5][2]={{640,400},{640,350},{720,400},{720,350},{640,480}};
+
+USHORT ModeResInfo[15][4]={{320,200,8,8},{320,240,8,8},{320,400,8,8},
+                       {400,300,8,8},{512,384,8,8},{640,400,8,16},
+                       {640,480,8,16},{800,600,8,16},{1024,768,8,16},
+                       {1280,1024,8,16},{1600,1200,8,16},{1920,1440,8,16},
+                       {720,480,8,16},{720,576,8,16},{1280,960,8,16}};
+
+
+USHORT NTSCTiming[61]={0x017,0x01D,0x003,0x009,0x005,0x006,0x00C,0x00C,
+                    0x094,0x049,0x001,0x00A,0x006,0x00D,0x004,0x00A,
+                    0x006,0x014,0x00D,0x004,0x00A,0x000,0x085,0x01B,
+                    0x00C,0x050,0x000,0x099,0x000,0x0EC,0x04A,0x017,
+                    0x088,0x000,0x04B,0x000,0x000,0x0E2,0x000,0x002,
+                    0x003,0x00A,0x065,0x09D,0x008,
+                    0x092,0x08F,0x040,0x060,0x080,0x014,0x090,0x08C,
+                    0x060,0x014,0x050,0x000,0x040,
+                    0x00044,0x002DB,0x0003B};//Ajust xxx
+
+USHORT PALTiming[61]={ 0x019,0x052,0x035,0x06E,0x004,0x038,0x03D,0x070,
+                    0x094,0x049,0x001,0x012,0x006,0x03E,0x035,0x06D,
+                    0x006,0x014,0x03E,0x035,0x06D,0x000,0x045,0x02B,
+                    0x070,0x050,0x000,0x097,0x000,0x0D7,0x05D,0x017,
+                    0x088,0x000,0x045,0x000,0x000,0x0E8,0x000,0x002,
+                    0x00D,0x000,0x068,0x0B0,0x00B,
+                    0x092,0x08F,0x040,0x060,0x080,0x014,0x090,0x08C,
+                    0x060,0x014,0x063,0x000,0x040,
+                    0x0003E,0x002E1,0x00028};//Ajust xxx
+
+USHORT HiTVTiming[61]={0x017,0x01D,0x003,0x009,0x005,0x006,0x00C,0x00C,
+                    0x094,0x049,0x001,0x00A,0x006,0x00D,0x004,0x00A,
+                    0x006,0x014,0x00D,0x004,0x00A,0x000,0x085,0x01B,
+                    0x00C,0x050,0x000,0x099,0x000,0x0EC,0x04A,0x017,
+                    0x088,0x000,0x04B,0x000,0x000,0x0E2,0x000,0x002,
+                    0x003,0x00A,0x065,0x09D,0x008,
+                    0x092,0x08F,0x040,0x060,0x080,0x014,0x090,0x08C,
+                    0x060,0x014,0x050,0x000,0x040,
+                    0x00027,0x0FFFC,0x0003B};//Ajust xxx
+
+USHORT HiTVTimingSimu[61]={0x020,0x054,0x02C,0x060,0x008,0x031,0x03A,0x061,
+                        0x028,0x002,0x001,0x03D,0x006,0x00D,0x004,0x00A,
+                        0x006,0x014,0x00D,0x004,0x00A,0x000,0x0C5,0x03F,
+                        0x064,0x090,0x000,0x0AA,0x000,0x006,0x060,0x003,
+                        0x011,0x005,0x011,0x00F,0x010,0x011,0x000,0x000,
+                        0x005,0x005,0x034,0x034,0x008,
+                        0x092,0x00F,0x040,0x060,0x080,0x014,0x090,0x08C,
+                        0x060,0x004,0x05F,0x000,0x060,
+                        0x0000E,0x0FFFC,0x00042};//Ajust xxx
+
+USHORT HiTVGroup3Data[63]={0x000,0x01A,0x022,0x063,0x062,0x022,0x008,0x05B,
+                        0x0FF,0x021,0x0AD,0x0AD,0x055,0x077,0x02A,0x0A6,
+                        0x025,0x02F,0x047,0x0FA,0x0C8,0x0FF,0x08E,0x020,
+                        0x08C,0x06E,0x060,0x02D,0x056,0x047,0x070,0x044,
+                        0x056,0x036,0x04F,0x06E,0x03F,0x080,0x000,0x080,
+                        0x045,0x07D,0x003,0x0A5,0x076,0x020,0x01A,0x0A4,
+                        0x014,0x005,0x003,0x07E,0x064,0x031,0x014,0x075,
+                        0x018,0x005,0x018,0x005,0x04C,0x0A8,0x001};
+
+USHORT HiTVGroup3Simu[63]={0x000,0x01A,0x022,0x063,0x062,0x022,0x008,0x094,
+                        0x0DA,0x020,0x0B7,0x0B7,0x055,0x047,0x02A,0x0A6,
+                        0x025,0x02F,0x047,0x0FA,0x0C8,0x0FF,0x08E,0x020,
+                        0x08C,0x06E,0x060,0x015,0x026,0x0D3,0x0E4,0x011,
+                        0x056,0x036,0x04F,0x06E,0x03F,0x080,0x000,0x080,
+                        0x066,0x035,0x001,0x047,0x00E,0x010,0x0BE,0x0B4,
+                        0x001,0x005,0x003,0x07E,0x065,0x031,0x014,0x075,
+                        0x018,0x005,0x018,0x005,0x04C,0x0A8,0x001};
+
+USHORT NTSCGroup3Data[63]= {0x000,0x014,0x015,0x025,0x055,0x015,0x00B,0x089,
+                         0x0D7,0x040,0x0B0,0x0B0,0x0FF,0x0C4,0x045,0x0A6,
+                         0x025,0x02F,0x067,0x0F6,0x0BF,0x0FF,0x08E,0x020,
+                         0x08C,0x0DA,0x060,0x092,0x0C8,0x055,0x08B,0x000,
+                         0x051,0x004,0x018,0x00A,0x0F8,0x087,0x000,0x080,
+                         0x03B,0x03B,0x000,0x0F0,0x0F0,0x000,0x0F0,0x0F0,
+                         0x000,0x051,0x00F,0x00F,0x008,0x00F,0x008,0x06F,
+                         0x018,0x005,0x005,0x005,0x04C,0x0AA,0x001};
+
+USHORT PALGroup3Data[63]={0x000,0x01A,0x022,0x063,0x062,0x022,0x008,0x085,
+                       0x0C3,0x020,0x0A4,0x0A4,0x055,0x047,0x02A,0x0A6,
+                       0x025,0x02F,0x047,0x0FA,0x0C8,0x0FF,0x08E,0x020,
+                       0x08C,0x0DC,0x060,0x092,0x0C8,0x04F,0x085,0x000,
+                       0x056,0x036,0x04F,0x06E,0x0FE,0x083,0x054,0x081,
+                       0x030,0x030,0x000,0x0F3,0x0F3,0x000,0x0A2,0x0A2,
+                       0x000,0x048,0x0FE,0x07E,0x008,0x040,0x008,0x091,
+                       0x018,0x005,0x018,0x005,0x04C,0x0A8,0x001};
+
+VOID overwriteregs(ULONG ROMAddr, USHORT BaseAddr);
+VOID SetDefCRT2ExtRegs(USHORT BaseAddr);
+BOOLEAN SetCRT2Group(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+USHORT GetRatePtrCRT2(ULONG ROMAddr, USHORT ModeNo);
+BOOLEAN AjustCRT2Rate(ULONG ROMAddr);
+VOID SaveCRT2Info(USHORT ModeNo);
+VOID DisableLockRegs(VOID);
+VOID DisableCRT2(VOID);
+VOID DisableBridge(USHORT  BaseAddr);
+VOID GetCRT2Data(ULONG ROMAddr,USHORT ModeNo);
+VOID GetResInfo(ULONG ROMAddr,USHORT ModeNo);
+VOID GetRAMDAC2DATA(ULONG ROMAddr,USHORT ModeNo);
+VOID GetCRT2Ptr(ULONG ROMAddr,USHORT ModeNo);
+VOID UnLockCRT2(USHORT BaseAddr);
+VOID SetCRT2ModeRegs(USHORT BaseAddr,USHORT ModeNo);
+VOID SetGroup1(USHORT  BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+VOID SetCRT2Offset(USHORT Part1Port,ULONG ROMAddr);
+USHORT GetOffset(ULONG ROMAddr);
+USHORT GetColorDepth(ULONG ROMAddr);
+VOID SetCRT2FIFO(USHORT  Part1Port,ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+USHORT GetVCLK(ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+USHORT GetVCLKPtr(ULONG ROMAddr,USHORT ModeNo);
+USHORT GetColorTh(ULONG ROMAddr);
+USHORT GetMCLK(ULONG ROMAddr);
+USHORT GetMCLKPtr(ULONG ROMAddr);
+USHORT GetDRAMType(ULONG ROMAddr);
+#ifndef CONFIG_FB_SIS_LINUXBIOS
+static USHORT CalcDelay(VOID);
+#endif
+USHORT GetVCLK2Ptr(ULONG ROMAddr,USHORT ModeNo);
+VOID SetCRT2Sync(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo);
+VOID GetCRT1Ptr(ULONG ROMAddr);
+VOID SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+USHORT GetVGAHT2(VOID);
+VOID SetGroup2(USHORT  BaseAddr,ULONG ROMAddr);
+VOID SetGroup3(USHORT  BaseAddr);
+VOID SetGroup4(USHORT  BaseAddr,ULONG ROMAddr,USHORT ModeNo);
+VOID SetCRT2VCLK(USHORT BaseAddr,ULONG ROMAddr,USHORT ModeNo);
+VOID SetGroup5(USHORT  BaseAddr,ULONG ROMAddr);
+VOID EnableCRT2(VOID);
+VOID LoadDAC2(ULONG ROMAddr,USHORT Part5Port);
+VOID WriteDAC2(USHORT Pdata,USHORT dl, USHORT ah, USHORT al, USHORT dh);
+VOID LockCRT2(USHORT BaseAddr);
+VOID SetLockRegs(VOID);
+VOID EnableBridge(USHORT BaseAddr);
+USHORT GetLockInfo(USHORT pattern);
+VOID GetVBInfo(USHORT BaseAddr,ULONG ROMAddr);
+BOOLEAN BridgeIsEnable(USHORT BaseAddr);
+BOOLEAN BridgeInSlave(VOID);
+BOOLEAN GetLCDResInfo(ULONG ROMAddr,USHORT P3d4);
+VOID PresetScratchregister(USHORT P3d4,PHW_DEVICE_EXTENSION HwDeviceExtension);
+BOOLEAN GetLCDDDCInfo(PHW_DEVICE_EXTENSION HwDeviceExtension);
+VOID SetTVSystem(PHW_DEVICE_EXTENSION HwDeviceExtension,ULONG ROMAddr);
+BOOLEAN GetSenseStatus(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT BaseAddr,ULONG ROMAddr);
+BOOLEAN Sense(USHORT Part4Port,USHORT inputbx,USHORT inputcx);
+BOOLEAN SenseLCD(PHW_DEVICE_EXTENSION HwDeviceExtension,USHORT Part4Port,ULONG ROMAddr);
+BOOLEAN TestMonitorType(USHORT d1,USHORT d2,USHORT d3);
+VOID WaitDisplay(VOID);
+BOOLEAN DetectMonitor(PHW_DEVICE_EXTENSION HwDeviceExtension);
+VOID LongWait(VOID);
+//VOID ClearALLBuffer(PHW_DEVICE_EXTENSION HwDeviceExtension);
+USHORT GetQueueConfig(VOID);
+VOID VBLongWait(VOID);
+USHORT GetVCLKLen(ULONG ROMAddr);
+BOOLEAN WaitVBRetrace(USHORT  BaseAddr);
+VOID GetLVDSDesData(ULONG ROMAddr,USHORT ModeNo);
+VOID ModCRT1CRTC(ULONG ROMAddr,USHORT ModeNo);
+VOID SetCRT2ECLK(ULONG ROMAddr, USHORT ModeNo);
+VOID GetCRT2Data301(ULONG ROMAddr,USHORT ModeNo);
+VOID GetCRT2DataLVDS(ULONG ROMAddr,USHORT ModeNo);
+USHORT GetLVDSDesPtr(ULONG ROMAddr,USHORT ModeNo);
+VOID SetGroup1_301(USHORT  BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+VOID SetGroup1_LVDS(USHORT  BaseAddr,ULONG ROMAddr,USHORT ModeNo,
+       PHW_DEVICE_EXTENSION HwDeviceExtension);
+VOID SetTPData(VOID);
+BOOLEAN GetPanelID(VOID);
+BOOLEAN GetLVDSCRT1Ptr(ULONG ROMAddr,USHORT ModeNo);
+
+extern USHORT DRAMType[17][5];
+extern USHORT MDA_DAC[];
+extern USHORT CGA_DAC[];
+extern USHORT EGA_DAC[];
+extern USHORT VGA_DAC[];
+
+extern USHORT   P3c4,P3d4,P3c0,P3ce,P3c2,P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
+extern USHORT  flag_clearbuffer; //0:no clear frame buffer 1:clear frame buffer
+extern int      RAMType;
+extern int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,VCLKData,MCLKData, ECLKData;
+extern int      REFIndex,ModeType;
+extern USHORT VBInfo,LCDResInfo,LCDTypeInfo,LCDInfo;
+extern USHORT   IF_DEF_LVDS,IF_DEF_TRUMPION;
+
+extern VOID     SetMemoryClock(ULONG);
+extern VOID     SetDRAMSize(PHW_DEVICE_EXTENSION);
+extern BOOLEAN  SearchModeID(ULONG, USHORT);
+extern BOOLEAN  CheckMemorySize(ULONG);
+extern VOID     GetModePtr(ULONG, USHORT);
+extern BOOLEAN  GetRatePtr(ULONG, USHORT);
+extern VOID     SetSeqRegs(ULONG);
+extern VOID     SetMiscRegs(ULONG);
+extern VOID     SetCRTCRegs(ULONG);
+extern VOID     SetATTRegs(ULONG);
+extern VOID     SetGRCRegs(ULONG);
+extern VOID     ClearExt1Regs(VOID);
+extern VOID     SetSync(ULONG);
+extern VOID     SetCRT1CRTC(ULONG);
+extern VOID     SetCRT1Offset(ULONG);
+extern VOID     SetCRT1FIFO(ULONG);
+extern VOID     SetCRT1VCLK(ULONG);
+extern VOID     LoadDAC(ULONG);
+extern VOID     DisplayOn(VOID);
+extern VOID     SetCRT1ModeRegs(ULONG, USHORT);
+extern VOID     SetVCLKState(ULONG, USHORT);
+extern VOID     WriteDAC(USHORT, USHORT, USHORT, USHORT);
+extern VOID     ClearBuffer(PHW_DEVICE_EXTENSION);
+//extern VOID  ClearDAC(ULONG);
+extern void    ClearDAC(u16 port);
+extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
+                                       USHORT ModeNo);
+extern void SetReg1(u16 port, u16 index, u16 data);
+extern void SetReg3(u16 port, u16 data);
+extern void SetReg4(u16 port, unsigned long data);
+extern u8 GetReg1(u16 port, u16 index);
+extern u8 GetReg2(u16 port);
+extern u32 GetReg3(u16 port);
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
new file mode 100644 (file)
index 0000000..0f24d4f
--- /dev/null
@@ -0,0 +1,2373 @@
+/*
+ * SiS 300/630/540 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 
+ * 
+ * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#define EXPORT_SYMTAB
+#undef  SISFBDEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vt_kern.h>
+#include <linux/capability.h>
+#include <linux/sisfb.h>
+#include <linux/fs.h>
+
+#include <asm/io.h>
+#include <asm/mtrr.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#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
+
+/* 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)
+
+#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)
+
+#define SIS_MEM_MAP_IO_ENABLE     (0x01)
+#define SIS_PCI_ADDR_ENABLE       (0x80)
+
+//#define MMIO_SIZE                 0x10000    /* 64K MMIO capability */
+#define MAX_ROM_SCAN              0x10000
+
+#define RESERVED_MEM_SIZE_4M      0x400000     /* 4M */
+#define RESERVED_MEM_SIZE_8M      0x800000     /* 8M */
+
+/* Mode set stuff */
+#define DEFAULT_MODE         0 /* 640x480x8 */
+#define DEFAULT_LCDMODE      9 /* 800x600x8 */
+#define DEFAULT_TVMODE       9 /* 800x600x8 */
+
+/* heap stuff */
+#define OH_ALLOC_SIZE         4000
+#define SENTINEL              0x7fffffff
+
+#define TURBO_QUEUE_AREA_SIZE 0x80000  /* 512K */
+#define HW_CURSOR_AREA_SIZE   0x1000   /* 4K */
+
+/* ------------------- Global Variables ----------------------------- */
+
+struct video_info ivideo;
+HW_DEVICE_EXTENSION HwExt={0,0,0,0,0,0};
+
+struct GlyInfo {
+       unsigned char ch;
+       int fontwidth;
+       int fontheight;
+       u8 gmask[72];
+       int ngmask;
+};
+
+/* 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}
+};
+
+/* 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}
+};
+
+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;
+
+static int inverse = 0;
+static int currcon = 0;
+
+static struct display_switch sisfb_sw;
+
+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}
+};
+
+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}
+};
+
+
+/* HEAP stuff */
+
+struct OH {
+       struct OH *pohNext;
+       struct OH *pohPrev;
+       unsigned long ulOffset;
+       unsigned long ulSize;
+};
+
+struct OHALLOC {
+       struct OHALLOC *pohaNext;
+       struct OH aoh[1];
+};
+
+struct HEAP {
+       struct OH ohFree;
+       struct OH ohUsed;
+       struct OH *pohFreeList;
+       struct OHALLOC *pohaChain;
+
+       unsigned long ulMaxFreeSize;
+};
+
+struct HEAP heap;
+unsigned long heap_start;
+unsigned long heap_end;
+unsigned long heap_size;
+
+unsigned int tqueue_pos;
+unsigned long hwcursor_vbase;
+
+
+/* -------------------- Macro definitions --------------------------- */
+
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#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))
+
+/* ---------------------- Routine Prototype ------------------------- */
+
+/* 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);
+
+/* 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);
+
+/* 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);
+
+/* 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);
+
+/* 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);
+
+/* ---------------------- Internal Routines ------------------------- */
+
+inline static u32 RD32(unsigned char *base, s32 off)
+{
+       return readl(base + off);
+}
+
+inline static void WR32(unsigned char *base, s32 off, u32 v)
+{
+       writel(v, base + off);
+}
+
+inline static void WR16(unsigned char *base, s32 off, u16 v)
+{
+       writew(v, base + off);
+}
+
+inline static void WR8(unsigned char *base, s32 off, u8 v)
+{
+       writeb(v, base + off);
+}
+
+inline static u32 regrl(s32 off)
+{
+       return RD32(ivideo.mmio_vbase, off);
+}
+
+inline static void regwl(s32 off, u32 v)
+{
+       WR32(ivideo.mmio_vbase, off, v);
+}
+
+inline static void regww(s32 off, u16 v)
+{
+       WR16(ivideo.mmio_vbase, off, v);
+}
+
+inline static void regwb(s32 off, u8 v)
+{
+       WR8(ivideo.mmio_vbase, off, v);
+}
+
+/* 
+ *    Get CRTC registers to set var 
+ */
+static void crtc_to_var(struct fb_var_screeninfo *var)
+{
+       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;
+
+       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;
+       }
+
+       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:                /* 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;
+
+               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;
+               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(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;
+
+       vgawb(CRTC_ADR, 0x4);
+       uCRdata = vgarb(CRTC_DATA);
+       HRS = (uCRdata & 0xff) | ((u16) (uSRdata & 0xC0) << 2);
+       F = HRS - E - 3;
+
+       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);
+
+       temp = HBE - ((E - 1) & 255);
+       B = (temp > 0) ? temp : (temp + 256);
+
+       temp = HRE - ((E + F + 3) & 63);
+       C = (temp > 0) ? temp : (temp + 64);
+
+       D = B - F - C;
+
+       var->xres = var->xres_virtual = E * 8;
+       var->left_margin = D * 8;
+       var->right_margin = F * 8;
+       var->hsync_len = C * 8;
+
+       var->activate = FB_ACTIVATE_NOW;
+
+       var->sync = 0;
+
+       uMRdata = vgarb(0x1C);
+       if (uMRdata & 0x80)
+               var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+       else
+               var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+       if (uMRdata & 0x40)
+               var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+       else
+               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);
+}
+
+static void sisfb_set_disp(int con, struct fb_var_screeninfo *var)
+{
+       struct fb_fix_screeninfo fix;
+       struct display *display;
+       struct display_switch *sw;
+       u32 flags;
+
+       if (con >= 0)
+               display = &fb_display[con];
+       else
+               display = &disp;        /* used during initialization */
+
+       sisfb_get_fix(&fix, con, 0);
+
+       display->screen_base = ivideo.video_vbase;
+       display->visual = fix.visual;
+       display->type = fix.type;
+       display->type_aux = fix.type_aux;
+       display->ypanstep = fix.ypanstep;
+       display->ywrapstep = fix.ywrapstep;
+       display->line_length = fix.line_length;
+       display->next_line = fix.line_length;
+       /*display->can_soft_blank = 1; */
+       display->can_soft_blank = 0;
+       display->inverse = inverse;
+       display->var = *var;
+
+       save_flags(flags);
+       switch (ivideo.video_bpp) {
+#ifdef FBCON_HAS_CFB8
+       case 8:
+               sw = &fbcon_cfb8;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB16
+       case 15:
+       case 16:
+               sw = &fbcon_cfb16;
+               display->dispsw_data = fbcon_cmap.cfb16;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB24
+       case 24:
+               sw = &fbcon_cfb24;
+               display->dispsw_data = fbcon_cmap.cfb24;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB32
+       case 32:
+               sw = &fbcon_cfb32;
+               display->dispsw_data = fbcon_cmap.cfb32;
+               break;
+#endif
+       default:
+               sw = &fbcon_dummy;
+               return;
+       }
+       memcpy(&sisfb_sw, sw, sizeof(*sw));
+       display->dispsw = &sisfb_sw;
+       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)
+{
+       if (regno >= video_cmap_len)
+               return 1;
+
+       *red = palette[regno].red;
+       *green = palette[regno].green;
+       *blue = palette[regno].blue;
+       *transp = 0;
+       return 0;
+}
+
+/*
+ *    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;
+
+       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);
+               }
+
+               break;
+#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:
+               red >>= 8;
+               green >>= 8;
+               blue >>= 8;
+               fbcon_cmap.cfb32[regno] =
+                   (red << 16) | (green << 8) | (blue);
+               break;
+#endif
+       }
+       return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+       if (con != currcon)
+               return;
+
+       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);
+}
+
+static int 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;
+
+       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;
+
+
+       if (!htotal || !vtotal) {
+               DPRINTK("Invalid 'var' Information!\n");
+               return 1;
+       }
+
+       drate = 1E12 / var->pixclock;
+       hrate = drate / htotal;
+       ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+
+       old_mode = mode_idx;
+       mode_idx = 0;
+
+       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(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;
+                               break;
+                       case LCD1920:
+                               if(var->xres > 1920)
+                                       found_mode = 0;
+                               break;
+                       case LCD1600:
+                               if(var->xres > 1600)
+                                       found_mode = 0;
+                               break;
+                       case LCD800:
+                               if(var->xres > 800)
+                                       found_mode = 0;
+                               break;
+                       case LCD640:
+                               if(var->xres > 640)
+                                       found_mode = 0;
+                               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;
+                               }
+                               break;
+                       default:
+                               /* illegal mode */
+                               found_mode = 0;
+                       }
+                       break;
+               }
+       }
+
+       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 (search_refresh_rate(ivideo.refresh_rate) == 0) {
+               /* not supported rate */
+               rate_idx = sisbios_mode[mode_idx].rate_idx;
+               ivideo.refresh_rate = 60;
+       }
+
+       if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
+               pre_setmode();
+
+               if (SiSSetMode(&HwExt, mode_no)) {
+                       DPRINTK("sisfb: set mode[0x%x]: failed\n",
+                               mode_no);
+                       return 1;
+               }
+
+               post_setmode();
+
+               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);
+
+               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);
+
+               DPRINTK("Current Mode: %dx%d-%d line_length=%d\n",
+                       ivideo.video_width, ivideo.video_height,
+                       ivideo.video_bpp, video_linelength);
+       }
+
+       return 0;
+}
+
+/* ---------------------- Draw Funtions ----------------------------- */
+
+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;
+
+
+       gly->fontheight = fontheight(p);
+       gly->fontwidth = fontwidth(p);
+       widthb = (fontwidth(p) + 7) / 8;
+
+       c = gly->ch & p->charmask;
+       if (fontwidth(p) <= 8)
+               cdat = p->fontdata + c * fontheight(p);
+       else
+               cdat = p->fontdata + (c * fontheight(p) << 1);
+
+       size = fontheight(p) * widthb;
+       memcpy(gbuf, cdat, size);
+       gly->ngmask = size;
+}
+
+
+/* ---------------------- HEAP Routines ----------------------------- */
+
+/* 
+ *  Heap Initialization
+ */
+
+static int sisfb_heap_init(void)
+{
+       struct OH *poh;
+       u8 jTemp, tq_state;
+
+       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;
+
+       heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
+       heap_size = heap_end - heap_start;
+
+
+       /* 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);
+               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;
+       }
+
+       /* 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;
+
+               caps |= HW_CURSOR_CAP;
+       }
+
+       heap.pohaChain = NULL;
+       heap.pohFreeList = NULL;
+
+       poh = 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;
+
+       return 0;
+}
+
+/*
+ *  Allocates a basic memory unit in which we'll pack our data structures.
+ */
+
+static struct OH *poh_new_node(void)
+{
+       int i;
+       unsigned long cOhs;
+       struct OHALLOC *poha;
+       struct OH *poh;
+
+       if (heap.pohFreeList == NULL) {
+               poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+
+               poha->pohaNext = heap.pohaChain;
+               heap.pohaChain = poha;
+
+               cOhs =
+                   (OH_ALLOC_SIZE -
+                    sizeof(struct OHALLOC)) / sizeof(struct OH) + 1;
+
+               poh = &poha->aoh[0];
+               for (i = cOhs - 1; i != 0; i--) {
+                       poh->pohNext = poh + 1;
+                       poh = poh + 1;
+               }
+
+               poh->pohNext = NULL;
+               heap.pohFreeList = &poha->aoh[0];
+       }
+
+       poh = heap.pohFreeList;
+       heap.pohFreeList = poh->pohNext;
+
+       return (poh);
+}
+
+/* 
+ *  Allocates space, return NULL when failed
+ */
+
+static struct OH *poh_allocate(unsigned long size)
+{
+       struct OH *pohThis;
+       struct OH *pohRoot;
+       int bAllocated = 0;
+
+       if (size > heap.ulMaxFreeSize) {
+               DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+                       (unsigned int) size / 1024);
+               return (NULL);
+       }
+
+       pohThis = heap.ohFree.pohNext;
+
+       while (pohThis != &heap.ohFree) {
+               if (size <= pohThis->ulSize) {
+                       bAllocated = 1;
+                       break;
+               }
+               pohThis = pohThis->pohNext;
+       }
+
+       if (!bAllocated) {
+               DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+                       (unsigned int) size / 1024);
+               return (NULL);
+       }
+
+       if (size == pohThis->ulSize) {
+               pohRoot = pohThis;
+               delete_node(pohThis);
+       } else {
+               pohRoot = poh_new_node();
+
+               if (pohRoot == NULL) {
+                       return (NULL);
+               }
+
+               pohRoot->ulOffset = pohThis->ulOffset;
+               pohRoot->ulSize = size;
+
+               pohThis->ulOffset += size;
+               pohThis->ulSize -= size;
+       }
+
+       heap.ulMaxFreeSize -= size;
+
+       pohThis = &heap.ohUsed;
+       insert_node(pohThis, pohRoot);
+
+       return (pohRoot);
+}
+
+/* 
+ *  To remove a node from a list.
+ */
+
+static void delete_node(struct OH *poh)
+{
+       struct OH *pohPrev;
+       struct OH *pohNext;
+
+
+       pohPrev = poh->pohPrev;
+       pohNext = poh->pohNext;
+
+       pohPrev->pohNext = pohNext;
+       pohNext->pohPrev = pohPrev;
+
+       return;
+}
+
+/* 
+ *  To insert a node into a list.
+ */
+
+static void insert_node(struct OH *pohList, struct OH *poh)
+{
+       struct OH *pohTemp;
+
+       pohTemp = pohList->pohNext;
+
+       pohList->pohNext = poh;
+       pohTemp->pohPrev = poh;
+
+       poh->pohPrev = pohList;
+       poh->pohNext = pohTemp;
+}
+
+/*
+ *  Frees an off-screen heap allocation.
+ */
+
+static struct OH *poh_free(unsigned long base)
+{
+
+       struct OH *pohThis;
+       struct OH *pohFreed;
+       struct OH *pohPrev;
+       struct OH *pohNext;
+       unsigned long ulUpper;
+       unsigned long ulLower;
+       int foundNode = 0;
+
+       pohFreed = heap.ohUsed.pohNext;
+
+       while (pohFreed != &heap.ohUsed) {
+               if (pohFreed->ulOffset == base) {
+                       foundNode = 1;
+                       break;
+               }
+
+               pohFreed = pohFreed->pohNext;
+       }
+
+       if (!foundNode)
+               return (NULL);
+
+       heap.ulMaxFreeSize += pohFreed->ulSize;
+
+       pohPrev = pohNext = NULL;
+       ulUpper = pohFreed->ulOffset + pohFreed->ulSize;
+       ulLower = pohFreed->ulOffset;
+
+       pohThis = heap.ohFree.pohNext;
+
+       while (pohThis != &heap.ohFree) {
+               if (pohThis->ulOffset == ulUpper) {
+                       pohNext = pohThis;
+               }
+                       else if ((pohThis->ulOffset + pohThis->ulSize) ==
+                                ulLower) {
+                       pohPrev = pohThis;
+               }
+               pohThis = pohThis->pohNext;
+       }
+
+       delete_node(pohFreed);
+
+       if (pohPrev && pohNext) {
+               pohPrev->ulSize += (pohFreed->ulSize + pohNext->ulSize);
+               delete_node(pohNext);
+               free_node(pohFreed);
+               free_node(pohNext);
+               return (pohPrev);
+       }
+
+       if (pohPrev) {
+               pohPrev->ulSize += pohFreed->ulSize;
+               free_node(pohFreed);
+               return (pohPrev);
+       }
+
+       if (pohNext) {
+               pohNext->ulSize += pohFreed->ulSize;
+               pohNext->ulOffset = pohFreed->ulOffset;
+               free_node(pohFreed);
+               return (pohNext);
+       }
+
+       insert_node(&heap.ohFree, pohFreed);
+
+       return (pohFreed);
+}
+
+/*
+ *  Frees our basic data structure allocation unit by adding it to a free
+ *  list.
+ */
+
+static void free_node(struct OH *poh)
+{
+       if (poh == NULL) {
+               return;
+       }
+
+       poh->pohNext = heap.pohFreeList;
+       heap.pohFreeList = poh;
+
+       return;
+}
+
+void sis_malloc(struct sis_memreq *req)
+{
+       struct OH *poh;
+
+       poh = poh_allocate(req->size);
+
+       if (poh == NULL) {
+               req->offset = 0;
+               req->size = 0;
+               DPRINTK("sisfb: VMEM Allocation Failed\n");
+       } else {
+               DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n",
+                       (char *) (poh->ulOffset +
+                                 (unsigned long) ivideo.video_vbase));
+
+               req->offset = poh->ulOffset;
+               req->size = poh->ulSize;
+       }
+
+}
+
+void sis_free(unsigned long base)
+{
+       struct OH *poh;
+
+       poh = poh_free(base);
+
+       if (poh == NULL) {
+               DPRINTK("sisfb: poh_free() failed at base 0x%x\n",
+                       (unsigned int) base);
+       }
+}
+
+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; 
+       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;
+               break;
+       default:
+               rec->chip = SiS_UNKNOWN;
+               break;
+       }
+}
+
+
+/* ---------------------- SetMode Routines -------------------------- */
+
+void SetReg1(u16 port, u16 index, u16 data)
+{
+       outb((u8) (index & 0xff), port);
+       port++;
+       outb((u8) (data & 0xff), port);
+}
+
+void SetReg3(u16 port, u16 data)
+{
+       outb((u8) (data & 0xff), port);
+}
+
+void SetReg4(u16 port, unsigned long data)
+{
+       outl((u32) (data & 0xffffffff), port);
+}
+
+u8 GetReg1(u16 port, u16 index)
+{
+       u8 data;
+
+       outb((u8) (index & 0xff), port);
+       port += 1;
+       data = inb(port);
+       return (data);
+}
+
+u8 GetReg2(u16 port)
+{
+       u8 data;
+
+       data = inb(port);
+
+       return (data);
+}
+
+u32 GetReg3(u16 port)
+{
+       u32 data;
+
+       data = inl(port);
+       return (data);
+}
+
+void ClearDAC(u16 port)
+{
+       int i,j;
+
+       vgawb(DAC_ADR, 0x00);
+       for(i=0; i<256; i++)
+               for(j=0; j<3; j++)
+                       vgawb(DAC_DATA, 0);
+}
+
+void ClearBuffer(PHW_DEVICE_EXTENSION pHwExt)
+{
+       memset((char *) ivideo.video_vbase, 0,
+               video_linelength * ivideo.video_height);
+}
+
+static void pre_setmode(void)
+{
+       unsigned char  uCR30=0, uCR31=0;
+
+       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;
+       }
+
+       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);
+}
+
+static void post_setmode(void)
+{
+       u8 uTemp;
+
+       vgawb(CRTC_ADR, 0x17);
+       uTemp = vgarb(CRTC_DATA);
+
+       if(crt1off)       /* turn off CRT1 */
+               uTemp &= ~0x80;
+       else          /* turn on CRT1 */
+               uTemp |= 0x80;
+       vgawb(CRTC_DATA, uTemp);
+
+       /* disable 24-bit palette RAM and Gamma correction */
+       vgawb(SEQ_ADR, 0x07);
+       uTemp = vgarb(SEQ_DATA);
+       uTemp &= ~0x04;
+       vgawb(SEQ_DATA, uTemp);
+}
+
+static void search_mode(const char *name)
+{
+       int i = 0;
+
+       if (name == NULL)
+               return;
+
+       while (sisbios_mode[i].mode_no != 0) {
+               if (!strcmp(name, sisbios_mode[i].name)) {
+                       mode_idx = i;
+                       break;
+               }
+               i++;
+       }
+
+       if (mode_idx < 0)
+               DPRINTK("Invalid user mode : %s\n", name);
+}
+
+static u8 search_refresh_rate(unsigned int rate)
+{
+       u16 xres, yres;
+       int i = 0;
+
+       xres = sisbios_mode[mode_idx].xres;
+       yres = sisbios_mode[mode_idx].yres;
+
+       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++;
+       }
+
+       DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate, xres,
+               yres);
+
+       return 0;
+}
+
+/* ------------------ Public Routines ------------------------------- */
+
+/*
+ *    Get the Fixed Part of the Display
+ */
+
+static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                        struct fb_info *info)
+{
+       DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con);
+
+       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+       strcpy(fix->id, fb_info.modename);
+
+       fix->smem_start = ivideo.video_base;
+       if(ivideo.video_size > 0x800000)
+               fix->smem_len = RESERVED_MEM_SIZE_8M;   /* reserved for Xserver */
+       else
+               fix->smem_len = RESERVED_MEM_SIZE_4M;   /* reserved for Xserver */
+
+       fix->type = video_type;
+       fix->type_aux = 0;
+       if (ivideo.video_bpp == 8)
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+       else
+               fix->visual = FB_VISUAL_TRUECOLOR;
+       fix->xpanstep = 0;
+       fix->ypanstep = 0;
+       fix->ywrapstep = 0;
+       fix->line_length = video_linelength;
+       fix->mmio_start = ivideo.mmio_base;
+       fix->mmio_len = 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 */
+
+       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);
+
+       if (con == -1)
+               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)
+{
+       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 */
+               return -EINVAL;
+       }
+
+       /* get actual setting value */
+       crtc_to_var(var);
+
+       /* update display of current console */
+       sisfb_set_disp(con, var);
+
+       if (info->changevar)
+               (*info->changevar) (con);
+
+       if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+               return err;
+
+       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);
+
+       return 0;
+}
+
+
+/*
+ *    Get the Colormap
+ */
+
+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);
+       else
+               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)
+{
+       int err;
+
+       if (!fb_display[con].cmap.len) {        /* no colormap allocated */
+               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);
+       else
+               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)
+{
+       switch (cmd) {
+       case FBIO_ALLOC:
+               if(!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               sis_malloc((struct sis_memreq *) arg);
+               break;
+       case FBIO_FREE:
+               if(!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               sis_free(*(unsigned long *) arg);
+               break;
+       case FBIOGET_GLYPH:
+               sis_get_glyph((struct GlyInfo *) arg);
+               break;
+       case FBIOGET_HWCINFO:
+               {
+                       unsigned long *hwc_offset = (unsigned long *) arg;
+
+                       if (caps & HW_CURSOR_CAP)
+                               *hwc_offset = hwcursor_vbase -
+                                   (unsigned long) ivideo.video_vbase;
+                       else
+                               *hwc_offset = 0;
+
+                       break;
+               }
+       case FBIOPUT_MODEINFO:
+               {    
+                       struct mode_info *x = (struct mode_info *)arg;
+
+                       /* 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);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int sisfb_mmap(struct fb_info *info, struct file *file,
+                     struct vm_area_struct *vma)
+{
+       struct fb_var_screeninfo var;
+       unsigned long start;
+       unsigned long off;
+       u32 len;
+
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               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);
+
+       if (off >= len) {
+               /* memory mapped io */
+               off -= len;
+               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);
+       }
+
+       start &= PAGE_MASK;
+       if ((vma->vm_end - vma->vm_start + off) > len)
+               return -EINVAL;
+       off += start;
+       vma->vm_pgoff = off >> PAGE_SHIFT;
+
+#if defined(__i386__)
+       if (boot_cpu_data.x86 > 3)
+               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)) 
+               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,
+};
+
+int sisfb_setup(char *options)
+{
+       char *this_opt;
+
+       fb_info.fontname[0] = '\0';
+       ivideo.refresh_rate = 0;
+
+       if (!options || !*options)
+               return 0;
+
+       for (this_opt = strtok(options, ","); this_opt;
+            this_opt = strtok(NULL, ",")) {
+               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;
+}
+
+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)
+{
+       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_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))) 
+       {
+               currcon = con;
+               return 1;
+       }
+
+       currcon = con;
+
+       do_set_var(&fb_display[con].var, 1, info);
+
+       sisfb_set_disp(con, &fb_display[con].var);
+
+       /* Install new colormap */
+       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);
+
+       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)
+{
+       u8 CRData;
+
+       vgawb(CRTC_ADR, 0x17);
+       CRData = vgarb(CRTC_DATA);
+
+       if (blank > 0)          /* turn off CRT1 */
+               CRData &= 0x7f;
+       else                    /* turn on CRT1 */
+               CRData |= 0x80;
+
+       vgawb(CRTC_ADR, 0x17);
+       vgawb(CRTC_DATA, CRData);
+}
+
+int has_VB(void)
+{
+       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);
+
+       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;
+       }
+}
+
+void sis_get301info(void)
+{
+       u8 uCRData;
+       unsigned long disp_state=0;
+
+       if (HwExt.jChipID >= SIS_Trojan)
+       {
+               if (!has_VB())
+               {
+                       vgawb(CRTC_ADR, 0x37);
+                       uCRData = vgarb(CRTC_DATA);
+
+                       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;
+                       }
+               }
+       }
+       else
+       {
+               has_VB();
+       }
+
+       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;
+       }
+
+       if(disp_state & 0x7)
+       {
+               if(crt1off)
+                       disp_state |= DISPMODE_SINGLE;
+               else
+                       disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+       }
+       else
+               disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
+
+       ivideo.disp_state = disp_state;
+}
+
+
+int __init sisfb_init(void)
+{
+       struct pci_dev *pdev = NULL;
+       struct board *b;
+       int pdev_valid = 0;
+       unsigned char jTemp;
+       u8 uSRData, uCRData;
+
+       outb(0x77, 0x80);
+
+       if (sisfb_off)
+               return -ENXIO;
+
+       pci_for_each_dev(pdev) {
+               for (b = dev_list; b->vendor; b++) 
+               {
+                       if ((b->vendor == pdev->vendor)
+                           && (b->device == pdev->device)) 
+                       {
+                               pdev_valid = 1;
+                               strcpy(fb_info.modename, b->name);
+                               ivideo.chip_id = pdev->device;
+                               pci_read_config_byte(pdev, PCI_REVISION_ID, &HwExt.revision_id);
+                               break;
+                       }
+               }
+
+               if (pdev_valid)
+                       break;
+       }
+
+       if (!pdev_valid)
+               return -1;
+
+       switch(ivideo.chip_id)
+       {
+       case PCI_DEVICE_ID_SI_300:
+               HwExt.jChipID = SIS_Glamour;
+               break;
+       case PCI_DEVICE_ID_SI_630_VGA:
+               HwExt.jChipID = SIS_Trojan;
+               break;
+       case PCI_DEVICE_ID_SI_540_VGA:
+               HwExt.jChipID = SIS_Spartan;
+               break;
+       case PCI_DEVICE_ID_SI_730_VGA:
+               HwExt.jChipID = SIS_730;
+               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;
+
+       MMIO_SIZE =  pci_resource_len(pdev, 1);
+
+#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;
+
+               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;
+               }
+       }
+
+       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
+
+
+       /* 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;
+               }
+       } 
+       else
+       {
+               if((uCRData & 0x20) && !crt1off)
+                       crt1off = 0;
+               else
+               {
+                       if(uCRData&0x5F)   /* DISP2 connected */
+                               crt1off = 1;
+                       else
+                               crt1off = 0;
+               }
+
+               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;
+
+                       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(uDispType == MASK_DISPTYPE_LCD)   // LCD conntected
+       {
+               // TODO: set LCDType by EDID
+               HwExt.usLCDType = LCD1024;
+       }
+
+       if (HwExt.jChipID >= SIS_Trojan)
+       {
+               vgawb(SEQ_ADR, 0x1A);
+               uSRData = vgarb(SEQ_DATA);
+               if (uSRData & 0x10)
+                       HwExt.bIntegratedMMEnabled = TRUE;
+               else
+                       HwExt.bIntegratedMMEnabled = FALSE;
+       }
+
+       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;
+                       }
+
+                       if(sisbios_mode[mode_idx].xres == 720)  /* only for TV */
+                               mode_idx = -1;
+                       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;
+                       }
+                       break;
+               }
+       }       
+       
+       if (mode_idx < 0)
+       {
+               switch(uDispType & MASK_DISPTYPE_DISP2)
+               {
+               case MASK_DISPTYPE_LCD:
+                       mode_idx = DEFAULT_LCDMODE;
+                       break;
+               case MASK_DISPTYPE_TV:
+                       mode_idx = DEFAULT_TVMODE;
+                       break;
+               default:
+                       mode_idx = DEFAULT_MODE;
+               }
+       }
+
+#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;
+
+       if (ivideo.refresh_rate != 0)
+               search_refresh_rate(ivideo.refresh_rate);
+
+       if (rate_idx == 0) {
+               rate_idx = sisbios_mode[mode_idx].rate_idx;     
+               /* set to default refresh rate 60MHz */
+               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.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);
+
+       pre_setmode();
+
+       if (SiSSetMode(&HwExt, mode_no)) {
+               DPRINTK("sisfb: set mode[0x%x]: failed\n", mode_no);
+               return -1;
+       }
+
+       post_setmode();
+
+       /* Get VB functions */
+       sis_get301info();
+
+       crtc_to_var(&default_var);
+
+       fb_info.changevar = NULL;
+       fb_info.node = -1;
+       fb_info.fbops = &sisfb_ops;
+       fb_info.disp = &disp;
+       fb_info.switch_con = &sisfb_switch;
+       fb_info.updatevar = &sisfb_update_var;
+       fb_info.blank = &sisfb_blank;
+       fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+       sisfb_set_disp(-1, &default_var);
+
+       if (sisfb_heap_init()) {
+               DPRINTK("sisfb: Failed to enable offscreen heap\n");
+       }
+
+       /* to avoid the inversed bgcolor bug of the initial state */
+       vc_resize_con(1, 1, 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);
+
+       return 0;
+}
+
+#ifdef MODULE
+
+static char *mode = NULL;
+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 */
+
+int init_module(void)
+{
+       if (mode)
+               search_mode(mode);
+
+       ivideo.refresh_rate = rate;
+
+       if(crt1 == 0)
+               crt1off = 1;
+       else
+               crt1off = 0;
+       
+       sisfb_init();
+
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       unregister_framebuffer(&fb_info);
+}
+#endif                         /* MODULE */
+
+
+EXPORT_SYMBOL(sis_malloc);
+EXPORT_SYMBOL(sis_free);
+
+EXPORT_SYMBOL(ivideo);
diff --git a/drivers/video/sisfb.c b/drivers/video/sisfb.c
deleted file mode 100644 (file)
index c2d460b..0000000
+++ /dev/null
@@ -1,3619 +0,0 @@
-/*
- * SiS 300/630/540 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 
- * 
- * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#define EXPORT_SYMTAB
-#undef  SISFBDEBUG
-#undef CONFIG_FB_SIS_LINUXBIOS
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vt_kern.h>
-#include <linux/capability.h>
-#include <linux/sisfb.h>
-
-#include <asm/io.h>
-#include <asm/mtrr.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb24.h>
-#include <video/fbcon-cfb32.h>
-
-/* ------------------- Constant Definitions ------------------------- */
-
-#define FALSE   0
-#define TRUE    1
-
-/* Draw Function 
-#define FBIOGET_GLYPH        0x4620
-#define FBIOGET_HWCINFO      0x4621
-*/
-#define BR(x)   (0x8200 | (x) << 2)
-
-#define BITBLT               0x00000000
-#define COLOREXP             0x00000001
-#define ENCOLOREXP           0x00000002
-#define MULTIPLE_SCANLINE    0x00000003
-#define LINE                 0x00000004
-#define TRAPAZOID_FILL       0x00000005
-#define TRANSPARENT_BITBLT   0x00000006
-
-#define SRCVIDEO             0x00000000
-#define SRCSYSTEM            0x00000010
-#define SRCAGP               0x00000020
-
-#define PATFG                0x00000000
-#define PATPATREG            0x00000040
-#define PATMONO              0x00000080
-
-#define X_INC                0x00010000
-#define X_DEC                0x00000000
-#define Y_INC                0x00020000
-#define Y_DEC                0x00000000
-
-#define NOCLIP               0x00000000
-#define NOMERGECLIP          0x04000000
-#define CLIPENABLE           0x00040000
-#define CLIPWITHOUTMERGE     0x04040000
-
-#define OPAQUE               0x00000000
-#define TRANSPARENT          0x00100000
-
-#define DSTAGP               0x02000000
-#define DSTVIDEO             0x02000000
-
-#define LINE_STYLE           0x00800000
-#define NO_RESET_COUNTER     0x00400000
-#define NO_LAST_PIXEL        0x00200000
-
-/* capabilities */
-#define TURBO_QUEUE_CAP      0x80
-#define HW_CURSOR_CAP        0x40
-
-/* 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)
-
-/* 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)
-
-#define SIS_MEM_MAP_IO_ENABLE     (0x01)
-#define SIS_PCI_ADDR_ENABLE       (0x80)
-
-#define MMIO_SIZE                 0x20000      /* 128K MMIO capability */
-#define MAX_ROM_SCAN              0x10000
-
-#define RESERVED_MEM_SIZE_4M      0x400000     /* 4M */
-#define RESERVED_MEM_SIZE_8M      0x800000     /* 8M */
-
-/* Mode set stuff */
-#define DEFAULT_MODE      0
-
-#define ModeInfoFlag      0x07
-#define MemoryInfoFlag    0x1E0
-#define MemorySizeShift   0x05
-#define ModeVGA           0x03
-#define ModeEGA           0x02
-#define CRT1Len           17
-#define DoubleScanMode    0x8000
-#define HalfDCLK          0x1000
-
-#define InterlaceMode     0x80
-#define LineCompareOff    0x400
-#define DACInfoFlag       0x18
-
-#define VCLKStartFreq      25
-
-#define SIS_Glamour       0x0300
-#define SIS_Trojan        0x6300
-#define SIS_Spartan       0x5300
-
-/* heap stuff */
-#define OH_ALLOC_SIZE         4000
-#define SENTINEL              0x7fffffff
-
-#define TURBO_QUEUE_AREA_SIZE 0x80000  /* 512K */
-#define HW_CURSOR_AREA_SIZE   0x1000   /* 4K */
-
-/* video connection status */
-#define VB_COMPOSITE 0x01
-#define VB_SVIDEO    0x02
-#define VB_SCART     0x04
-#define VB_LCD       0x08
-#define VB_CRT2      0x10
-#define CRT1         0x20
-#define VB_HDTV      0x40
-
-/* ------------------- Global Variables ----------------------------- */
-
-struct video_info ivideo;
-
-struct GlyInfo {
-       unsigned char ch;
-       int fontwidth;
-       int fontheight;
-       u8 gmask[72];
-       int ngmask;
-};
-
-/* 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"},
-       {0, 0, NULL}
-};
-
-/* 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 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}
-};
-
-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;
-
-static int inverse = 0;
-static int currcon = 0;
-
-static struct display_switch sisfb_sw;
-
-u8 caps = 0;
-
-/* ModeSet stuff */
-
-u16 P3c4, P3d4, P3c0, P3ce, P3c2, P3ca, P3c6, P3c7, P3c8, P3c9, P3da;
-u16 CRT1VCLKLen;
-u16 flag_clearbuffer;
-u16 CRT1VCLKLen;
-int ModeIDOffset, StandTable, CRT1Table, ScreenOffset;
-int REFIndex, ModeType;
-int VCLKData;
-int RAMType;
-
-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},
-       {"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}
-};
-
-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,  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}
-};
-
-u16 DRAMType[17][5] = {
-       {0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
-       {0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44},
-       {0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40},
-       {0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32},
-       {0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30},
-       {0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28},
-       {0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24},
-       {0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10},
-       {0x09, 0x08, 0x01, 0x01, 0x00}
-};
-
-u16 MDA_DAC[] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
-       0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
-       0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
-       0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
-       0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
-};
-
-u16 CGA_DAC[] = {
-       0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
-       0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
-       0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
-       0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
-       0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
-       0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
-       0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
-       0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
-};
-
-u16 EGA_DAC[] = {
-       0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
-       0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
-       0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
-       0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
-       0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17,
-       0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37,
-       0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
-       0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
-};
-
-u16 VGA_DAC[] = {
-       0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
-       0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
-       0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
-       0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
-       0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
-       0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
-       0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
-       0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
-       0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
-       0x0B, 0x0C, 0x0D, 0x0F, 0x10
-};
-
-#define Monitor1Sense 0x20
-
-unsigned char SRegsInit[] = { 
-       0x03, 0x00, 0x03, 0x00, 0x02, 0xa1, 0x00, 0x13,
-       0x2f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-       0x00, 0x0f, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00,
-       0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 
-       0xa1, 0x76, 0xb2, 0xf6, 0x0d, 0x00, 0x00, 0x00,
-       0x37, 0x61, 0x80, 0x1b, 0xe1, 0x01, 0x55, 0x43, 
-       0x80, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff,
-       0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff
-};
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-
-unsigned char SRegs[] = { 
-       0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13,
-       0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-       0x0B, 0x0F, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00,
-       0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x40, 0x00,
-       0xA1, 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0xF8, 0xF0,
-       0x37, 0x61, 0x80, 0x1B, 0xE1, 0x80, 0x55, 0x43,
-       0x80, 0x00, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF,
-       0x8E, 0x40, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF
-};
-
-unsigned char CRegs[] = { 
-       0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
-       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
-       0xe9, 0x0b, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3,
-       0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff
-};     // clear CR11[7]
-
-unsigned char GRegs[] = { 
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, 0x00
-};
-
-unsigned char ARegs[] = { 
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-unsigned char MReg = 0x6f;
-
-#endif
-
-
-/* HEAP stuff */
-
-struct OH {
-       struct OH *pohNext;
-       struct OH *pohPrev;
-       unsigned long ulOffset;
-       unsigned long ulSize;
-};
-
-struct OHALLOC {
-       struct OHALLOC *pohaNext;
-       struct OH aoh[1];
-};
-
-struct HEAP {
-       struct OH ohFree;
-       struct OH ohUsed;
-       struct OH *pohFreeList;
-       struct OHALLOC *pohaChain;
-
-       unsigned long ulMaxFreeSize;
-};
-
-struct HEAP heap;
-unsigned long heap_start;
-unsigned long heap_end;
-unsigned long heap_size;
-
-unsigned int tqueue_pos;
-unsigned long hwcursor_vbase;
-
-/* Draw Function stuff */
-u32 command_reg;
-
-/* -------------------- Macro definitions --------------------------- */
-
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#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))
-
-/* ---------------------- Routine Prototype ------------------------- */
-
-/* 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);
-
-/* 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);
-
-/* 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);
-
-/* set-mode routines */
-static void set_reg1(u16 port, u16 index, u16 data);
-static void set_reg3(u16 port, u16 data);
-static void set_reg4(u16 port, unsigned long data);
-static u8 get_reg1(u16 port, u16 index);
-static u8 get_reg2(u16 port);
-//#ifndef CONFIG_FB_SIS_LINUXBIOS
-static u32 get_reg3(u16 port);
-static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo);
-static int search_modeID(unsigned long ROMAddr, u16 ModeNo);
-static int check_memory_size(unsigned long ROMAddr);
-static void get_mode_ptr(unsigned long ROMAddr, u16 ModeNo);
-static void set_seq_regs(unsigned long ROMAddr);
-static void set_misc_regs(unsigned long ROMAddr);
-static void set_crtc_regs(unsigned long ROMAddr);
-static void set_attregs(unsigned long ROMAddr);
-static void set_grc_regs(unsigned long ROMAddr);
-static void ClearExt1Regs(void);
-static u16 GetRefindexLength(unsigned long ROMAddr, u16 ModeNo);
-static int get_rate_ptr(unsigned long ROMAddr, u16 ModeNo);
-static void set_sync(unsigned long ROMAddr);
-static void set_crt1_crtc(unsigned long ROMAddr);
-static void set_crt1_offset(unsigned long ROMAddr);
-static u16 get_vclk_len(unsigned long ROMAddr);
-static void set_crt1_vclk(unsigned long ROMAddr);
-static void set_vclk_state(unsigned long ROMAddr, u16 ModeNo);
-static u16 calc_delay2(unsigned long ROMAddr, u16 key);
-static u16 calc_delay(unsigned long ROMAddr, u16 key);
-static void set_crt1_FIFO(unsigned long ROMAddr);
-static void set_crt1_FIFO2(unsigned long ROMAddr);
-static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo);
-static void set_interlace(unsigned long ROMAddr, u16 ModeNo);
-//#endif
-static void write_DAC(u16 dl, u16 ah, u16 al, u16 dh);
-static void load_DAC(unsigned long ROMAddr);
-static void display_on(void);
-
-static int SiSSetMode(u16 ModeNo);
-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);
-
-/* 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);
-
-/* ---------------------- Internal Routines ------------------------- */
-
-inline static u32 RD32(unsigned char *base, s32 off)
-{
-       return readl(base + off);
-}
-
-inline static void WR32(unsigned char *base, s32 off, u32 v)
-{
-       writel(v, base + off);
-}
-
-inline static void WR16(unsigned char *base, s32 off, u16 v)
-{
-       writew(v, base + off);
-}
-
-inline static void WR8(unsigned char *base, s32 off, u8 v)
-{
-       writeb(v, base + off);
-}
-
-inline static u32 regrl(s32 off)
-{
-       return RD32(ivideo.mmio_vbase, off);
-}
-
-inline static void regwl(s32 off, u32 v)
-{
-       WR32(ivideo.mmio_vbase, off, v);
-}
-
-inline static void regww(s32 off, u16 v)
-{
-       WR16(ivideo.mmio_vbase, off, v);
-}
-
-inline static void regwb(s32 off, u8 v)
-{
-       WR8(ivideo.mmio_vbase, off, v);
-}
-
-/* 
- *    Get CRTC registers to set var 
- */
-static void crtc_to_var(struct fb_var_screeninfo *var)
-{
-       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;
-
-       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;
-       }
-
-       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:                /* 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;
-
-               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;
-               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(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;
-
-       vgawb(CRTC_ADR, 0x4);
-       uCRdata = vgarb(CRTC_DATA);
-       HRS = (uCRdata & 0xff) | ((u16) (uSRdata & 0xC0) << 2);
-       F = HRS - E - 3;
-
-       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);
-
-       temp = HBE - ((E - 1) & 255);
-       B = (temp > 0) ? temp : (temp + 256);
-
-       temp = HRE - ((E + F + 3) & 63);
-       C = (temp > 0) ? temp : (temp + 64);
-
-       D = B - F - C;
-
-       var->xres = var->xres_virtual = E * 8;
-       var->left_margin = D * 8;
-       var->right_margin = F * 8;
-       var->hsync_len = C * 8;
-
-       var->activate = FB_ACTIVATE_NOW;
-
-       var->sync = 0;
-
-       uMRdata = vgarb(0x1C);
-       if (uMRdata & 0x80)
-               var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
-       else
-               var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-       if (uMRdata & 0x40)
-               var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
-       else
-               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);
-}
-
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var)
-{
-       struct fb_fix_screeninfo fix;
-       struct display *display;
-       struct display_switch *sw;
-       u32 flags;
-
-       if (con >= 0)
-               display = &fb_display[con];
-       else
-               display = &disp;        /* used during initialization */
-
-       sisfb_get_fix(&fix, con, 0);
-
-       display->screen_base = ivideo.video_vbase;
-       display->visual = fix.visual;
-       display->type = fix.type;
-       display->type_aux = fix.type_aux;
-       display->ypanstep = fix.ypanstep;
-       display->ywrapstep = fix.ywrapstep;
-       display->line_length = fix.line_length;
-       display->next_line = fix.line_length;
-       /*display->can_soft_blank = 1; */
-       display->can_soft_blank = 0;
-       display->inverse = inverse;
-       display->var = *var;
-
-       save_flags(flags);
-       switch (ivideo.video_bpp) {
-#ifdef FBCON_HAS_CFB8
-       case 8:
-               sw = &fbcon_cfb8;
-               break;
-#endif
-
-#ifdef FBCON_HAS_CFB16
-       case 15:
-       case 16:
-               sw = &fbcon_cfb16;
-               display->dispsw_data = fbcon_cmap.cfb16;
-               break;
-#endif
-
-#ifdef FBCON_HAS_CFB24
-       case 24:
-               sw = &fbcon_cfb24;
-               display->dispsw_data = fbcon_cmap.cfb24;
-               break;
-#endif
-
-#ifdef FBCON_HAS_CFB32
-       case 32:
-               sw = &fbcon_cfb32;
-               display->dispsw_data = fbcon_cmap.cfb32;
-               break;
-#endif
-
-       default:
-               sw = &fbcon_dummy;
-               return;
-       }
-       memcpy(&sisfb_sw, sw, sizeof(*sw));
-       display->dispsw = &sisfb_sw;
-       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)
-{
-       if (regno >= video_cmap_len)
-               return 1;
-
-       *red = palette[regno].red;
-       *green = palette[regno].green;
-       *blue = palette[regno].blue;
-       *transp = 0;
-       return 0;
-}
-
-/*
- *    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;
-
-       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);
-               break;
-#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:
-               red >>= 8;
-               green >>= 8;
-               blue >>= 8;
-               fbcon_cmap.cfb32[regno] =
-                   (red << 16) | (green << 8) | (blue);
-               break;
-#endif
-       }
-       return 0;
-}
-
-static void do_install_cmap(int con, struct fb_info *info)
-{
-       if (con != currcon)
-               return;
-
-       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);
-}
-
-static int 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;
-
-       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;
-
-
-       if (!htotal || !vtotal) {
-               DPRINTK("Invalid 'var' Information!\n");
-               return 1;
-       }
-
-       drate = 1E12 / var->pixclock;
-       hrate = drate / htotal;
-       ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
-
-       mode_idx = 0;
-       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 (!found_mode) {
-               printk("sisfb does not support mode %dx%d-%d\n", var->xres,
-                      var->yres, var->bits_per_pixel);
-               return 1;
-       }
-
-       if (search_refresh_rate(ivideo.refresh_rate) == 0) {
-               /* not supported rate */
-               rate_idx = sisbios_mode[mode_idx].rate_idx;
-               ivideo.refresh_rate = 60;
-       }
-
-       if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
-               pre_setmode();
-
-               if (SiSSetMode(mode_no)) {
-                       DPRINTK("sisfb: set mode[0x%x]: failed\n",
-                               mode_no);
-                       return 1;
-               }
-
-               post_setmode();
-
-               ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
-               ivideo.video_width = sisbios_mode[mode_idx].xres;
-               ivideo.video_height = sisbios_mode[mode_idx].yres;
-               video_linelength =
-                   ivideo.video_width * (ivideo.video_bpp >> 3);
-
-               DPRINTK("Current Mode: %dx%d-%d line_length=%d\n",
-                       ivideo.video_width, ivideo.video_height,
-                       ivideo.video_bpp, video_linelength);
-       }
-
-       return 0;
-}
-
-/* ---------------------- Draw Funtions ----------------------------- */
-
-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;
-
-
-       gly->fontheight = fontheight(p);
-       gly->fontwidth = fontwidth(p);
-       widthb = (fontwidth(p) + 7) / 8;
-
-       c = gly->ch & p->charmask;
-       if (fontwidth(p) <= 8)
-               cdat = p->fontdata + c * fontheight(p);
-       else
-               cdat = p->fontdata + (c * fontheight(p) << 1);
-
-       size = fontheight(p) * widthb;
-       memcpy(gbuf, cdat, size);
-       gly->ngmask = size;
-}
-
-
-/* ---------------------- HEAP Routines ----------------------------- */
-
-/* 
- *  Heap Initialization
- */
-
-static int sisfb_heap_init(void)
-{
-       struct OH *poh;
-       u8 jTemp, tq_state;
-
-       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;
-
-       heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
-       heap_size = heap_end - heap_start;
-
-
-       /* 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);
-               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;
-       }
-
-       /* 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;
-
-               caps |= HW_CURSOR_CAP;
-       }
-
-       heap.pohaChain = NULL;
-       heap.pohFreeList = NULL;
-
-       poh = 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;
-
-       return 0;
-}
-
-/*
- *  Allocates a basic memory unit in which we'll pack our data structures.
- */
-
-static struct OH *poh_new_node(void)
-{
-       int i;
-       unsigned long cOhs;
-       struct OHALLOC *poha;
-       struct OH *poh;
-
-       if (heap.pohFreeList == NULL) {
-               poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
-
-               poha->pohaNext = heap.pohaChain;
-               heap.pohaChain = poha;
-
-               cOhs =
-                   (OH_ALLOC_SIZE -
-                    sizeof(struct OHALLOC)) / sizeof(struct OH) + 1;
-
-               poh = &poha->aoh[0];
-               for (i = cOhs - 1; i != 0; i--) {
-                       poh->pohNext = poh + 1;
-                       poh = poh + 1;
-               }
-
-               poh->pohNext = NULL;
-               heap.pohFreeList = &poha->aoh[0];
-       }
-
-       poh = heap.pohFreeList;
-       heap.pohFreeList = poh->pohNext;
-
-       return (poh);
-}
-
-/* 
- *  Allocates space, return NULL when failed
- */
-
-static struct OH *poh_allocate(unsigned long size)
-{
-       struct OH *pohThis;
-       struct OH *pohRoot;
-       int bAllocated = 0;
-
-       if (size > heap.ulMaxFreeSize) {
-               DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
-                       (unsigned int) size / 1024);
-               return (NULL);
-       }
-
-       pohThis = heap.ohFree.pohNext;
-
-       while (pohThis != &heap.ohFree) {
-               if (size <= pohThis->ulSize) {
-                       bAllocated = 1;
-                       break;
-               }
-               pohThis = pohThis->pohNext;
-       }
-
-       if (!bAllocated) {
-               DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
-                       (unsigned int) size / 1024);
-               return (NULL);
-       }
-
-       if (size == pohThis->ulSize) {
-               pohRoot = pohThis;
-               delete_node(pohThis);
-       } else {
-               pohRoot = poh_new_node();
-
-               if (pohRoot == NULL) {
-                       return (NULL);
-               }
-
-               pohRoot->ulOffset = pohThis->ulOffset;
-               pohRoot->ulSize = size;
-
-               pohThis->ulOffset += size;
-               pohThis->ulSize -= size;
-       }
-
-       heap.ulMaxFreeSize -= size;
-
-       pohThis = &heap.ohUsed;
-       insert_node(pohThis, pohRoot);
-
-       return (pohRoot);
-}
-
-/* 
- *  To remove a node from a list.
- */
-
-static void delete_node(struct OH *poh)
-{
-       struct OH *pohPrev;
-       struct OH *pohNext;
-
-
-       pohPrev = poh->pohPrev;
-       pohNext = poh->pohNext;
-
-       pohPrev->pohNext = pohNext;
-       pohNext->pohPrev = pohPrev;
-
-       return;
-}
-
-/* 
- *  To insert a node into a list.
- */
-
-static void insert_node(struct OH *pohList, struct OH *poh)
-{
-       struct OH *pohTemp;
-
-       pohTemp = pohList->pohNext;
-
-       pohList->pohNext = poh;
-       pohTemp->pohPrev = poh;
-
-       poh->pohPrev = pohList;
-       poh->pohNext = pohTemp;
-}
-
-/*
- *  Frees an off-screen heap allocation.
- */
-
-static struct OH *poh_free(unsigned long base)
-{
-
-       struct OH *pohThis;
-       struct OH *pohFreed;
-       struct OH *pohPrev;
-       struct OH *pohNext;
-       unsigned long ulUpper;
-       unsigned long ulLower;
-       int foundNode = 0;
-
-       pohFreed = heap.ohUsed.pohNext;
-
-       while (pohFreed != &heap.ohUsed) {
-               if (pohFreed->ulOffset == base) {
-                       foundNode = 1;
-                       break;
-               }
-
-               pohFreed = pohFreed->pohNext;
-       }
-
-       if (!foundNode)
-               return (NULL);
-
-       heap.ulMaxFreeSize += pohFreed->ulSize;
-
-       pohPrev = pohNext = NULL;
-       ulUpper = pohFreed->ulOffset + pohFreed->ulSize;
-       ulLower = pohFreed->ulOffset;
-
-       pohThis = heap.ohFree.pohNext;
-
-       while (pohThis != &heap.ohFree) {
-               if (pohThis->ulOffset == ulUpper) {
-                       pohNext = pohThis;
-               }
-                       else if ((pohThis->ulOffset + pohThis->ulSize) ==
-                                ulLower) {
-                       pohPrev = pohThis;
-               }
-               pohThis = pohThis->pohNext;
-       }
-
-       delete_node(pohFreed);
-
-       if (pohPrev && pohNext) {
-               pohPrev->ulSize += (pohFreed->ulSize + pohNext->ulSize);
-               delete_node(pohNext);
-               free_node(pohFreed);
-               free_node(pohNext);
-               return (pohPrev);
-       }
-
-       if (pohPrev) {
-               pohPrev->ulSize += pohFreed->ulSize;
-               free_node(pohFreed);
-               return (pohPrev);
-       }
-
-       if (pohNext) {
-               pohNext->ulSize += pohFreed->ulSize;
-               pohNext->ulOffset = pohFreed->ulOffset;
-               free_node(pohFreed);
-               return (pohNext);
-       }
-
-       insert_node(&heap.ohFree, pohFreed);
-
-       return (pohFreed);
-}
-
-/*
- *  Frees our basic data structure allocation unit by adding it to a free
- *  list.
- */
-
-static void free_node(struct OH *poh)
-{
-       if (poh == NULL) {
-               return;
-       }
-
-       poh->pohNext = heap.pohFreeList;
-       heap.pohFreeList = poh;
-
-       return;
-}
-
-void sis_malloc(struct sis_memreq *req)
-{
-       struct OH *poh;
-
-       poh = poh_allocate(req->size);
-
-       if (poh == NULL) {
-               req->offset = 0;
-               req->size = 0;
-               DPRINTK("sisfb: VMEM Allocation Failed\n");
-       } else {
-               DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n",
-                       (char *) (poh->ulOffset +
-                                 (unsigned long) ivideo.video_vbase));
-
-               req->offset = poh->ulOffset;
-               req->size = poh->ulSize;
-       }
-
-}
-
-void sis_free(unsigned long base)
-{
-       struct OH *poh;
-
-       poh = poh_free(base);
-
-       if (poh == NULL) {
-               DPRINTK("sisfb: poh_free() failed at base 0x%x\n",
-                       (unsigned int) base);
-       }
-
-}
-
-
-
-/* ---------------------- SetMode Routines -------------------------- */
-
-static void set_reg1(u16 port, u16 index, u16 data)
-{
-       outb((u8) (index & 0xff), port);
-       port++;
-       outb((u8) (data & 0xff), port);
-}
-
-static void set_reg3(u16 port, u16 data)
-{
-       outb((u8) (data & 0xff), port);
-}
-
-static void set_reg4(u16 port, unsigned long data)
-{
-       outl((u32) (data & 0xffffffff), port);
-}
-
-static u8 get_reg1(u16 port, u16 index)
-{
-       u8 data;
-
-       outb((u8) (index & 0xff), port);
-       port += 1;
-       data = inb(port);
-       return (data);
-}
-
-static u8 get_reg2(u16 port)
-{
-       u8 data;
-
-       data = inb(port);
-
-       return (data);
-}
-
-static u32 get_reg3(u16 port)
-{
-       u32 data;
-
-       data = inl(port);
-       return (data);
-}
-
-static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo)
-{
-       u16 modeidlength;
-       u16 usModeIDOffset;
-       unsigned short PreviousWord,CurrentWord;
-
-       return(10);
-   
-       modeidlength=0;
-       usModeIDOffset=*((unsigned short *)(ROMAddr+0x20A));      // Get EModeIDTable
-
-       CurrentWord=*((unsigned short *)(ROMAddr+usModeIDOffset));     // Offset 0x20A
-       PreviousWord=*((unsigned short *)(ROMAddr+usModeIDOffset-2));     // Offset 0x20A
-       while((CurrentWord!=0x2E07)||(PreviousWord!=0x0801)) 
-       {
-       modeidlength++;
-       usModeIDOffset=usModeIDOffset+1;               // 10 <= ExtStructSize
-       CurrentWord=*((unsigned short *)(ROMAddr+usModeIDOffset));
-       PreviousWord=*((unsigned short *)(ROMAddr+usModeIDOffset-2)); 
-       }
-       modeidlength++;
-
-       return(modeidlength);
-}
-
-static int search_modeID(unsigned long ROMAddr, u16 ModeNo)
-{
-       unsigned char ModeID;
-       u16 usIDLength;
-       unsigned int count = 0;
-
-       ModeIDOffset = *((u16 *) (ROMAddr + 0x20A));
-       ModeID = *((unsigned char *) (ROMAddr + ModeIDOffset));
-       usIDLength = get_modeID_length(ROMAddr, ModeNo);
-       while (ModeID != 0xff && ModeID != ModeNo) {
-               ModeIDOffset = ModeIDOffset + usIDLength;
-               ModeID = *((unsigned char *) (ROMAddr + ModeIDOffset));
-               if (count++ >= 0xff)
-                       break;
-       }
-       if (ModeID == 0xff)
-               return (FALSE);
-       else
-               return (TRUE);
-}
-
-static int check_memory_size(unsigned long ROMAddr)
-{
-       u16 memorysize;
-       u16 modeflag;
-       u16 temp;
-
-       modeflag = *((u16 *) (ROMAddr + ModeIDOffset + 0x01));
-       ModeType = modeflag & ModeInfoFlag;
-
-       memorysize = modeflag & MemoryInfoFlag;
-       memorysize = memorysize >> MemorySizeShift;
-       memorysize++;
-
-       temp = get_reg1(P3c4, 0x14);
-       temp = temp & 0x3F;
-       temp++;
-
-       if (temp < memorysize)
-               return (FALSE);
-       else
-               return (TRUE);
-}
-
-static void get_mode_ptr(unsigned long ROMAddr, u16 ModeNo)
-{
-       unsigned char index;
-
-       StandTable = *((u16 *) (ROMAddr + 0x202));
-
-       if (ModeNo <= 13)
-               index = *((unsigned char *) (ROMAddr + ModeIDOffset + 0x03));
-       else {
-               if (ModeType <= 0x02)
-                       index = 0x1B;
-               else
-                       index = 0x0F;
-       }
-
-       StandTable = StandTable + 64 * index;
-
-}
-
-static void set_seq_regs(unsigned long ROMAddr)
-{
-       unsigned char SRdata;
-       u16 i;
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       SRdata = SRegs[0x01];
-#else
-       set_reg1(P3c4, 0x00, 0x03);
-       StandTable = StandTable + 0x05;
-       SRdata = *((unsigned char *) (ROMAddr + StandTable));
-#endif
-
-       SRdata = SRdata | 0x20;
-       set_reg1(P3c4, 0x01, SRdata);
-
-
-       for (i = 02; i <= 04; i++) {
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-               SRdata = SRegs[i];
-#else
-               StandTable++;
-               SRdata = *((unsigned char *) (ROMAddr + StandTable));
-#endif
-               set_reg1(P3c4, i, SRdata);
-       }
-}
-
-static void set_misc_regs(unsigned long ROMAddr)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg3(P3c2, 0x23);
-#else
-       unsigned char Miscdata;
-
-       StandTable++;
-       Miscdata = *((unsigned char *) (ROMAddr + StandTable));
-       set_reg3(P3c2, Miscdata);
-#endif
-}
-
-static void set_crtc_regs(unsigned long ROMAddr)
-{
-       unsigned char CRTCdata;
-       u16 i;
-
-       CRTCdata = (unsigned char) get_reg1(P3d4, 0x11);
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       CRTCdata = CRTCdata & 0x7f;
-#endif
-       set_reg1(P3d4, 0x11, CRTCdata);
-
-       for (i = 0; i <= 0x18; i++) {
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-               set_reg1(P3d4, i, CRegs[i]);
-#else
-               StandTable++;
-               CRTCdata = *((unsigned char *) (ROMAddr + StandTable));
-               set_reg1(P3d4, i, CRTCdata);
-#endif
-       }
-}
-
-static void set_attregs(unsigned long ROMAddr)
-{
-       unsigned char ARdata;
-       u16 i;
-
-       for (i = 0; i <= 0x13; i++) {
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-               get_reg2(P3da);
-               set_reg3(P3c0, i);
-               set_reg3(P3c0, ARegs[i]);
-#else
-               StandTable++;
-               ARdata = *((unsigned char *) (ROMAddr + StandTable));
-
-               get_reg2(P3da);
-               set_reg3(P3c0, i);
-               set_reg3(P3c0, ARdata);
-#endif
-       }
-
-       get_reg2(P3da);
-       set_reg3(P3c0, 0x14);
-       set_reg3(P3c0, 0x00);
-       get_reg2(P3da);
-       set_reg3(P3c0, 0x20);
-}
-
-static void set_grc_regs(unsigned long ROMAddr)
-{
-       unsigned char GRdata;
-       u16 i;
-
-       for (i = 0; i <= 0x08; i++) {
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-               set_reg1(P3ce, i, GRegs[i]);
-#else
-               StandTable++;
-               GRdata = *((unsigned char *) (ROMAddr + StandTable));
-               set_reg1(P3ce, i, GRdata);
-#endif
-       }
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       if (ModeType > ModeVGA) {
-               GRdata = (unsigned char) get_reg1(P3ce, 0x05);
-               GRdata = GRdata & 0xBF;
-               set_reg1(P3ce, 0x05, GRdata);
-       }
-#endif
-}
-
-static void ClearExt1Regs(void)
-{
-       u16 i;
-
-       for (i = 0x0A; i <= 0x0E; i++)
-               set_reg1(P3c4, i, 0x00);
-}
-
-static u16 GetRefindexLength(unsigned long ROMAddr, u16 ModeNo)
-{
-       unsigned char ModeID;
-       unsigned char temp;
-       u16 refindexlength;
-       u16 usModeIDOffset;
-       u16 usREFIndex;
-       u16 usIDLength;
-
-       usModeIDOffset = *((u16 *) (ROMAddr + 0x20A));
-       ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset));
-       usIDLength = get_modeID_length(ROMAddr, ModeNo);
-       while (ModeID != 0x40) {
-               usModeIDOffset = usModeIDOffset + usIDLength;
-               ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset));
-       }
-
-       refindexlength = 1;
-       usREFIndex = *((u16 *) (ROMAddr + usModeIDOffset + 0x04));
-       usREFIndex++;
-       temp = *((unsigned char *) (ROMAddr + usREFIndex));
-       while (temp != 0xFF) {
-               refindexlength++;
-               usREFIndex++;
-               temp = *((unsigned char *) (ROMAddr + usREFIndex));
-       }
-       return (refindexlength);
-}
-
-static int get_rate_ptr(unsigned long ROMAddr, u16 ModeNo)
-{
-       short index;
-       u16 temp;
-       u16 ulRefIndexLength;
-
-       if (ModeNo < 0x14)
-               return (FALSE);
-
-       index = get_reg1(P3d4, 0x33);
-       index = index & 0x0F;
-       if (index != 0)
-               index--;
-
-       REFIndex = *((u16 *) (ROMAddr + ModeIDOffset + 0x04));
-
-       ulRefIndexLength = GetRefindexLength(ROMAddr, ModeNo);
-
-       do {
-               temp = *((u16 *) (ROMAddr + REFIndex));
-               if (temp == 0xFFFF)
-                       break;
-               temp = temp & ModeInfoFlag;
-               if (temp < ModeType)
-                       break;
-
-               REFIndex = REFIndex + ulRefIndexLength;
-               index--;
-       } while (index >= 0);
-
-       REFIndex = REFIndex - ulRefIndexLength;
-       return (TRUE);
-}
-
-static void set_sync(unsigned long ROMAddr)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg3(P3c2, MReg);
-#else
-       u16 sync;
-       u16 temp;
-
-       sync = *((u16 *) (ROMAddr + REFIndex));
-       sync = sync & 0xC0;
-       temp = 0x2F;
-       temp = temp | sync;
-       set_reg3(P3c2, temp);
-#endif
-}
-
-static void set_crt1_crtc(unsigned long ROMAddr)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       unsigned char data;
-       u16 i;
-
-       data = (unsigned char) get_reg1(P3d4, 0x11);
-       data = data & 0x7F;
-       set_reg1(P3d4, 0x11, data);
-
-       for (i = 0; i <= 0x07; i++)
-               set_reg1(P3d4, i, CRegs[i]);
-       for (i = 0x10; i <= 0x12; i++)
-               set_reg1(P3d4, i, CRegs[i]);
-       for (i = 0x15; i <= 0x16; i++)
-               set_reg1(P3d4, i, CRegs[i]);
-       for (i = 0x0A; i <= 0x0C; i++)
-               set_reg1(P3c4, i, SRegs[i]);
-
-       data = SRegs[0x0E] & 0xE0;
-       set_reg1(P3c4, 0x0E, data);
-
-       set_reg1(P3d4, 0x09, CRegs[0x09]);
-#else
-       unsigned char index;
-       unsigned char data;
-       u16 i;
-
-       index = *((unsigned char *) (ROMAddr + REFIndex + 0x02));
-       CRT1Table = *((u16 *) (ROMAddr + 0x204));
-       CRT1Table = CRT1Table + index * CRT1Len;
-
-       data = (unsigned char) get_reg1(P3d4, 0x11);
-       data = data & 0x7F;
-       set_reg1(P3d4, 0x11, data);
-
-       CRT1Table--;
-       for (i = 0; i <= 0x05; i++) {
-               CRT1Table++;
-               data = *((unsigned char *) (ROMAddr + CRT1Table));
-               set_reg1(P3d4, i, data);
-       }
-       for (i = 0x06; i <= 0x07; i++) {
-               CRT1Table++;
-               data = *((unsigned char *) (ROMAddr + CRT1Table));
-               set_reg1(P3d4, i, data);
-       }
-       for (i = 0x10; i <= 0x12; i++) {
-               CRT1Table++;
-               data = *((unsigned char *) (ROMAddr + CRT1Table));
-               set_reg1(P3d4, i, data);
-       }
-       for (i = 0x15; i <= 0x16; i++) {
-               CRT1Table++;
-               data = *((unsigned char *) (ROMAddr + CRT1Table));
-               set_reg1(P3d4, i, data);
-       }
-       for (i = 0x0A; i <= 0x0C; i++) {
-               CRT1Table++;
-               data = *((unsigned char *) (ROMAddr + CRT1Table));
-               set_reg1(P3c4, i, data);
-       }
-
-       CRT1Table++;
-       data = *((unsigned char *) (ROMAddr + CRT1Table));
-       data = data & 0xE0;
-       set_reg1(P3c4, 0x0E, data);
-
-       data = (unsigned char) get_reg1(P3d4, 0x09);
-       data = data & 0xDF;
-       i = *((unsigned char *) (ROMAddr + CRT1Table));
-       i = i & 0x01;
-       i = i << 5;
-       data = data | i;
-       i = *((u16 *) (ROMAddr + ModeIDOffset + 0x01));
-       i = i & DoubleScanMode;
-       if (i)
-               data = data | 0x80;
-       set_reg1(P3d4, 0x09, data);
-
-       if (ModeType > 0x03)
-               set_reg1(P3d4, 0x14, 0x4F);
-#endif
-}
-
-
-static void set_crt1_offset(unsigned long ROMAddr)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg1(P3c4, 0x0E, SRegs[0x0E]);
-       set_reg1(P3c4, 0x10, SRegs[0x10]);
-#else
-       u16 temp, ah, al;
-       u16 temp2, i;
-       u16 DisplayUnit;
-
-       temp = *((unsigned char *) (ROMAddr + ModeIDOffset + 0x03));
-       temp = temp >> 4;
-       ScreenOffset = *((u16 *) (ROMAddr + 0x206));
-       temp = *((unsigned char *) (ROMAddr + ScreenOffset + temp));
-
-       temp2 = *((u16 *) (ROMAddr + REFIndex + 0x00));
-       temp2 = temp2 & InterlaceMode;
-       if (temp2)
-               temp = temp << 1;
-       temp2 = ModeType - ModeEGA;
-       switch (temp2) {
-       case 0:
-               temp2 = 1;
-               break;
-       case 1:
-               temp2 = 2;
-               break;
-       case 2:
-               temp2 = 4;
-               break;
-       case 3:
-               temp2 = 4;
-               break;
-       case 4:
-               temp2 = 6;
-               break;
-       case 5:
-               temp2 = 8;
-               break;
-       }
-       temp = temp * temp2;
-       DisplayUnit = temp;
-
-       temp2 = temp;
-       temp = temp >> 8;
-       temp = temp & 0x0F;
-       i = get_reg1(P3c4, 0x0E);
-       i = i & 0xF0;
-       i = i | temp;
-       set_reg1(P3c4, 0x0E, i);
-
-       temp = (unsigned char) temp2;
-       temp = temp & 0xFF;
-       set_reg1(P3d4, 0x13, temp);
-
-       temp2 = *((u16 *) (ROMAddr + REFIndex + 0x00));
-       temp2 = temp2 & InterlaceMode;
-       if (temp2)
-               DisplayUnit >>= 1;
-
-       DisplayUnit = DisplayUnit << 5;
-       ah = (DisplayUnit & 0xff00) >> 8;
-       al = DisplayUnit & 0x00ff;
-       if (al == 0)
-               ah = ah + 1;
-       else
-               ah = ah + 2;
-       set_reg1(P3c4, 0x10, ah);
-#endif
-}
-
-static u16 get_vclk_len(unsigned long ROMAddr)
-{
-       u16 VCLKDataStart, vclklabel, temp;
-       VCLKDataStart = *((u16 *) (ROMAddr + 0x208));
-       for (temp = 0;; temp++) {
-               vclklabel = *((u16 *) (ROMAddr + VCLKDataStart + temp));
-               if (vclklabel == VCLKStartFreq) {
-                       temp = temp + 2;
-                       return (temp);
-               }
-       }
-       return (0);
-}
-
-static void set_crt1_vclk(unsigned long ROMAddr)
-{
-       u16 i;
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       unsigned char index, data;
-
-       index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
-       index &= 0x03F;
-       CRT1VCLKLen = get_vclk_len(ROMAddr);
-       data = index * CRT1VCLKLen;
-       VCLKData = *((u16 *) (ROMAddr + 0x208));
-       VCLKData = VCLKData + data;
-#endif
-
-       set_reg1(P3c4, 0x31, 0);
-
-       for (i = 0x2B; i <= 0x2C; i++) {
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-               set_reg1(P3c4, i, SRegs[i]);
-#else
-               data = *((unsigned char *) (ROMAddr + VCLKData));
-               set_reg1(P3c4, i, data);
-               VCLKData++;
-#endif
-       }
-       set_reg1(P3c4, 0x2D, 0x80);
-}
-static void set_vclk_state(unsigned long ROMAddr, u16 ModeNo)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg1(P3c4, 0x32, SRegs[0x32]);
-       set_reg1(P3c4, 0x07, SRegs[0x07]);
-#else
-
-       u16 data, data2;
-       u16 VCLK;
-       unsigned char index;
-
-       index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
-       index &= 0x3F;
-       CRT1VCLKLen = get_vclk_len(ROMAddr);
-       data = index * CRT1VCLKLen;
-       VCLKData = *((u16 *) (ROMAddr + 0x208));
-       VCLKData = VCLKData + data + (CRT1VCLKLen - 2);
-
-       VCLK = *((u16 *) (ROMAddr + VCLKData));
-       if (ModeNo <= 0x13)
-               VCLK = 0;
-
-       data = get_reg1(P3c4, 0x07);
-       data = data & 0x7B;
-       if (VCLK >= 150)
-               data = data | 0x80;
-       set_reg1(P3c4, 0x07, data);
-
-       data = get_reg1(P3c4, 0x32);
-       data = data & 0xD7;
-       if (VCLK >= 150)
-               data = data | 0x08;
-       set_reg1(P3c4, 0x32, data);
-
-       data2 = 0x03;
-       if (VCLK > 135)
-               data2 = 0x02;
-       if (VCLK > 160)
-               data2 = 0x01;
-       if (VCLK > 260)
-               data2 = 0x00;
-       data = get_reg1(P3c4, 0x07);
-       data = data & 0xFC;
-       data = data | data2;
-       set_reg1(P3c4, 0x07, data);
-#endif
-}
-
-static u16 calc_delay2(unsigned long ROMAddr, u16 key)
-{
-       u16 data, index;
-       unsigned char LatencyFactor[] = { 
-               88, 80, 78, 72, 70, 00,
-               00, 79, 77, 71, 69, 49,
-               88, 80, 78, 72, 70, 00,
-               00, 72, 70, 64, 62, 44
-       };
-       index = 0;
-       data = get_reg1(P3c4, 0x14);
-       if (data & 0x80)
-               index = index + 12;
-
-       data = get_reg1(P3c4, 0x15);
-       data = (data & 0xf0) >> 4;
-       if (data & 0x01)
-               index = index + 6;
-
-       data = data >> 1;
-       index = index + data;
-       data = LatencyFactor[index];
-
-       return (data);
-}
-
-static u16 calc_delay(unsigned long ROMAddr, u16 key)
-{
-       u16 data, data2, temp0, temp1;
-       unsigned char ThLowA[] = { 
-               61, 3, 52, 5, 68, 7, 100, 11,
-               43, 3, 42, 5, 54, 7, 78, 11,
-               34, 3, 37, 5, 47, 7, 67, 11
-       };
-       unsigned char ThLowB[] = { 
-               81, 4, 72, 6, 88, 8, 120, 12,
-               55, 4, 54, 6, 66, 8, 90, 12,
-               42, 4, 45, 6, 55, 8, 75, 12
-       };
-       unsigned char ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 };
-
-       data = get_reg1(P3c4, 0x16);
-       data = data >> 6;
-       data2 = get_reg1(P3c4, 0x14);
-       data2 = (data2 >> 4) & 0x0C;
-       data = data | data2;
-       data = data < 1;
-       if (key == 0) {
-               temp0 = (u16) ThLowA[data];
-               temp1 = (u16) ThLowA[data + 1];
-       } else {
-               temp0 = (u16) ThLowB[data];
-               temp1 = (u16) ThLowB[data + 1];
-       }
-
-       data2 = 0;
-       data = get_reg1(P3c4, 0x18);
-       if (data & 0x02)
-               data2 = data2 | 0x01;
-       if (data & 0x20)
-               data2 = data2 | 0x02;
-       if (data & 0x40)
-               data2 = data2 | 0x04;
-
-       data = temp1 * ThTiming[data2] + temp0;
-       return (data);
-}
-
-
-static void set_crt1_FIFO(unsigned long ROMAddr)
-{
-       u16 index, data, VCLK, data2, MCLKOffset, MCLK, colorth = 1;
-       u16 ah, bl, A, B;
-
-       index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
-       index &= 0x3F;
-       CRT1VCLKLen = get_vclk_len(ROMAddr);
-       data = index * CRT1VCLKLen;
-       VCLKData = *((u16 *) (ROMAddr + 0x208));
-       VCLKData = VCLKData + data + (CRT1VCLKLen - 2);
-       VCLK = *((u16 *) (ROMAddr + VCLKData));
-
-       MCLKOffset = *((u16 *) (ROMAddr + 0x20C));
-       index = get_reg1(P3c4, 0x3A);
-       index = index & 07;
-       MCLKOffset = MCLKOffset + index * 5;
-       MCLK = *((unsigned char *) (ROMAddr + MCLKOffset + 0x03));
-
-       data2 = ModeType - 0x02;
-       switch (data2) {
-       case 0:
-               colorth = 1;
-               break;
-       case 1:
-               colorth = 2;
-               break;
-       case 2:
-               colorth = 4;
-               break;
-       case 3:
-               colorth = 4;
-               break;
-       case 4:
-               colorth = 6;
-               break;
-       case 5:
-               colorth = 8;
-               break;
-       }
-
-       do {
-               B = (calc_delay(ROMAddr, 0) * VCLK * colorth);
-               B = B / (16 * MCLK);
-               B++;
-
-               A = (calc_delay(ROMAddr, 1) * VCLK * colorth);
-               A = A / (16 * MCLK);
-               A++;
-
-               if (A < 4)
-                       A = 0;
-               else
-                       A = A - 4;
-
-               if (A > B)
-                       bl = A;
-               else
-                       bl = B;
-
-               bl++;
-               if (bl > 0x13) {
-                       data = get_reg1(P3c4, 0x16);
-                       data = data >> 6;
-                       if (data != 0) {
-                               data--;
-                               data = data << 6;
-                               data2 = get_reg1(P3c4, 0x16);
-                               data2 = (data2 & 0x3f) | data;
-                               set_reg1(P3c4, 0x16, data2);
-                       } else
-                               bl = 0x13;
-               }
-       } while (bl > 0x13);
-
-       ah = bl;
-       ah = ah << 4;
-       ah = ah | 0x0f;
-       set_reg1(P3c4, 0x08, ah);
-
-       data = bl;
-       data = data & 0x10;
-       data = data << 1;
-       data2 = get_reg1(P3c4, 0x0F);
-       data2 = data2 & 0x9f;
-       data2 = data2 | data;
-       set_reg1(P3c4, 0x0F, data2);
-
-       data = bl + 3;
-       if (data > 0x0f)
-               data = 0x0f;
-       set_reg1(P3c4, 0x3b, 0x00);
-       data2 = get_reg1(P3c4, 0x09);
-       data2 = data2 & 0xF0;
-       data2 = data2 | data;
-       set_reg1(P3c4, 0x09, data2);
-}
-
-static void set_crt1_FIFO2(unsigned long ROMAddr)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg1(P3c4, 0x15, SRegs[0x15]);
-
-       set_reg4(0xcf8, 0x80000050);
-       set_reg4(0xcfc, 0xc5041e04);
-
-       set_reg1(P3c4, 0x08, SRegs[0x08]);
-       set_reg1(P3c4, 0x0F, SRegs[0x0F]);
-       set_reg1(P3c4, 0x3b, 0x00);
-       set_reg1(P3c4, 0x09, SRegs[0x09]);
-#else
-
-       u16 index, data, VCLK, data2, MCLKOffset, MCLK, colorth = 1;
-       u16 ah, bl, B;
-       unsigned long eax;
-
-       index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
-       index &= 0x3F;
-       CRT1VCLKLen = get_vclk_len(ROMAddr);
-       data = index * CRT1VCLKLen;
-       VCLKData = *((u16 *) (ROMAddr + 0x208));
-       VCLKData = VCLKData + data + (CRT1VCLKLen - 2);
-       VCLK = *((u16 *) (ROMAddr + VCLKData));
-
-       MCLKOffset = *((u16 *) (ROMAddr + 0x20C));
-       index = get_reg1(P3c4, 0x1A);
-       index = index & 07;
-       MCLKOffset = MCLKOffset + index * 5;
-       MCLK = *((u16 *) (ROMAddr + MCLKOffset + 0x03));
-
-       data2 = ModeType - 0x02;
-       switch (data2) {
-       case 0:
-               colorth = 1;
-               break;
-       case 1:
-               colorth = 1;
-               break;
-       case 2:
-               colorth = 2;
-               break;
-       case 3:
-               colorth = 2;
-               break;
-       case 4:
-               colorth = 3;
-               break;
-       case 5:
-               colorth = 4;
-               break;
-       }
-
-       do {
-               B = (calc_delay2(ROMAddr, 0) * VCLK * colorth);
-               if (B % (16 * MCLK) == 0) {
-                       B = B / (16 * MCLK);
-                       bl = B + 1;
-               } else {
-                       B = B / (16 * MCLK);
-                       bl = B + 2;
-               }
-
-               if (bl > 0x13) {
-                       data = get_reg1(P3c4, 0x15);
-                       data = data & 0xf0;
-                       if (data != 0xb0) {
-                               data = data + 0x20;
-                               if (data == 0xa0)
-                                       data = 0x30;
-                               data2 = get_reg1(P3c4, 0x15);
-                               data2 = (data2 & 0x0f) | data;
-                               set_reg1(P3c4, 0x15, data2);
-                       } else
-                               bl = 0x13;
-               }
-       } while (bl > 0x13);
-
-       data2 = get_reg1(P3c4, 0x15);
-       data2 = (data2 & 0xf0) >> 4;
-       data2 = data2 << 24;
-
-       set_reg4(0xcf8, 0x80000050);
-       eax = get_reg3(0xcfc);
-       eax = eax & 0x0f0ffffff;
-       eax = eax | data2;
-       set_reg4(0xcfc, eax);
-
-       ah = bl;
-       ah = ah << 4;
-       ah = ah | 0x0f;
-       set_reg1(P3c4, 0x08, ah);
-
-       data = bl;
-       data = data & 0x10;
-       data = data << 1;
-       data2 = get_reg1(P3c4, 0x0F);
-       data2 = data2 & 0x9f;
-       data2 = data2 | data;
-       set_reg1(P3c4, 0x0F, data2);
-
-       data = bl + 3;
-       if (data > 0x0f)
-               data = 0x0f;
-       set_reg1(P3c4, 0x3b, 0x00);
-       data2 = get_reg1(P3c4, 0x09);
-       data2 = data2 & 0xF0;
-       data2 = data2 | data;
-       set_reg1(P3c4, 0x09, data2);
-#endif
-}
-
-static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg1(P3c4, 0x06, SRegs[0x06]);
-       set_reg1(P3c4, 0x01, SRegs[0x01]);
-       set_reg1(P3c4, 0x0F, SRegs[0x0F]);
-       set_reg1(P3c4, 0x21, SRegs[0x21]);
-#else
-
-       u16 data, data2, data3;
-
-       if (ModeNo > 0x13)
-               data = *((u16 *) (ROMAddr + REFIndex + 0x00));
-       else
-               data = 0;
-
-       data2 = 0;
-       if (ModeNo > 0x13)
-               if (ModeType > 0x02) {
-                       data2 = data2 | 0x02;
-                       data3 = ModeType - ModeVGA;
-                       data3 = data3 << 2;
-                       data2 = data2 | data3;
-               }
-
-       data = data & InterlaceMode;
-       if (data)
-               data2 = data2 | 0x20;
-       set_reg1(P3c4, 0x06, data2);
-
-       data = get_reg1(P3c4, 0x01);
-       data = data & 0xF7;
-       data2 = *((u16 *) (ROMAddr + ModeIDOffset + 0x01));
-       data2 = data2 & HalfDCLK;
-       if (data2)
-               data = data | 0x08;
-       set_reg1(P3c4, 0x01, data);
-
-       data = get_reg1(P3c4, 0x0F);
-       data = data & 0xF7;
-       data2 = *((u16 *) (ROMAddr + ModeIDOffset + 0x01));
-       data2 = data2 & LineCompareOff;
-       if (data2)
-               data = data | 0x08;
-       set_reg1(P3c4, 0x0F, data);
-
-       data = get_reg1(P3c4, 0x21);
-       data = data & 0x1F;
-       if (ModeType == 0x00)
-               data = data | 0x60;
-       else if (ModeType <= 0x02)
-               data = data | 0x00;
-       else
-               data = data | 0xA0;
-       set_reg1(P3c4, 0x21, data);
-#endif
-}
-
-static void set_interlace(unsigned long ROMAddr, u16 ModeNo)
-{
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       set_reg1(P3d4, 0x19, CRegs[0x19]);
-       set_reg1(P3d4, 0x1A, CRegs[0x1A]);
-#else
-
-       unsigned long Temp;
-       u16 data, Temp2;
-
-       Temp = (unsigned long) get_reg1(P3d4, 0x01);
-       Temp++;
-       Temp = Temp * 8;
-
-       if (Temp == 1024)
-               data = 0x0035;
-       else if (Temp == 1280)
-               data = 0x0048;
-       else
-               data = 0x0000;
-
-       Temp2 = *((u16 *) (ROMAddr + REFIndex + 0x00));
-       Temp2 &= InterlaceMode;
-       if (Temp2 == 0)
-               data = 0x0000;
-
-       set_reg1(P3d4, 0x19, data);
-
-       Temp = (unsigned long) get_reg1(P3d4, 0x1A);
-       Temp2 = (u16) (Temp & 0xFC);
-       set_reg1(P3d4, 0x1A, (u16) Temp);
-
-       Temp = (unsigned long) get_reg1(P3c4, 0x0f);
-       Temp2 = (u16) Temp & 0xBF;
-       if (ModeNo == 0x37)
-               Temp2 = Temp2 | 0x40;
-       set_reg1(P3d4, 0x1A, (u16) Temp2);
-#endif
-}
-
-static void write_DAC(u16 dl, u16 ah, u16 al, u16 dh)
-{
-       u16 temp;
-       u16 bh, bl;
-
-       bh = ah;
-       bl = al;
-       if (dl != 0) {
-               temp = bh;
-               bh = dh;
-               dh = temp;
-               if (dl == 1) {
-                       temp = bl;
-                       bl = dh;
-                       dh = temp;
-               } else {
-                       temp = bl;
-                       bl = bh;
-                       bh = temp;
-               }
-       }
-       set_reg3(P3c9, (u16) dh);
-       set_reg3(P3c9, (u16) bh);
-       set_reg3(P3c9, (u16) bl);
-}
-
-
-static void load_DAC(unsigned long ROMAddr)
-{
-       u16 data, data2;
-       u16 time, i, j, k;
-       u16 m, n, o;
-       u16 si, di, bx, dl;
-       u16 al, ah, dh;
-       u16 *table = VGA_DAC;
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       data = *((u16 *) (ROMAddr + ModeIDOffset + 0x01));
-       data = data & DACInfoFlag;
-       time = 64;
-       if (data == 0x00)
-               table = MDA_DAC;
-       if (data == 0x08)
-               table = CGA_DAC;
-       if (data == 0x10)
-               table = EGA_DAC;
-       if (data == 0x18) {
-               time = 256;
-               table = VGA_DAC;
-       }
-#else
-       time = 256;
-       table = VGA_DAC;
-#endif
-
-       if (time == 256)
-               j = 16;
-       else
-               j = time;
-
-       set_reg3(P3c6, 0xFF);
-       set_reg3(P3c8, 0x00);
-
-       for (i = 0; i < j; i++) {
-               data = table[i];
-               for (k = 0; k < 3; k++) {
-                       data2 = 0;
-                       if (data & 0x01)
-                               data2 = 0x2A;
-                       if (data & 0x02)
-                               data2 = data2 + 0x15;
-                       set_reg3(P3c9, data2);
-                       data = data >> 2;
-               }
-       }
-
-       if (time == 256) {
-               for (i = 16; i < 32; i++) {
-                       data = table[i];
-                       for (k = 0; k < 3; k++)
-                               set_reg3(P3c9, data);
-               }
-               si = 32;
-               for (m = 0; m < 9; m++) {
-                       di = si;
-                       bx = si + 0x04;
-                       dl = 0;
-                       for (n = 0; n < 3; n++) {
-                               for (o = 0; o < 5; o++) {
-                                       dh = table[si];
-                                       ah = table[di];
-                                       al = table[bx];
-                                       si++;
-                                       write_DAC(dl, ah, al, dh);
-                               }
-                               si = si - 2;
-                               for (o = 0; o < 3; o++) {
-                                       dh = table[bx];
-                                       ah = table[di];
-                                       al = table[si];
-                                       si--;
-                                       write_DAC(dl, ah, al, dh);
-                               }
-                               dl++;
-                       }
-                       si = si + 5;
-               }
-       }
-}
-
-static void display_on(void)
-{
-       u16 data;
-
-       data = get_reg1(P3c4, 0x01);
-       data = data & 0xDF;
-       set_reg1(P3c4, 0x01, data);
-}
-
-void SetMemoryClock(void)
-{
-       unsigned char i;
-       int idx;
-
-       u8 MCLK[] = {
-               0x5A, 0x64, 0x80, 0x66, 0x00,   // SDRAM
-               0xB3, 0x45, 0x80, 0x83, 0x00,   // SGRAM
-               0x37, 0x61, 0x80, 0x00, 0x01,   // ESDRAM
-               0x37, 0x22, 0x80, 0x33, 0x01,
-               0x37, 0x61, 0x80, 0x00, 0x01,
-               0x37, 0x61, 0x80, 0x00, 0x01,
-               0x37, 0x61, 0x80, 0x00, 0x01,
-               0x37, 0x61, 0x80, 0x00, 0x01
-       };
-
-       u8 ECLK[] = {
-               0x54, 0x43, 0x80, 0x00, 0x01,
-               0x53, 0x43, 0x80, 0x00, 0x01,
-               0x55, 0x43, 0x80, 0x00, 0x01,
-               0x52, 0x43, 0x80, 0x00, 0x01,
-               0x3f, 0x42, 0x80, 0x00, 0x01,
-               0x54, 0x43, 0x80, 0x00, 0x01,
-               0x54, 0x43, 0x80, 0x00, 0x01,
-               0x54, 0x43, 0x80, 0x00, 0x01
-       };
-
-       idx = RAMType * 5;
-
-       for (i = 0x28; i <= 0x2A; i++) {        // Set MCLK
-               set_reg1(P3c4, i, MCLK[idx]);
-               idx++;
-       }
-
-       idx = RAMType * 5;
-       for (i = 0x2E; i <= 0x30; i++) {        // Set ECLK
-               set_reg1(P3c4, i, ECLK[idx]);
-               idx++;
-       }
-}
-
-void ClearDAC(u16 port)
-{
-       int i;
-
-       set_reg3(P3c8, 0x00);
-       for (i = 0; i < (256 * 3); i++)
-               set_reg3(P3c9, 0x00);
-}
-
-void ClearALLBuffer(void)
-{
-       unsigned long AdapterMemorySize;
-
-       AdapterMemorySize = get_reg1(P3c4, 0x14);
-       AdapterMemorySize = AdapterMemorySize & 0x3F;
-       AdapterMemorySize++;
-
-       memset((char *) ivideo.video_vbase, 0, AdapterMemorySize);
-}
-
-void LongWait(void)
-{
-       unsigned long temp;
-
-       for (temp = 1; temp > 0;) {
-               temp = get_reg2(P3da);
-               temp = temp & 0x08;
-       }
-       for (; temp == 0;) {
-               temp = get_reg2(P3da);
-               temp = temp & 0x08;
-       }
-}
-
-void WaitDisplay(void)
-{
-       unsigned short temp;
-
-       for (temp = 0; temp == 0;) {
-               temp = get_reg2(P3da);
-               temp = temp & 0x01;
-       }
-       for (; temp == 1;) {
-               temp = get_reg2(P3da);
-               temp = temp & 0x01;
-       }
-}
-
-int TestMonitorType(unsigned short d1, unsigned short d2, unsigned short d3)
-{
-       unsigned short temp;
-       set_reg3(P3c6, 0xFF);
-       set_reg3(P3c8, 0x00);
-       set_reg3(P3c9, d1);
-       set_reg3(P3c9, d2);
-       set_reg3(P3c9, d3);
-       WaitDisplay();          //wait horizontal retrace
-       temp = get_reg2(P3c2);
-       if (temp & 0x10)
-               return 1;
-       else
-               return 0;
-}
-
-void SetRegANDOR(unsigned short Port, unsigned short Index,
-                unsigned short DataAND, unsigned short DataOR)
-{
-       unsigned short temp1;
-       temp1 = get_reg1(Port, Index);  //part1port index 02
-       temp1 = (temp1 & (DataAND)) | DataOR;
-       set_reg1(Port, Index, temp1);
-}
-
-
-int DetectMonitor(void)
-{
-       unsigned short flag1;
-       unsigned short DAC_TEST_PARMS[3] = { 0x0F, 0x0F, 0x0F };
-       unsigned short DAC_CLR_PARMS[3] = { 0x00, 0x00, 0x00 };
-
-       flag1 = get_reg1(P3c4, 0x38);   //call BridgeisOn
-       if ((flag1 & 0x20)) {
-               set_reg1(P3d4, 0x30, 0x41);
-       }
-
-       SiSSetMode(0x2E);       //set mode to 0x2E instead of 0x3
-
-       ClearDAC(P3c8);
-       ClearALLBuffer();
-
-       LongWait();
-       LongWait();
-
-       flag1 = TestMonitorType(DAC_TEST_PARMS[0], DAC_TEST_PARMS[1],
-                               DAC_TEST_PARMS[2]);
-       if (flag1 == 0) {
-               flag1 = TestMonitorType(DAC_TEST_PARMS[0], DAC_TEST_PARMS[1],
-                                       DAC_TEST_PARMS[2]);
-       }
-
-       if (flag1 == 1) {
-               SetRegANDOR(P3d4, 0x32, ~Monitor1Sense, Monitor1Sense);
-       } else {
-               SetRegANDOR(P3d4, 0x32, ~Monitor1Sense, 0x0);
-       }
-
-       TestMonitorType(DAC_CLR_PARMS[0], DAC_CLR_PARMS[1],
-                       DAC_CLR_PARMS[2]);
-
-       set_reg1(P3d4, 0x34, 0x4A);
-
-       return 1;
-}
-
-int SiSInit300(void)
-{
-       //unsigned long ROMAddr = rom_vbase;
-       u16 BaseAddr = (u16) ivideo.vga_base;
-       unsigned char i, temp, AGP;
-       unsigned long j, k, ulTemp;
-       unsigned char SR11, SR19, SR1A, SR21, SR22;
-       unsigned char SR14;
-       unsigned long Temp;
-
-       P3c4 = BaseAddr + 0x14;
-       P3d4 = BaseAddr + 0x24;
-       P3c0 = BaseAddr + 0x10;
-       P3ce = BaseAddr + 0x1e;
-       P3c2 = BaseAddr + 0x12;
-       P3ca = BaseAddr + 0x1a;
-       P3c6 = BaseAddr + 0x16;
-       P3c7 = BaseAddr + 0x17;
-       P3c8 = BaseAddr + 0x18;
-       P3c9 = BaseAddr + 0x19;
-       P3da = BaseAddr + 0x2A;
-
-       set_reg1(P3c4, 0x05, 0x86);     // 1.Openkey
-
-       SR14 = (unsigned char) get_reg1(P3c4, 0x14);
-       SR19 = (unsigned char) get_reg1(P3c4, 0x19);
-       SR1A = (unsigned char) get_reg1(P3c4, 0x1A);
-
-       for (i = 0x06; i < 0x20; i++)
-               set_reg1(P3c4, i, 0);   // 2.Reset Extended register
-       for (i = 0x21; i <= 0x27; i++)
-               set_reg1(P3c4, i, 0);   //   Reset Extended register
-       for (i = 0x31; i <= 0x3D; i++)
-               set_reg1(P3c4, i, 0);
-       for (i = 0x30; i <= 0x37; i++)
-               set_reg1(P3d4, i, 0);
-
-#if 0
-       if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan))
-               // 3.Set Define Extended register
-               temp = (unsigned char) SR1A;
-       else {
-               temp = *((unsigned char *) (ROMAddr + SoftSettingAddr));
-               if ((temp & SoftDRAMType) == 0) {
-                       // 3.Set Define Extended register
-                       temp = (unsigned char) get_reg1(P3c4, 0x3A);
-               }
-       }
-#endif
-
-       // 3.Set Define Extended register
-       temp = (unsigned char) SR1A;
-
-       RAMType = temp & 0x07;
-       SetMemoryClock();
-       for (k = 0; k < 5; k++)
-               for (j = 0; j < 0xffff; j++)
-                       ulTemp = (unsigned long) get_reg1(P3c4, 0x05);
-
-       Temp = (unsigned long) get_reg1(P3c4, 0x3C);
-       Temp = Temp | 0x01;
-       set_reg1(P3c4, 0x3C, (unsigned short) Temp);
-       for (k = 0; k < 5; k++)
-               for (j = 0; j < 0xffff; j++)
-                       Temp = (unsigned long) get_reg1(P3c4, 0x05);
-
-       Temp = (unsigned long) get_reg1(P3c4, 0x3C);
-       Temp = Temp & 0xFE;
-       set_reg1(P3c4, 0x3C, (unsigned short) Temp);
-       for (k = 0; k < 5; k++)
-               for (j = 0; j < 0xffff; j++)
-                       Temp = (unsigned long) get_reg1(P3c4, 0x05);
-
-       //SR07=*((unsigned char *)(ROMAddr+0xA4));  // todo
-       set_reg1(P3c4, 0x07, SRegsInit[0x07]);
-#if 0
-       if (HwDeviceExtension->jChipID == SIS_Glamour)
-               for (i = 0x15; i <= 0x1C; i++) {
-                       temp = *((unsigned char *) (ROMAddr + 0xA5 + ((i - 0x15) * 8) + RAMType));
-                       set_reg1(P3c4, i, temp);
-               }
-#endif
-
-       //SR1F=*((unsigned char *)(ROMAddr+0xE5));  
-       set_reg1(P3c4, 0x1F, SRegsInit[0x1F]);
-
-       // Get AGP
-       AGP = 1;
-       temp = (unsigned char) get_reg1(P3c4, 0x3A);
-       temp = temp & 0x30;
-       if (temp == 0x30)
-               // PCI
-               AGP = 0;
-
-       //SR21=*((unsigned char *)(ROMAddr+0xE6));
-       SR21 = SRegsInit[0x21];
-       if (AGP == 0)
-               SR21 = SR21 & 0xEF;     // PCI
-       set_reg1(P3c4, 0x21, SR21);
-
-       //SR22=*((unsigned char *)(ROMAddr+0xE7));
-       SR22 = SRegsInit[0x22];
-       if (AGP == 1)
-               SR22 = SR22 & 0x20;     // AGP
-       set_reg1(P3c4, 0x22, SR22);
-
-       //SR23=*((unsigned char *)(ROMAddr+0xE8));
-       set_reg1(P3c4, 0x23, SRegsInit[0x23]);
-
-       //SR24=*((unsigned char *)(ROMAddr+0xE9));
-       set_reg1(P3c4, 0x24, SRegsInit[0x24]);
-
-       //SR25=*((unsigned char *)(ROMAddr+0xEA));
-       set_reg1(P3c4, 0x25, SRegsInit[0x25]);
-
-       //SR32=*((unsigned char *)(ROMAddr+0xEB));
-       set_reg1(P3c4, 0x32, SRegsInit[0x32]);
-
-       SR11 = 0x0F;
-       set_reg1(P3c4, 0x11, SR11);
-
-#if 0
-       if (IF_DEF_LVDS == 1) {
-               //LVDS
-               temp = ExtChipLVDS;
-       } else if (IF_DEF_TRUMPION == 1) {
-               //Trumpion
-               temp = ExtChipTrumpion;
-       } else {
-               //301
-               temp = ExtChip301;
-       }
-#endif
-
-       // 301;
-       temp = 0x02;
-       set_reg1(P3d4, 0x37, temp);
-
-#if 0
-       //09/07/99 modify by domao for 630/540 MM
-       if (HwDeviceExtension->jChipID == SIS_Glamour) {
-               //For SiS 300 Chip
-               SetDRAMSize(HwDeviceExtension);
-               SetDRAMSize(HwDeviceExtension);
-       } else {
-               //For SiS 630/540 Chip
-               //Restore SR14, SR19 and SR1A
-               set_reg1(P3c4, 0x14, SR14);
-               set_reg1(P3c4, 0x19, SR19);
-               set_reg1(P3c4, 0x1A, SR1A);
-       }
-#endif
-
-       set_reg1(P3c4, 0x14, SR14);
-       set_reg1(P3c4, 0x19, SR19);
-       set_reg1(P3c4, 0x1A, SR1A);
-       set_reg3(P3c6, 0xff);
-       ClearDAC(P3c8);
-       DetectMonitor();
-
-#if 0
-       //sense CRT2
-       GetSenseStatus(HwDeviceExtension, BaseAddr, ROMAddr);      
-#endif
-
-       return (TRUE);
-}
-
-static int SiSSetMode(u16 ModeNo)
-{
-       //#ifndef CONFIG_FB_SIS_LINUXBIOS
-       unsigned long temp;
-       //#endif
-
-       u16 cr30flag, cr31flag;
-       unsigned long ROMAddr = rom_vbase;
-       u16 BaseAddr = (u16) ivideo.vga_base;
-
-       P3c4 = BaseAddr + 0x14;
-       P3d4 = BaseAddr + 0x24;
-       P3c0 = BaseAddr + 0x10;
-       P3ce = BaseAddr + 0x1e;
-       P3c2 = BaseAddr + 0x12;
-       P3ca = BaseAddr + 0x1a;
-       P3c6 = BaseAddr + 0x16;
-       P3c7 = BaseAddr + 0x17;
-       P3c8 = BaseAddr + 0x18;
-       P3c9 = BaseAddr + 0x19;
-       P3da = BaseAddr + 0x2A;
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       temp = search_modeID(ROMAddr, ModeNo);
-
-       if (temp == 0)
-               return (0);
-
-       temp = check_memory_size(ROMAddr);
-       if (temp == 0)
-               return (0);
-#endif
-
-#if 1
-       cr30flag = (unsigned char) get_reg1(P3d4, 0x30);
-       if (((cr30flag & 0x01) == 1) || ((cr30flag & 0x02) == 0)) {
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-               get_mode_ptr(ROMAddr, ModeNo);
-#endif
-               set_seq_regs(ROMAddr);
-               set_misc_regs(ROMAddr);
-               set_crtc_regs(ROMAddr);
-               set_attregs(ROMAddr);
-               set_grc_regs(ROMAddr);
-               ClearExt1Regs();
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-               temp = get_rate_ptr(ROMAddr, ModeNo);
-               if (temp) {
-#endif
-                       set_sync(ROMAddr);
-                       set_crt1_crtc(ROMAddr);
-                       set_crt1_offset(ROMAddr);
-                       set_crt1_vclk(ROMAddr);
-                       set_vclk_state(ROMAddr, ModeNo);
-
-                       if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan))
-                               set_crt1_FIFO2(ROMAddr);
-                       else    /* SiS 300 */
-                               set_crt1_FIFO(ROMAddr);
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-               }
-#endif
-               set_crt1_mode_regs(ROMAddr, ModeNo);
-               if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan))
-                       set_interlace(ROMAddr, ModeNo);
-               load_DAC(ROMAddr);
-
-               /* clear OnScreen */
-               memset((char *) ivideo.video_vbase, 0,
-                      video_linelength * ivideo.video_height);
-       }
-#else
-       cr30flag = (unsigned char) get_reg1(P3d4, 0x30);
-       if (((cr30flag & 0x01) == 1) || ((cr30flag & 0x02) == 0)) {
-               //set_seq_regs(ROMAddr);
-               {
-                       unsigned char SRdata;
-                       SRdata = SRegs[0x01] | 0x20;
-                       set_reg1(P3c4, 0x01, SRdata);
-
-                       for (i = 02; i <= 04; i++)
-                               set_reg1(P3c4, i, SRegs[i]);
-               }
-
-               //set_misc_regs(ROMAddr);
-               {
-                       set_reg3(P3c2, 0x23);
-               }
-
-               //set_crtc_regs(ROMAddr);
-               {
-                       unsigned char CRTCdata;
-
-                       CRTCdata = (unsigned char) get_reg1(P3d4, 0x11);
-                       set_reg1(P3d4, 0x11, CRTCdata);
-
-                       for (i = 0; i <= 0x18; i++)
-                               set_reg1(P3d4, i, CRegs[i]);
-               }
-
-               //set_attregs(ROMAddr);
-               {
-                       for (i = 0; i <= 0x13; i++) {
-                               get_reg2(P3da);
-                               set_reg3(P3c0, i);
-                               set_reg3(P3c0, ARegs[i]);
-                       }
-                       get_reg2(P3da);
-                       set_reg3(P3c0, 0x14);
-                       set_reg3(P3c0, 0x00);
-                       get_reg2(P3da);
-                       set_reg3(P3c0, 0x20);
-               }
-
-               //set_grc_regs(ROMAddr);
-               {
-                       for (i = 0; i <= 0x08; i++)
-                               set_reg1(P3ce, i, GRegs[i]);
-               }
-
-               //ClearExt1Regs();
-               {
-                       for (i = 0x0A; i <= 0x0E; i++)
-                               set_reg1(P3c4, i, 0x00);
-               }
-
-               //set_sync(ROMAddr);
-               {
-                       set_reg3(P3c2, MReg);
-               }
-
-               //set_crt1_crtc(ROMAddr);
-               {
-                       unsigned char data;
-
-                       data = (unsigned char) get_reg1(P3d4, 0x11);
-                       data = data & 0x7F;
-                       set_reg1(P3d4, 0x11, data);
-
-                       for (i = 0; i <= 0x07; i++)
-                               set_reg1(P3d4, i, CRegs[i]);
-                       for (i = 0x10; i <= 0x12; i++)
-                               set_reg1(P3d4, i, CRegs[i]);
-                       for (i = 0x15; i <= 0x16; i++)
-                               set_reg1(P3d4, i, CRegs[i]);
-                       for (i = 0x0A; i <= 0x0C; i++)
-                               set_reg1(P3c4, i, SRegs[i]);
-
-                       data = SRegs[0x0E] & 0xE0;
-                       set_reg1(P3c4, 0x0E, data);
-
-                       set_reg1(P3d4, 0x09, CRegs[0x09]);
-
-               }
-
-               //set_crt1_offset(ROMAddr);
-               {
-                       set_reg1(P3c4, 0x0E, SRegs[0x0E]);
-                       set_reg1(P3c4, 0x10, SRegs[0x10]);
-               }
-
-               //set_crt1_vclk(ROMAddr);
-               {
-                       set_reg1(P3c4, 0x31, 0);
-
-                       for (i = 0x2B; i <= 0x2C; i++)
-                               set_reg1(P3c4, i, SRegs[i]);
-                       set_reg1(P3c4, 0x2D, 0x80);
-               }
-
-               //set_vclk_state(ROMAddr, ModeNo);
-               {
-                       set_reg1(P3c4, 0x32, SRegs[0x32]);
-                       set_reg1(P3c4, 0x07, SRegs[0x07]);
-               }
-
-               if ((ivideo.chip_id == SIS_Trojan)
-                   || (ivideo.chip_id == SIS_Spartan)) {
-                       //set_crt1_FIFO2(ROMAddr);
-                       set_reg1(P3c4, 0x15, SRegs[0x15]);
-
-                       set_reg4(0xcf8, 0x80000050);
-                       set_reg4(0xcfc, 0xc5041e04);
-
-                       set_reg1(P3c4, 0x08, SRegs[0x08]);
-                       set_reg1(P3c4, 0x0F, SRegs[0x0F]);
-                       set_reg1(P3c4, 0x3b, 0x00);
-                       set_reg1(P3c4, 0x09, SRegs[0x09]);
-               }
-
-               //set_crt1_mode_regs(ROMAddr, ModeNo);
-               {
-                       set_reg1(P3c4, 0x06, SRegs[0x06]);
-                       set_reg1(P3c4, 0x01, SRegs[0x01]);
-                       set_reg1(P3c4, 0x0F, SRegs[0x0F]);
-                       set_reg1(P3c4, 0x21, SRegs[0x21]);
-               }
-
-               if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan)) {
-                       //set_interlace(ROMAddr, ModeNo);
-                       set_reg1(P3d4, 0x19, CRegs[0x19]);
-                       set_reg1(P3d4, 0x1A, CRegs[0x1A]);
-               }
-               load_DAC(ROMAddr);
-
-               /* clear OnScreen */
-               memset((char *) ivideo.video_vbase, 0,
-                      video_linelength * ivideo.video_height);
-       }
-#endif
-       cr31flag = (unsigned char) get_reg1(P3d4, 0x31);
-
-       display_on();
-
-       return (0);
-}
-
-static void pre_setmode(void)
-{
-       vgawb(CRTC_ADR, 0x30);
-       vgawb(CRTC_DATA, 0x00);
-
-       vgawb(CRTC_ADR, 0x31);
-       vgawb(CRTC_DATA, 0x60);
-
-       DPRINTK("Setting CR33 = 0x%x\n", rate_idx & 0x0f);
-
-       /* set CRT1 refresh rate */
-       vgawb(CRTC_ADR, 0x33);
-       vgawb(CRTC_DATA, rate_idx & 0x0f);
-}
-
-static void post_setmode(void)
-{
-       u8 uTemp;
-
-       /* turn on CRT1 */
-       vgawb(CRTC_ADR, 0x17);
-       uTemp = vgarb(CRTC_DATA);
-       uTemp |= 0x80;
-       vgawb(CRTC_DATA, uTemp);
-
-       /* disable 24-bit palette RAM and Gamma correction */
-       vgawb(SEQ_ADR, 0x07);
-       uTemp = vgarb(SEQ_DATA);
-       uTemp &= ~0x04;
-       vgawb(SEQ_DATA, uTemp);
-}
-
-static void search_mode(const char *name)
-{
-       int i = 0;
-
-       if (name == NULL)
-               return;
-
-       while (sisbios_mode[i].mode_no != 0) {
-               if (!strcmp(name, sisbios_mode[i].name)) {
-                       mode_idx = i;
-                       break;
-               }
-               i++;
-       }
-       if (mode_idx < 0)
-               DPRINTK("Invalid user mode : %s\n", name);
-}
-
-static u8 search_refresh_rate(unsigned int rate)
-{
-       u16 xres, yres;
-       int i = 0;
-
-       xres = sisbios_mode[mode_idx].xres;
-       yres = sisbios_mode[mode_idx].yres;
-
-       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++;
-       }
-
-       DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate, xres,
-               yres);
-
-       return 0;
-}
-
-
-
-/* ------------------ Public Routines ------------------------------- */
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-                        struct fb_info *info)
-{
-       DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con);
-
-       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       strcpy(fix->id, fb_info.modename);
-
-       fix->smem_start = ivideo.video_base;
-       if(ivideo.video_size > 0x800000)
-               fix->smem_len = RESERVED_MEM_SIZE_8M;   /* reserved for Xserver */
-       else
-               fix->smem_len = RESERVED_MEM_SIZE_4M;   /* reserved for Xserver */
-
-       fix->type = video_type;
-       fix->type_aux = 0;
-       if (ivideo.video_bpp == 8)
-               fix->visual = FB_VISUAL_PSEUDOCOLOR;
-       else
-               fix->visual = FB_VISUAL_TRUECOLOR;
-       fix->xpanstep = 0;
-       fix->ypanstep = 0;
-       fix->ywrapstep = 0;
-       fix->line_length = video_linelength;
-       fix->mmio_start = ivideo.mmio_base;
-       fix->mmio_len = 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 */
-
-       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);
-
-       if (con == -1)
-               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)
-{
-       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 */
-               return -EINVAL;
-       }
-
-       /* get actual setting value */
-       crtc_to_var(var);
-
-       /* update display of current console */
-       sisfb_set_disp(con, var);
-
-       if (info->changevar)
-               (*info->changevar) (con);
-
-       if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
-               return err;
-
-       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);
-
-       return 0;
-}
-
-
-/*
- *    Get the Colormap
- */
-
-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);
-       else
-               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)
-{
-       int err;
-
-       if (!fb_display[con].cmap.len) {        /* no colormap allocated */
-               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);
-       else
-               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)
-{
-       switch (cmd) {
-       case FBIO_ALLOC:
-               if (!capable(CAP_SYS_RAWIO))
-                       return -EPERM;
-               sis_malloc((struct sis_memreq *) arg);
-               break;
-       case FBIO_FREE:
-               if (!capable(CAP_SYS_RAWIO))
-                       return -EPERM;
-               sis_free(*(unsigned long *) arg);
-               break;
-       case FBIOGET_GLYPH:
-               sis_get_glyph((struct GlyInfo *) arg);
-               break;
-       case FBIOGET_HWCINFO:
-               {
-                       unsigned long *hwc_offset = (unsigned long *) arg;
-
-                       if (caps | HW_CURSOR_CAP)
-                               *hwc_offset = hwcursor_vbase -
-                                   (unsigned long) ivideo.video_vbase;
-                       else
-                               *hwc_offset = 0;
-
-                       break;
-               }
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int sisfb_mmap(struct fb_info *info, struct file *file,
-                     struct vm_area_struct *vma)
-{
-       struct fb_var_screeninfo var;
-       unsigned long start;
-       unsigned long off;
-       u32 len;
-
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               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);
-
-       if (off >= len) {
-               /* memory mapped io */
-               off -= len;
-               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);
-       }
-
-       start &= PAGE_MASK;
-       if ((vma->vm_end - vma->vm_start + off) > len)
-               return -EINVAL;
-       off += start;
-       vma->vm_pgoff = off >> PAGE_SHIFT;
-
-#if defined(__i386__)
-       if (boot_cpu_data.x86 > 3)
-               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))
-               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,
-};
-
-int __init sisfb_setup(char *options)
-{
-       char *this_opt;
-
-       fb_info.fontname[0] = '\0';
-       ivideo.refresh_rate = 0;
-
-       if (!options || !*options)
-               return 0;
-
-       for (this_opt = strtok(options, ","); this_opt; 
-            this_opt = strtok(NULL, ",")) {
-               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
-                       DPRINTK("invalid parameter %s\n", this_opt);
-       }
-       return 0;
-}
-
-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)
-{
-       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_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))) 
-       {
-               currcon = con;
-               return 1;
-       }
-
-       currcon = con;
-
-       do_set_var(&fb_display[con].var, 1, info);
-
-       sisfb_set_disp(con, &fb_display[con].var);
-
-       /* Install new colormap */
-       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);
-
-       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)
-{
-       u8 CRData;
-
-       vgawb(CRTC_ADR, 0x17);
-       CRData = vgarb(CRTC_DATA);
-
-       if (blank > 0)          /* turn off CRT1 */
-               CRData &= 0x7f;
-       else                    /* turn on CRT1 */
-               CRData |= 0x80;
-
-       vgawb(CRTC_ADR, 0x17);
-       vgawb(CRTC_DATA, CRData);
-}
-
-int __init sisfb_init(void)
-{
-       struct pci_dev *pdev = NULL;
-       struct board *b;
-       int pdev_valid = 0;
-       unsigned char jTemp;
-
-       outb(0x77, 0x80);
-
-       if (sisfb_off)
-               return -ENXIO;
-
-       pci_for_each_dev(pdev) {
-               for (b = dev_list; b->vendor; b++) 
-               {
-                       if ((b->vendor == pdev->vendor)
-                           && (b->device == pdev->device)) 
-                       {
-                               pdev_valid = 1;
-                               strcpy(fb_info.modename, b->name);
-                               ivideo.chip_id = pdev->device;
-                               break;
-                       }
-               }
-
-               if (pdev_valid)
-                       break;
-       }
-
-       if (!pdev_valid)
-               return -1;
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-       if (pci_enable_device(pdev))
-               return -EIO;
-#endif
-
-       ivideo.video_base = pci_resource_start(pdev, 0);
-       if (!request_mem_region(ivideo.video_base, pci_resource_len(pdev, 0),
-                               "sisfb FB")) {
-               printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
-               return -ENODEV;
-       }
-       ivideo.mmio_base = pci_resource_start(pdev, 1);
-       if (!request_mem_region(ivideo.mmio_base, pci_resource_len(pdev, 1),
-                               "sisfb MMIO")) {
-               printk(KERN_ERR "sisfb: cannot reserve MMIO region\n");
-               release_mem_region(pci_resource_start(pdev, 1), 
-                                  pci_resource_len(pdev, 1));
-               return -ENODEV;
-       }
-       ivideo.vga_base = pci_resource_start(pdev, 2);
-       if (!request_region(ivideo.vga_base, pci_resource_len(pdev, 2),
-                           "sisfb IO")) {
-               printk(KERN_ERR "sisfb: cannot reserve I/O ports\n");
-               release_mem_region(pci_resource_start(pdev, 1),
-                                  pci_resource_len(pdev, 1));
-               release_mem_region(pci_resource_start(pdev, 0),
-                                  pci_resource_len(pdev, 0));
-               return -ENODEV;
-       }
-       ivideo.vga_base += 0x30;
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       rom_base = 0x000C0000;
-       request_region(rom_base, 32, "sisfb");
-#else
-        rom_base = 0x0;
-#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);
-
-       /* get video ram size by SR14 */
-       vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);
-       ivideo.video_size = ((int) ((vgarb(SEQ_DATA) & 0x3f) + 1) << 20);
-
-       if (mode_idx < 0)
-               mode_idx = DEFAULT_MODE;        /* 0:640x480x8 */
-
-#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;
-
-       if (ivideo.refresh_rate != 0)
-               search_refresh_rate(ivideo.refresh_rate);
-
-       if (rate_idx == 0) {
-               rate_idx = sisbios_mode[mode_idx].rate_idx;
-               /* set to default refresh rate 60MHz */
-               ivideo.refresh_rate = 60;
-       }
-
-       ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
-       ivideo.video_width = sisbios_mode[mode_idx].xres;
-       ivideo.video_height = sisbios_mode[mode_idx].yres;
-       video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
-
-       ivideo.video_vbase = ioremap(ivideo.video_base, ivideo.video_size);
-       ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);
-
-#ifndef CONFIG_FB_SIS_LINUXBIOS
-       rom_vbase = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);
-#endif
-
-       SiSInit300(); 
-
-       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);
-
-       pre_setmode();
-
-       if (SiSSetMode(mode_no)) {
-               DPRINTK("sisfb: set mode[0x%x]: failed\n", 0x30);
-               return -1;
-       }
-
-       post_setmode();
-
-       crtc_to_var(&default_var);
-
-       fb_info.changevar = NULL;
-       fb_info.node = -1;
-       fb_info.fbops = &sisfb_ops;
-       fb_info.disp = &disp;
-       fb_info.switch_con = &sisfb_switch;
-       fb_info.updatevar = &sisfb_update_var;
-       fb_info.blank = &sisfb_blank;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
-
-       sisfb_set_disp(-1, &default_var);
-
-       if (sisfb_heap_init()) {
-               DPRINTK("sisfb: Failed to enable offscreen heap\n");
-       }
-
-       /* to avoid the inversed bgcolor bug of the initial state */
-       vc_resize_con(1, 1, 0);
-
-       if (register_framebuffer(&fb_info) < 0)
-               return -EINVAL;
-
-       ivideo.status = CRT1;
-
-       printk(KERN_INFO "fb%d: %s frame buffer device\n",
-              GET_FB_IDX(fb_info.node), fb_info.modename);
-
-       return 0;
-}
-
-#ifdef MODULE
-
-static char *mode = NULL;
-static unsigned int rate = 0;
-
-MODULE_PARM(mode, "s");
-MODULE_PARM(rate, "i");
-
-int init_module(void)
-{
-       if (mode)
-               search_mode(mode);
-
-       ivideo.refresh_rate = rate;
-
-       sisfb_init();
-
-       return 0;
-}
-
-void cleanup_module(void)
-{
-       unregister_framebuffer(&fb_info);
-}
-#endif                         /* MODULE */
-
-
-EXPORT_SYMBOL(sis_malloc);
-EXPORT_SYMBOL(sis_free);
-
-EXPORT_SYMBOL(ivideo);
index d728d2166d308d3b1f4f9122cb97fb0b68affa17..53380d06796f9b1d41c34f5c36a824c229ebdd17 100644 (file)
@@ -117,6 +117,7 @@ if [ "$CONFIG_NET" = "y" ]; then
 else
    # for fs/nls/Config.in
    define_bool CONFIG_NCPFS_NLS n
+   define_bool CONFIG_SMB_FS n
 fi
 
 mainmenu_option next_comment
index f7e78a75d55c77f7d64692f3048bc4c434f81c78..b125dee4e855f117ee3560fea60469e70f291acd 100644 (file)
@@ -20,7 +20,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
 {
        struct buffer_head *bh;
        struct inode *inode = (struct inode*)page->mapping->host;
-       char *link = (char*)kmap(page);
+       char *link = kmap(page);
        struct slink_front *lf;
        int err;
        int                      i, j;
index 4de38a0e486979ef30a8a401ade81724bd51a112..5bbef41fc5e14d2db2e2dc81c409489f518e19c7 100644 (file)
@@ -1470,7 +1470,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
        int err = 0;
        unsigned blocksize, bbits;
        struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;
-       char *kaddr = (char *)kmap(page);
+       char *kaddr = kmap(page);
 
        blocksize = inode->i_sb->s_blocksize;
        if (!page->buffers)
@@ -1585,7 +1585,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
        unsigned long iblock, lblock;
        struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
        unsigned int blocksize, blocks;
-       unsigned long kaddr = 0;
+       char *kaddr = NULL;
        int nr, i;
 
        if (!PageLocked(page))
@@ -1614,7 +1614,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
                        if (!buffer_mapped(bh)) {
                                if (!kaddr)
                                        kaddr = kmap(page);
-                               memset((char *)(kaddr + i*blocksize), 0, blocksize);
+                               memset(kaddr + i*blocksize, 0, blocksize);
                                flush_dcache_page(page);
                                set_bit(BH_Uptodate, &bh->b_state);
                                continue;
@@ -1818,7 +1818,7 @@ int block_truncate_page(struct address_space *mapping, loff_t from, get_block_t
                        goto unlock;
        }
 
-       memset((char *) kmap(page) + offset, 0, length);
+       memset(kmap(page) + offset, 0, length);
        flush_dcache_page(page);
        kunmap(page);
 
index dbdc946f4c53a3df66d67c8c99e9799d3835eb56..2df6cf719f4b0bc69984de1217f988064bb394b0 100644 (file)
@@ -28,7 +28,7 @@ static int coda_symlink_filler(struct file *file, struct page *page)
        int error;
        struct coda_inode_info *cnp;
        unsigned int len = PAGE_SIZE;
-       char *p = (char*)kmap(page);
+       char *p = kmap(page);
 
        lock_kernel();
         cnp = ITOC(inode);
index 90fd86b06dd36fa138826b51e047e72085d50fda..5711e6b4175207ba547d7c03ac57ff2170766ca8 100644 (file)
@@ -103,14 +103,14 @@ void __inode_dir_notify(struct inode *inode, unsigned long event)
        write_lock(&dn_lock);
        prev = &inode->i_dnotify;
        while ((dn = *prev) != NULL) {
-               if ((dn->dn_mask & event) == 0) {
-                       prev = &dn->dn_next;
-                       continue;
-               }
                if (dn->dn_magic != DNOTIFY_MAGIC) {
                        printk(KERN_ERR "__inode_dir_notify: bad magic "
                                "number in dnotify_struct!\n");
-                       return;
+                       goto out;
+               }
+               if ((dn->dn_mask & event) == 0) {
+                       prev = &dn->dn_next;
+                       continue;
                }
                fown = &dn->dn_filp->f_owner;
                if (fown->pid)
@@ -125,6 +125,7 @@ void __inode_dir_notify(struct inode *inode, unsigned long event)
        }
        if (changed)
                redo_inode_mask(inode);
+out:
        write_unlock(&dn_lock);
 }
 
index 20840409d16ccf3d132b72e4435e100a62f259e6..d1c788cc29a344367a21f499ad7329a2d9da3a9a 100644 (file)
@@ -13,7 +13,7 @@
 
 static int efs_symlink_readpage(struct file *file, struct page *page)
 {
-       char *link = (char*)kmap(page);
+       char *link = kmap(page);
        struct buffer_head * bh;
        struct inode * inode = (struct inode*)page->mapping->host;
        efs_block_t size = inode->i_size;
index 203100d33743d81e0cf870082dc500f2e6459fdf..1e24a4aceb82678dfed3f6c5286774ed46e68b92 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -212,7 +212,7 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm)
                                        return -ENOMEM;
                                new = 1;
                        }
-                       kaddr = (char *)kmap(page);
+                       kaddr = kmap(page);
 
                        if (new && offset)
                                memset(kaddr, 0, offset);
@@ -748,7 +748,7 @@ void remove_arg_zero(struct linux_binprm *bprm)
                        kunmap(page);
 inside:
                        page = bprm->page[bprm->p/PAGE_SIZE];
-                       kaddr = (char *)kmap(page);
+                       kaddr = kmap(page);
                }
                kunmap(page);
                bprm->argc--;
index 3438cdb853f9c4b3fbb5c4d0a05761cdc00dd7a4..0d38b408c9da03af8a59f46eb4c7b6f1cc2597c5 100644 (file)
@@ -401,7 +401,7 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 
 int hpfs_symlink_readpage(struct file *file, struct page *page)
 {
-       char *link = (char*)kmap(page);
+       char *link = kmap(page);
        struct inode *i = (struct inode*)page->mapping->host;
        struct fnode *fnode;
        struct buffer_head *bh;
index 1a7cbe374a5dd65a79dbe7ca3af2213e5622fe63..b2eff877f570d43d0dca6d3320a75a411043eb9a 100644 (file)
@@ -449,7 +449,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr)
 static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = (struct inode*)page->mapping->host;
-       char *link = (char*)kmap(page);
+       char *link = kmap(page);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
        struct buffer_head *bh;
index c22fc2ec31ca7948a254c26475bdda0226f779c3..026dc7e1039bd0ee18d1880e88054270bd87898b 100644 (file)
@@ -1949,7 +1949,7 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
        if (!Page_Uptodate(page))
                goto async_fail;
        *ppage = page;
-       return (char*) kmap(page);
+       return kmap(page);
 
 async_fail:
        page_cache_release(page);
index eda3fe6af4214bd765f1dfc798493e3067b67f71..a187b119919b67fc99c2d599c1fb90a8d6254993 100644 (file)
@@ -462,7 +462,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (!page)
                goto read_really;
 
-       ctl.cache = cache = (union ncp_dir_cache *) kmap(page);
+       ctl.cache = cache = kmap(page);
        ctl.head  = cache->head;
 
        if (!Page_Uptodate(page) || !ctl.head.eof)
@@ -490,7 +490,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
                        if (!ctl.page)
                                goto invalid_cache;
-                       ctl.cache = (union ncp_dir_cache *) kmap(ctl.page);
+                       ctl.cache = kmap(ctl.page);
                        if (!Page_Uptodate(ctl.page))
                                goto invalid_cache;
                }
@@ -635,7 +635,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
                ctl.ofs  += 1;
                ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
                if (ctl.page)
-                       ctl.cache = (union ncp_dir_cache *) kmap(ctl.page);
+                       ctl.cache = kmap(ctl.page);
        }
        if (ctl.cache) {
                ctl.cache->dentry[ctl.idx] = newdent;
index 0962593daf5b169f2b373b97dbd74aa1f67f5713..022cbce783fb4ab2d26e8a9261694238fc4ae2ff 100644 (file)
@@ -48,7 +48,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
        struct inode *inode = (struct inode*)page->mapping->host;
        int error, length, len, cnt;
        char *link;
-       char *buf = (char*)kmap(page);
+       char *buf = kmap(page);
 
        error = -ENOMEM;
        for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
index 3f6b770aacc7c56fd28ce81cfbd63bf5256c454c..c66d870d9f22cb480e48f99f13efd857bf18ea80 100644 (file)
@@ -97,7 +97,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 {
        struct file     *file = desc->file;
        struct inode    *inode = file->f_dentry->d_inode;
-       void            *buffer = (void *)kmap(page);
+       void            *buffer = kmap(page);
        int             plus = NFS_USE_READDIRPLUS(inode);
        int             error;
 
@@ -145,7 +145,7 @@ static inline
 int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
 {
        struct nfs_entry *entry = desc->entry;
-       char            *start = (char *)kmap(page),
+       char            *start = kmap(page),
                        *p = start;
        int             loop_count = 0,
                        status = 0;
@@ -251,7 +251,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
 {
        struct file     *file = desc->file;
        struct nfs_entry *entry = desc->entry;
-       char            *start = (char *)kmap(desc->page),
+       char            *start = kmap(desc->page),
                        *p = start + desc->page_offset;
        unsigned long   fileid;
        int             loop_count = 0,
@@ -323,7 +323,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                status = -ENOMEM;
                goto out;
        }
-       p = (u32 *)kmap(page);
+       p = kmap(page);
        status = NFS_PROTO(inode)->readdir(file, desc->target, p,
                                           NFS_SERVER(inode)->dtsize, 0);
        if (status >= 0) {
index 7c1aad253e0942363828152637d8a79743787e64..76fc2f437bb15f22c1dddd4587614e61340af78f 100644 (file)
@@ -101,7 +101,7 @@ nfs_readpage_sync(struct file *file, struct page *page)
         * This works now because the socket layer never tries to DMA
         * into this buffer directly.
         */
-       buffer = (char *) kmap(page);
+       buffer = kmap(page);
        do {
                if (count < rsize)
                        rsize = count;
@@ -257,7 +257,7 @@ nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
                struct nfs_page *req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
                nfs_list_add_request(req, &data->pages);
-               iov->iov_base = (void *)(kmap(req->wb_page) + req->wb_offset);
+               iov->iov_base = kmap(req->wb_page) + req->wb_offset;
                iov->iov_len = req->wb_bytes;
                count += req->wb_bytes;
                iov++;
index 4c9c45e2aa6c0b3ed3262f4019841c9ed1955182..4960526b4705b63724eaa84a101ea79400d0ff74 100644 (file)
@@ -30,7 +30,7 @@
 static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
 {
        struct inode *inode = dentry->d_inode;
-       void *buffer = (void *)kmap(page);
+       void *buffer = kmap(page);
        int error;
 
        /* We place the length at the beginning of the page,
@@ -69,7 +69,7 @@ static char *nfs_getlink(struct dentry *dentry, struct page **ppage)
        if (!Page_Uptodate(page))
                goto getlink_read_error;
        *ppage = page;
-       p = (u32 *) kmap(page);
+       p = kmap(page);
        return (char*)(p+1);
                
 getlink_read_error:
index 5346e63028d6d3050c8b017f1c946ba78441fa9a..55c915ee367d76862c204c26490200e7a74245ed 100644 (file)
@@ -184,7 +184,7 @@ nfs_writepage_sync(struct file *file, struct page *page,
                dentry->d_parent->d_name.name, dentry->d_name.name,
                count, (long long)(page_offset(page) + offset));
 
-       buffer = (u8 *) kmap(page) + offset;
+       buffer = kmap(page) + offset;
        base = page_offset(page) + offset;
 
        flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC;
@@ -1065,7 +1065,7 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
                struct nfs_page *req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
                nfs_list_add_request(req, &data->pages);
-               iov->iov_base = (void *)(kmap(req->wb_page) + req->wb_offset);
+               iov->iov_base = kmap(req->wb_page) + req->wb_offset;
                iov->iov_len = req->wb_bytes;
                count += req->wb_bytes;
                iov++;
index a1f7efe0f75ba137f2a4cb239760c21371c34881..25fa7bdbc4d2b6bc04d0035247325f9c6b19a93e 100644 (file)
@@ -207,15 +207,12 @@ static int standard_permission(struct inode *inode, int mask)
        return -EACCES;
 }
 
-static int proc_permission(struct inode *inode, int mask)
+static int proc_check_root(struct inode *inode)
 {
        struct dentry *de, *base, *root;
        struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
        int res = 0;
 
-       if (standard_permission(inode, mask) != 0)
-               return -EACCES;
-
        if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
                return -ENOENT;
        read_lock(&current->fs->lock);
@@ -250,6 +247,13 @@ out:
        goto exit;
 }
 
+static int proc_permission(struct inode *inode, int mask)
+{
+       if (standard_permission(inode, mask) != 0)
+               return -EACCES;
+       return proc_check_root(inode);
+}
+
 static ssize_t pid_maps_read(struct file * file, char * buf,
                              size_t count, loff_t *ppos)
 {
@@ -403,12 +407,14 @@ static struct inode_operations proc_mem_inode_operations = {
 static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
-       int error;
+       int error = -EACCES;
 
        /* We don't need a base pointer in the /proc filesystem */
        path_release(nd);
 
-       error = proc_permission(inode, MAY_EXEC);
+       if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE))
+               goto out;
+       error = proc_check_root(inode);
        if (error)
                goto out;
 
@@ -441,12 +447,14 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
 
 static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen)
 {
-       int error;
+       int error = -EACCES;
        struct inode *inode = dentry->d_inode;
        struct dentry *de;
        struct vfsmount *mnt = NULL;
 
-       error = proc_permission(inode, MAY_EXEC);
+       if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE))
+               goto out;
+       error = proc_check_root(inode);
        if (error)
                goto out;
 
index f13ba4f3d4f4a42d50411103415a63a7bd4cddde..7d53485b8d1510929579481b8ac91f4034723a2e 100644 (file)
@@ -65,7 +65,8 @@ static struct dentry * ramfs_lookup(struct inode *dir, struct dentry *dentry)
 static int ramfs_readpage(struct file *file, struct page * page)
 {
        if (!Page_Uptodate(page)) {
-               memset(page_address(page), 0, PAGE_CACHE_SIZE);
+               memset(kmap(page), 0, PAGE_CACHE_SIZE);
+               kunmap(page);
                flush_dcache_page(page);
                SetPageUptodate(page);
        }
@@ -85,9 +86,7 @@ static int ramfs_writepage(struct file *file, struct page *page)
 
 static int ramfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
-       void *addr;
-
-       addr = (void *) kmap(page);
+       void *addr = kmap(page);
        if (!Page_Uptodate(page)) {
                memset(addr, 0, PAGE_CACHE_SIZE);
                flush_dcache_page(page);
index 0b42c2387dc7288eaf8ea359739d3d73a9664e01..aa85680ace1e149a3000e9823a3c290d6c53eada 100644 (file)
@@ -47,11 +47,11 @@ smb_get_dircache(struct dentry * dentry)
                page = grab_cache_page(mapping, 0);
                if (!page)
                        goto out;
-               cachep = (struct cache_head *)kmap(page);
+               cachep = kmap(page);
                memset((char*)cachep, 0, PAGE_SIZE);
                goto out;
        }
-       cachep = (struct cache_head *)kmap(page);
+       cachep = kmap(page);
        if (cachep->valid) {
                /*
                 * OK, at least the page 0 survived and seems to be promising.
@@ -69,7 +69,7 @@ smb_get_dircache(struct dentry * dentry)
                                cachep->valid = 0;
                                goto out;
                        }
-                       index->block = (struct cache_block *) kmap(page);
+                       index->block = kmap(page);
                }
        }
 out:
@@ -188,7 +188,7 @@ get_block:
        page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT);
        page = grab_cache_page(mapping, page_off>>PAGE_CACHE_SHIFT);
        if (page) {
-               block = (struct cache_block *)kmap(page);
+               block = kmap(page);
                index->block = block;
                index->space = PAGE_SIZE;
                goto add_entry;
index 9ba4a6641f0d6f06dd12bcb0bd3aa3a2e42654d7..7e8ac9b7d825d72eeca12a70967cd5be53a7a60e 100644 (file)
@@ -54,7 +54,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
        if (!PageLocked(page))
                PAGE_BUG(page);
 
-       kaddr = (char *)kmap(page);
+       kaddr = kmap(page);
        memset(kaddr, 0, PAGE_CACHE_SIZE);
        block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
        bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize);
@@ -78,7 +78,7 @@ static int udf_adinicb_writepage(struct file *file, struct page *page)
        if (!PageLocked(page))
                PAGE_BUG(page);
 
-       kaddr = (char *)kmap(page);
+       kaddr = kmap(page);
        block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
        bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize);
        memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
index 8a0dde5e41309e973728ad31bae21838dd723b2f..547fc784b8514ae1db67673e2d41a8fd2c889801 100644 (file)
@@ -83,7 +83,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        struct buffer_head *bh = NULL;
        char *symlink;
        int err = -EIO;
-       char *p = (char *)kmap(page);
+       char *p = kmap(page);
        
        lock_kernel();
        if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
index 63ee81b165e01048eac6572fafd042b65eb45492..2e0b7bb147673fe573816f3cf04b1db5531f930d 100644 (file)
@@ -700,7 +700,7 @@ struct dentry *umsdos_solve_hlink (struct dentry *hlink)
        path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
        if (path == NULL)
                goto out_release;
-       memcpy(path, (char*)kmap(page), hlink->d_inode->i_size);
+       memcpy(path, kmap(page), hlink->d_inode->i_size);
        kunmap(page);
        page_cache_release(page);
 
index 551c9662fb150e3f62954d7484c2381ce7df23c7..93c6af317015151445740c8be508e537a06ec617 100644 (file)
@@ -129,7 +129,7 @@ int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_di
        wait_on_page(page);
        if (!Page_Uptodate(page))
                goto async_fail;
-       p = (struct umsdos_dirent*)((char*)kmap(page)+offs);
+       p = (struct umsdos_dirent*)(kmap(page)+offs);
 
        /* if this is an invalid entry (invalid name length), ignore it */
        if( p->name_len > UMSDOS_MAXNAME )
@@ -158,7 +158,7 @@ int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_di
                        goto async_fail;
                }
                memcpy(entry->spare,p->spare,part);
-               memcpy(entry->spare+part,(char*)kmap(page2),
+               memcpy(entry->spare+part,kmap(page2),
                                recsize+offs-PAGE_CACHE_SIZE);
                kunmap(page2);
                page_cache_release(page2);
@@ -399,7 +399,7 @@ static int umsdos_find (struct dentry *demd, struct umsdos_info *info)
                        wait_on_page(page);
                        if (!Page_Uptodate(page))
                                goto async_fail;
-                       p = (char*)kmap(page);
+                       p = kmap(page);
                }
 
                rentry = (struct umsdos_dirent *)(p+offs);
@@ -451,7 +451,7 @@ static int umsdos_find (struct dentry *demd, struct umsdos_info *info)
                                page = next_page;
                                goto async_fail;
                        }
-                       q = (char*)kmap(next_page);
+                       q = kmap(next_page);
                        if (memcmp(entry->name, rentry->name, len) ||
                            memcmp(entry->name+len, q, entry->name_len-len)) {
                                kunmap(next_page);
index d6a26eb247a9a59f804517b0b14c6174e7ab606d..af39a19f1c775b5a27168e820c38e1c59fca1c17 100644 (file)
@@ -27,4 +27,8 @@
 
 #define MAXHOSTNAMELEN 64      /* max length of hostname */
 
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC        HZ      /* frequency at which times() counts */
+#endif
+
 #endif /* _ASM_ALPHA_PARAM_H */
index 8370b7eb6002cdb92df069577c4b24ad8e70b69e..dfff7fad02a355c93093ba634a1c9ef128081f26 100644 (file)
@@ -53,19 +53,19 @@ extern void kmap_init(void) __init;
 #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
-extern unsigned long FASTCALL(kmap_high(struct page *page));
+extern void * FASTCALL(kmap_high(struct page *page));
 extern void FASTCALL(kunmap_high(struct page *page));
 
-extern inline unsigned long kmap(struct page *page)
+static inline void *kmap(struct page *page)
 {
        if (in_interrupt())
                BUG();
        if (page < highmem_start_page)
-               return (unsigned long) page_address(page);
+               return page_address(page);
        return kmap_high(page);
 }
 
-extern inline void kunmap(struct page *page)
+static inline void kunmap(struct page *page)
 {
        if (in_interrupt())
                BUG();
@@ -80,13 +80,13 @@ extern inline void kunmap(struct page *page)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
+static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
        enum fixed_addresses idx;
        unsigned long vaddr;
 
        if (page < highmem_start_page)
-               return (unsigned long) page_address(page);
+               return page_address(page);
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
@@ -97,12 +97,13 @@ extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
        set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
        __flush_tlb_one(vaddr);
 
-       return vaddr;
+       return (void*) vaddr;
 }
 
-extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type)
+static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 {
 #if HIGHMEM_DEBUG
+       unsigned long vaddr = (unsigned long) kvaddr;
        enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
        if (vaddr < FIXADDR_START) // FIXME
index 428a59d1c6c99ce4364294c92ff6c25baacb97dc..38114e564f6b30ed0f3935547910d1d5828e7b38 100644 (file)
@@ -49,19 +49,19 @@ extern void kmap_init(void) __init;
 
 #define KMAP_FIX_BEGIN (0xfe400000UL)
 
-extern unsigned long kmap_high(struct page *page);
+extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
 
-extern inline unsigned long kmap(struct page *page)
+static inline void *kmap(struct page *page)
 {
        if (in_interrupt())
                BUG();
        if (page < highmem_start_page)
-               return (unsigned long) page_address(page);
+               return page_address(page);
        return kmap_high(page);
 }
 
-extern inline void kunmap(struct page *page)
+static inline void kunmap(struct page *page)
 {
        if (in_interrupt())
                BUG();
@@ -76,13 +76,13 @@ extern inline void kunmap(struct page *page)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
+static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
        unsigned int idx;
        unsigned long vaddr;
 
        if (page < highmem_start_page)
-               return (unsigned long) page_address(page);
+               return page_address(page);
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = KMAP_FIX_BEGIN + idx * PAGE_SIZE;
@@ -93,12 +93,13 @@ extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
        set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
        flush_hash_page(0, vaddr);
 
-       return vaddr;
+       return (void*) vaddr;
 }
 
-extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type)
+static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 {
 #if HIGHMEM_DEBUG
+       unsigned long vaddr = (unsigned long) kvaddr;
        unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
 
        if (vaddr < KMAP_FIX_BEGIN) // FIXME
index d1b967a007d5a4947e710e5472fe4a0f40a3a428..ad4a8457161e03a9c3f96eb37cb6429e70e484bb 100644 (file)
 # define BPP_GP_Select 0x0800
 # define BPP_GP_nFault 0x1000
 
-
-/*
- * Prototype for the initialization routine.
- */
-
-#ifdef __KERNEL__
-extern int bpp_init(void);
-#endif
-
 #endif
index 0724061e4cdedd959b112fbe87736ec48bd4fbea..179f1a3cbd95c891116fb4b2a9bc00f856b2c6a4 100644 (file)
@@ -49,19 +49,19 @@ extern void kmap_init(void) __init;
 #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
-extern unsigned long kmap_high(struct page *page);
+extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
 
-extern inline unsigned long kmap(struct page *page)
+static inline void *kmap(struct page *page)
 {
        if (in_interrupt())
                BUG();
        if (page < highmem_start_page)
-               return (unsigned long) page_address(page);
+               return page_address(page);
        return kmap_high(page);
 }
 
-extern inline void kunmap(struct page *page)
+static inline void kunmap(struct page *page)
 {
        if (in_interrupt())
                BUG();
@@ -76,13 +76,13 @@ extern inline void kunmap(struct page *page)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
+static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
        unsigned long idx;
        unsigned long vaddr;
 
        if (page < highmem_start_page)
-               return (unsigned long) page_address(page);
+               return page_address(page);
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = FIX_KMAP_BEGIN + idx * PAGE_SIZE;
@@ -106,12 +106,13 @@ extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
        flush_tlb_all();
 #endif
 
-       return vaddr;
+       return (void*) vaddr;
 }
 
-extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type)
+static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 {
 #if HIGHMEM_DEBUG
+       unsigned long vaddr = (unsigned long) kvaddr;
        unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
 
 #if 0
index bebb788ac753ffec4addee3734868eaeb03d3d2a..6e32823ab4e2753939815496293ad5e6aac0dbaf 100644 (file)
@@ -64,11 +64,5 @@ struct opiocdesc
 #define        OPIOCGETNEXT    _IOWR('O', 5, int)
 #define        OPIOCGETCHILD   _IOWR('O', 6, int)
 
-
-#ifdef __KERNEL__
-int openprom_init(void);
-#endif
-
-
 #endif /* _SPARC_OPENPROMIO_H */
 
index c2add3bd75b19753da8487ed2f6e9dfdf2be4a0a..020b68fbbb55523ab0347a31b58d4ae3d179e91f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.105 2000/10/30 21:01:41 davem Exp $ */
+/* $Id: pgtable.h,v 1.106 2000/11/08 04:49:24 davem Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
index 4b36c92092b075e105397598ac933baf5040e2f4..eb86015ee63881cac0367104f9029cce6c6ffdad 100644 (file)
 # define BPP_GP_Select 0x0800
 # define BPP_GP_nFault 0x1000
 
-
-/*
- * Prototype for the initialization routine.
- */
-
-#ifdef __KERNEL__
-extern int bpp_init(void);
-#endif
-
 #endif
index e16de8fb2bace794492ebae42533e5d7e984d861..53a6653815eb40808606baa72102dbda30557be4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: envctrl.h,v 1.2 2000/10/17 16:20:36 davem Exp $
+/* $Id: envctrl.h,v 1.3 2000/11/03 00:37:40 davem Exp $
  *
  * envctrl.h: Definitions for access to the i2c environment
  *            monitoring on Ultrasparc systems.
@@ -54,6 +54,8 @@
 #define ENVCTRL_RD_ETHERNET_TEMPERATURE        _IOR('p', 0x47, int)
 #define ENVCTRL_RD_MTHRBD_TEMPERATURE  _IOR('p', 0x48, int)
 
+#define ENVCTRL_RD_GLOBALADDRESS       _IOR('p', 0x49, int)
+
 /* Read return values for a voltage status request. */
 #define ENVCTRL_VOLTAGE_POWERSUPPLY_GOOD       0x01
 #define ENVCTRL_VOLTAGE_BAD                    0x02
index 99fe7c780903e12737dd76d12776ea70919a92cf..f44977ec81d133000fbc575f519d4d78a89209b8 100644 (file)
@@ -6,6 +6,6 @@
 
 extern void * module_map (unsigned long size);
 extern void module_unmap (void *addr);
-#define module_arch_init (x)   (0)
+#define module_arch_init(x)    (0)
 
 #endif /* _ASM_SPARC64_MODULE_H */
index 37420b761c59cf4c86e1d7a4d3d5cd2269a48db1..555b3b5b115f38b753bde61617d4988b94d313a0 100644 (file)
@@ -64,11 +64,5 @@ struct opiocdesc
 #define        OPIOCGETNEXT    _IOWR('O', 5, int)
 #define        OPIOCGETCHILD   _IOWR('O', 6, int)
 
-
-#ifdef __KERNEL__
-int openprom_init(void);
-#endif
-
-
 #endif /* _SPARC64_OPENPROMIO_H */
 
index be3dde29ca684cdb67a13fb4e84cfc8b3edb17a9..23603f287510fe5a4a2ce118770ede25e0b54742 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id */
+/* $Id: pgalloc.h,v 1.13 2000/11/06 06:59:04 davem Exp $ */
 #ifndef _SPARC64_PGALLOC_H
 #define _SPARC64_PGALLOC_H
 
 /* These operations are unnecessary on the SpitFire since D-CACHE is write-through. */
 #define flush_icache_range(start, end)         do { } while (0)
 #define flush_page_to_ram(page)                        do { } while (0)
-extern void __flush_dcache_page(void *addr);
-#define flush_dcache_page(page)        __flush_dcache_page((page)->virtual)
+
+extern void __flush_dcache_page(void *addr, int flush_icache);
+#define flush_dcache_page(page) \
+do {   if ((page)->mapping && !(page)->mapping->i_mmap && !(page)->mapping->i_mmap_shared) \
+               set_bit(PG_dcache_dirty, &(page)->flags); \
+       else \
+               __flush_dcache_page((page)->virtual, \
+                                   (page)->mapping != NULL); \
+} while(0)
 
 extern void __flush_dcache_range(unsigned long start, unsigned long end);
 
index 41fdc35e3a018d91c000f740a1e0e1f4f2ddc519..a010423462aa165e936433e136d00b5d696c2c09 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.132 2000/10/19 00:50:16 davem Exp $
+/* $Id: pgtable.h,v 1.135 2000/11/08 04:49:24 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -19,6 +19,8 @@
 
 #ifndef __ASSEMBLY__
 
+#define PG_dcache_dirty                PG_arch_1
+
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
@@ -233,7 +235,7 @@ extern pgd_t swapper_pg_dir[1];
 #define mmu_lockarea(vaddr, len)               (vaddr)
 #define mmu_unlockarea(vaddr, len)             do { } while(0)
 
-extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte);
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
 
 #define flush_icache_page(vma, pg)     do { } while(0)
 
index 66bbdcf606e77c2d37a13dc935c61dff77d0646c..eb4d603e7530098e99cb8c3f89c365d0352b904d 100644 (file)
@@ -115,7 +115,6 @@ void end_that_request_last(struct request *req);
 
 /* ram disk */
 #define DEVICE_NAME "ramdisk"
-#define DEVICE_REQUEST rd_request
 #define DEVICE_NR(device) (MINOR(device))
 #define DEVICE_NO_RANDOM
 
index fa8f9cded5ef43213ac852c62a6898ac67fa3342..357878b650490ef606a14e4994a85d383f0b2d8f 100644 (file)
@@ -29,6 +29,9 @@
 #define FBIO_FREE               0x4614
 #define FBIOGET_GLYPH           0x4615
 #define FBIOGET_HWCINFO         0x4616
+#define FBIOPUT_MODEINFO        0x4617
+#define FBIOGET_DISPINFO        0x4618
+
 
 #define FB_TYPE_PACKED_PIXELS          0       /* Packed Pixels        */
 #define FB_TYPE_PLANES                 1       /* Non interleaved planes */
index 184407e40ca22a7258ce55c95a05111d6a032c41..88dc7d7f538b7735bda365178e5c5be2fd3f7a5d 100644 (file)
@@ -23,9 +23,7 @@ static inline unsigned int nr_free_highpages(void) { return 0; }
 #define prepare_highmem_swapout(page) page
 #define replace_with_highmem(page) page
 
-static __inline__ unsigned long kmap(struct page * page) {
-       return (unsigned long) page_address(page);
-}
+static inline void *kmap(struct page *page) { return page_address(page); }
 
 #define kunmap(page) do { } while (0)
 
@@ -37,30 +35,24 @@ static __inline__ unsigned long kmap(struct page * page) {
 /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
 static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-       unsigned long kaddr;
-
-       kaddr = kmap(page);
-       clear_user_page((void *)kaddr, vaddr);
+       clear_user_page(kmap(page), vaddr);
        kunmap(page);
 }
 
 static inline void clear_highpage(struct page *page)
 {
-       unsigned long kaddr;
-
-       kaddr = kmap(page);
-       clear_page((void *)kaddr);
+       clear_page(kmap(page));
        kunmap(page);
 }
 
 static inline void memclear_highpage(struct page *page, unsigned int offset, unsigned int size)
 {
-       unsigned long kaddr;
+       char *kaddr;
 
        if (offset + size > PAGE_SIZE)
                BUG();
        kaddr = kmap(page);
-       memset((void *)(kaddr + offset), 0, size);
+       memset(kaddr + offset, 0, size);
        kunmap(page);
 }
 
@@ -69,34 +61,34 @@ static inline void memclear_highpage(struct page *page, unsigned int offset, uns
  */
 static inline void memclear_highpage_flush(struct page *page, unsigned int offset, unsigned int size)
 {
-       unsigned long kaddr;
+       char *kaddr;
 
        if (offset + size > PAGE_SIZE)
                BUG();
        kaddr = kmap(page);
-       memset((void *)(kaddr + offset), 0, size);
+       memset(kaddr + offset, 0, size);
        flush_page_to_ram(page);
        kunmap(page);
 }
 
 static inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr)
 {
-       unsigned long vfrom, vto;
+       char *vfrom, *vto;
 
        vfrom = kmap(from);
        vto = kmap(to);
-       copy_user_page((void *)vto, (void *)vfrom, vaddr);
+       copy_user_page(vto, vfrom, vaddr);
        kunmap(from);
        kunmap(to);
 }
 
 static inline void copy_highpage(struct page *to, struct page *from)
 {
-       unsigned long vfrom, vto;
+       char *vfrom, *vto;
 
        vfrom = kmap(from);
        vto = kmap(to);
-       copy_page((void *)vto, (void *)vfrom);
+       copy_page(vto, vfrom);
        kunmap(from);
        kunmap(to);
 }
index 59355eb8aa49b4eb815af2cd68bb0e684f0a2235..8713dfd2982f2a8dae73c55563c18d1c57b8d84b 100644 (file)
@@ -181,7 +181,8 @@ typedef struct page {
 #define PG_skip                        10
 #define PG_inactive_clean      11
 #define PG_highmem             12
-                               /* bits 21-30 unused */
+                               /* bits 21-29 unused */
+#define PG_arch_1              30
 #define PG_reserved            31
 
 
@@ -328,6 +329,10 @@ typedef struct page {
  * parts of the address space.
  *
  * PG_error is set to indicate that an I/O error occurred on this page.
+ *
+ * PG_arch_1 is an architecture specific page state bit.  The generic
+ * code guarentees that this bit is cleared for a page when it first
+ * is entered into the page cache.
  */
 
 extern mem_map_t * mem_map;
@@ -447,8 +452,6 @@ extern void truncate_inode_pages(struct address_space *, loff_t);
 
 /* generic vm_area_ops exported for stackable file systems */
 extern int filemap_swapout(struct page * page, struct file *file);
-extern pte_t filemap_swapin(struct vm_area_struct * vma,
-                           unsigned long offset, unsigned long entry);
 extern int filemap_sync(struct vm_area_struct * vma, unsigned long address,
                        size_t size, unsigned int flags);
 extern struct page *filemap_nopage(struct vm_area_struct * area,
index fbf8e78654bdff9c3d6ff9e7dffbd3d611915434..d3957292ce12bdfb0b2ea619f75f100265339cfb 100644 (file)
 #define PCI_DEVICE_ID_SI_620           0x0620
 #define PCI_DEVICE_ID_SI_630           0x0630
 #define PCI_DEVICE_ID_SI_630_VGA       0x6300
+#define PCI_DEVICE_ID_SI_730_VGA       0x7300
 #define PCI_DEVICE_ID_SI_5107          0x5107
 #define PCI_DEVICE_ID_SI_5300          0x5300
 #define PCI_DEVICE_ID_SI_5511          0x5511
index cfc8ce704f33dc40d190cdddd92e2962593d3646..2f5be64743ac336f062f8b8a8ea5dd5eb9600ba7 100644 (file)
@@ -1,17 +1,91 @@
 #ifndef _LINUX_SISFB
 #define _LINUX_SISFB
 
+/* CRT2 connection */
+#define MASK_DISPTYPE_CRT2     0x04         /* Connect CRT2 */
+#define MASK_DISPTYPE_LCD      0x02         /* Connect LCD */
+#define MASK_DISPTYPE_TV       0x01         /* Connect TV */
+#define MASK_DISPTYPE_DISP2    (MASK_DISPTYPE_LCD | MASK_DISPTYPE_TV | MASK_DISPTYPE_CRT2)
+
+#define DISPTYPE_CRT1       0x00000008L
+#define DISPTYPE_CRT2       0x00000004L
+#define DISPTYPE_LCD        0x00000002L
+#define DISPTYPE_TV         0x00000001L
+#define DISPTYPE_DISP1      DISPTYPE_CRT1
+#define DISPTYPE_DISP2      (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
+#define DISPMODE_SINGLE            0x00000020L
+#define DISPMODE_MIRROR            0x00000010L
+#define DISPMODE_DUALVIEW   0x00000040L
+
+#define HASVB_NONE             0
+#define HASVB_301              1
+#define HASVB_LVDS             2
+#define HASVB_TRUMPION         3
+#define HASVB_LVDS_CHRONTEL    4
+#define HASVB_LVDS_ALL      (HASVB_LVDS | HASVB_TRUMPION | HASVB_LVDS_CHRONTEL)
+
+enum _TVMODE
+{
+       TVMODE_NTSC = 0,
+       TVMODE_PAL,
+       TVMODE_HIVISION,
+       TVMODE_TOTAL
+};
+
+enum _TVPLUGTYPE
+{
+       TVPLUG_UNKNOWN = 0,
+       TVPLUG_COMPOSITE,
+       TVPLUG_SVIDEO,
+       TVPLUG_SCART,
+       TVPLUG_TOTAL
+};
+
+enum CHIPTYPE
+{
+       SiS_UNKNOWN = 0,
+       SiS_300,
+       SiS_540,
+       SiS_630,
+       SiS_630S,
+       SiS_730
+};
+
 struct sis_memreq
 {
     unsigned long offset;
     unsigned long size;
 };
 
+/* Data for AP */
+struct mode_info
+{
+    int    bpp;
+    int    xres;
+    int    yres;
+    int    v_xres;
+    int    v_yres;
+    int    org_x;
+    int    org_y;
+    unsigned int  vrate;
+};
+
+struct ap_data
+{
+    struct mode_info minfo;
+    unsigned long iobase;
+    unsigned int  mem_size;
+    unsigned long disp_state;          
+       enum CHIPTYPE chip;
+};
+
+
+/* Data for kernel */
 struct video_info
 {
     /* card parameters */
     int    chip_id;
-    int    video_size;
+    unsigned int  video_size;
     unsigned long video_base;
     char  *video_vbase;
     unsigned long mmio_base;
@@ -22,8 +96,17 @@ struct video_info
     int    video_bpp;
     int    video_width;
     int    video_height;
-    unsigned int  refresh_rate;
-    u8     status;
+    int    video_vwidth;
+    int    video_vheight;
+    int    org_x;
+    int    org_y;
+    unsigned int refresh_rate;
+
+    /* VB functions */
+    unsigned long disp_state;
+    unsigned char hasVB;
+    unsigned char TV_type;
+    unsigned char TV_plug;
 };
 
 #ifdef __KERNEL__
index b93b0b0e4a2fc35d3f2cddd3d4d7d4a904d2bf2d..f436a6322f2af9a6998f020434869c7f58dc83af 100644 (file)
@@ -572,9 +572,9 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
         */
        if (nr_threads >= max_threads)
                goto bad_fork_cleanup_count;
+       
+       get_exec_domain(p->exec_domain);
 
-       if (p->exec_domain && p->exec_domain->module)
-               __MOD_INC_USE_COUNT(p->exec_domain->module);
        if (p->binfmt && p->binfmt->module)
                __MOD_INC_USE_COUNT(p->binfmt->module);
 
index 1d5bbe5c236223f46d301c72bd9f2633464579aa..410f9de937bcce2d92ca747eb9a0590bc4192f07 100644 (file)
@@ -24,7 +24,7 @@ static int access_one_page(struct mm_struct * mm, struct vm_area_struct * vma, u
        pgd_t * pgdir;
        pmd_t * pgmiddle;
        pte_t * pgtable;
-       unsigned long maddr; 
+       char *maddr; 
        struct page *page;
 
 repeat:
@@ -54,13 +54,13 @@ repeat:
 
        if (write) {
                maddr = kmap(page);
-               memcpy((char *)maddr + (addr & ~PAGE_MASK), buf, len);
+               memcpy(maddr + (addr & ~PAGE_MASK), buf, len);
                flush_page_to_ram(page);
                flush_icache_page(vma, page);
                kunmap(page);
        } else {
                maddr = kmap(page);
-               memcpy(buf, (char *)maddr + (addr & ~PAGE_MASK), len);
+               memcpy(buf, maddr + (addr & ~PAGE_MASK), len);
                flush_page_to_ram(page);
                kunmap(page);
        }
index 3d7aa17d0b502f11a9b766ae7d107c68a4fdbe7e..b553eb0ff2e95c79f74610d1fe28486405c7f76e 100644 (file)
@@ -288,7 +288,7 @@ void __release_region(struct resource *parent, unsigned long start, unsigned lon
                }
                p = &res->sibling;
        }
-       printk("Trying to free nonexistent resource <%04lx-%04lx>\n", start, end);
+       printk("Trying to free nonexistent resource <%08lx-%08lx>\n", start, end);
 }
 
 /*
index 0a97edb9aa6aac481799c3bcd28820a2c539b39a..80643fdf429f76eba8daacab6c841f8736018dcc 100644 (file)
@@ -1228,7 +1228,9 @@ void daemonize(void)
        fs = init_task.fs;
        current->fs = fs;
        atomic_inc(&fs->count);
-
+       exit_files(current);
+       current->files = init_task.files;
+       atomic_inc(&current->files->count);
 }
 
 void __init init_idle(void)
index b19f4c5b33b9980ccffb3d672ead4e718a218a98..98c97b787861987f10703e14f084bd4da157591b 100644 (file)
@@ -387,7 +387,7 @@ static inline void __add_to_page_cache(struct page * page,
        if (PageLocked(page))
                BUG();
 
-       flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced));
+       flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced) | (1 << PG_arch_1));
        page->flags = flags | (1 << PG_locked);
        page_cache_get(page);
        page->index = offset;
@@ -1095,14 +1095,14 @@ no_cached_page:
 
 static int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
 {
-       unsigned long kaddr;
+       char *kaddr;
        unsigned long left, count = desc->count;
 
        if (size > count)
                size = count;
 
        kaddr = kmap(page);
-       left = __copy_to_user(desc->buf, (void *)(kaddr + offset), size);
+       left = __copy_to_user(desc->buf, kaddr + offset, size);
        kunmap(page);
        
        if (left) {
@@ -1146,7 +1146,7 @@ ssize_t generic_file_read(struct file * filp, char * buf, size_t count, loff_t *
 
 static int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset , unsigned long size)
 {
-       unsigned long kaddr;
+       char *kaddr;
        ssize_t written;
        unsigned long count = desc->count;
        struct file *file = (struct file *) desc->buf;
@@ -1158,8 +1158,7 @@ static int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned
        set_fs(KERNEL_DS);
 
        kaddr = kmap(page);
-       written = file->f_op->write(file, (char *)kaddr + offset,
-                                                size, &file->f_pos);
+       written = file->f_op->write(file, kaddr + offset, size, &file->f_pos);
        kunmap(page);
        set_fs(old_fs);
        if (written < 0) {
index d83d9bb879b955949f2f74e8dc0b3e28c075929f..08f20755ec19ae66ed16753b6c15ec8dccd99173 100644 (file)
@@ -29,7 +29,7 @@ struct page * prepare_highmem_swapout(struct page * page)
 {
        struct page *new_page;
        unsigned long regular_page;
-       unsigned long vaddr;
+
        /*
         * If this is a highmem page so it can't be swapped out directly
         * otherwise the b_data buffer addresses will break
@@ -50,8 +50,7 @@ struct page * prepare_highmem_swapout(struct page * page)
        if (!regular_page)
                return NULL;
 
-       vaddr = kmap(page);
-       copy_page((void *)regular_page, (void *)vaddr);
+       copy_page((void *)regular_page, kmap(page));
        kunmap(page);
 
        /*
@@ -67,7 +66,6 @@ struct page * prepare_highmem_swapout(struct page * page)
 struct page * replace_with_highmem(struct page * page)
 {
        struct page *highpage;
-       unsigned long vaddr;
 
        if (PageHighMem(page) || !nr_free_highpages())
                return page;
@@ -80,8 +78,7 @@ struct page * replace_with_highmem(struct page * page)
                return page;
        }
 
-       vaddr = kmap(highpage);
-       copy_page((void *)vaddr, page_address(page));
+       copy_page(kmap(highpage), page_address(page));
        kunmap(highpage);
 
        if (page->mapping)
@@ -188,7 +185,7 @@ start:
        return vaddr;
 }
 
-unsigned long kmap_high(struct page *page)
+void *kmap_high(struct page *page)
 {
        unsigned long vaddr;
 
@@ -206,7 +203,7 @@ unsigned long kmap_high(struct page *page)
        if (pkmap_count[PKMAP_NR(vaddr)] < 2)
                BUG();
        spin_unlock(&kmap_lock);
-       return vaddr;
+       return (void*) vaddr;
 }
 
 void kunmap_high(struct page *page)
@@ -242,7 +239,7 @@ static inline void copy_from_high_bh (struct buffer_head *to,
                         struct buffer_head *from)
 {
        struct page *p_from;
-       unsigned long vfrom;
+       char *vfrom;
        unsigned long flags;
 
        p_from = from->b_page;
@@ -254,7 +251,7 @@ static inline void copy_from_high_bh (struct buffer_head *to,
        __save_flags(flags);
        __cli();
        vfrom = kmap_atomic(p_from, KM_BOUNCE_WRITE);
-       memcpy(to->b_data, (char *)vfrom + bh_offset(from), to->b_size);
+       memcpy(to->b_data, vfrom + bh_offset(from), to->b_size);
        kunmap_atomic(vfrom, KM_BOUNCE_WRITE);
        __restore_flags(flags);
 }
@@ -263,14 +260,14 @@ static inline void copy_to_high_bh_irq (struct buffer_head *to,
                         struct buffer_head *from)
 {
        struct page *p_to;
-       unsigned long vto;
+       char *vto;
        unsigned long flags;
 
        p_to = to->b_page;
        __save_flags(flags);
        __cli();
        vto = kmap_atomic(p_to, KM_BOUNCE_READ);
-       memcpy((char *)vto + bh_offset(to), from->b_data, to->b_size);
+       memcpy(vto + bh_offset(to), from->b_data, to->b_size);
        kunmap_atomic(vto, KM_BOUNCE_READ);
        __restore_flags(flags);
 }
index d26c66f54dfda9d5fa953996991b34e4ab3d6eaa..3a91d955e97327cfdb4355fc35bcf63cbb24067f 100644 (file)
@@ -58,7 +58,7 @@ void add_to_swap_cache(struct page *page, swp_entry_t entry)
                BUG();
        if (page->mapping)
                BUG();
-       flags = page->flags & ~((1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced));
+       flags = page->flags & ~((1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced) | (1 << PG_arch_1));
        page->flags = flags | (1 << PG_uptodate);
        add_to_page_cache_locked(page, &swapper_space, entry.val);
 }
index 15261612eeff454584797c0b557fb9671f8ccc4f..339cffb5bbd60798eddadfffe20949e44802a544 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -137,24 +138,31 @@ inline int vmalloc_area_pages (unsigned long address, unsigned long size,
 {
        pgd_t * dir;
        unsigned long end = address + size;
+       int ret;
 
        dir = pgd_offset_k(address);
        flush_cache_all();
+       lock_kernel();
        do {
                pmd_t *pmd;
                
                pmd = pmd_alloc_kernel(dir, address);
+               ret = -ENOMEM;
                if (!pmd)
-                       return -ENOMEM;
+                       break;
 
+               ret = -ENOMEM;
                if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot))
-                       return -ENOMEM;
+                       break;
 
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                dir++;
+
+               ret = 0;
        } while (address && (address < end));
+       unlock_kernel();
        flush_tlb_all();
-       return 0;
+       return ret;
 }
 
 struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)
@@ -165,9 +173,15 @@ struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)
        area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
        if (!area)
                return NULL;
+       size += PAGE_SIZE;
        addr = VMALLOC_START;
        write_lock(&vmlist_lock);
        for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
+               if ((size + addr) < addr) {
+                       write_unlock(&vmlist_lock);
+                       kfree(area);
+                       return NULL;
+               }
                if (size + addr < (unsigned long) tmp->addr)
                        break;
                addr = tmp->size + (unsigned long) tmp->addr;
@@ -179,7 +193,7 @@ struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)
        }
        area->flags = flags;
        area->addr = (void *)addr;
-       area->size = size + PAGE_SIZE;
+       area->size = size;
        area->next = *p;
        *p = area;
        write_unlock(&vmlist_lock);
index ff79d8584f2d23c16d82f1cdbc91bf5ea95f631a..ddfdab2a5bf178954430c8c8ef792d409a280f1b 100644 (file)
@@ -7,7 +7,7 @@
 
 O_TARGET :=    network.o
 
-mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink
+mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink sched
 export-objs := netsyms.o
 
 subdir-y :=    core ethernet
index 7490dff2bd54e154163a802ad4aa8bda81d2c18c..cacc02146c64bb8e48dbd351e6f4638741f3c8d9 100644 (file)
@@ -7,7 +7,7 @@ Code Section            Bug Report Contact
     [token ring        ]       p.norton@computer.org
 appletalk              jschlst@turbolinux.com
 ax25                   g4klx@g4klx.demon.co.uk
-bridge                 buytenh@openrock.net
+bridge                 buytenh@gnu.org
 core                   alan@lxorguk.ukuu.org.uk
 decnet                 SteveW@ACM.org
 ethernet               alan@lxorguk.ukuu.org.uk
index ff28ed551a7367f7bef363176470efd993e20f98..922039cb59b10ecd2e4daecb37121fce84cd0f01 100644 (file)
@@ -130,7 +130,7 @@ static int __init atmpvc_init(void)
        error = sock_register(&pvc_family_ops);
        if (error < 0) {
                printk(KERN_ERR "ATMPVC: can't register (%d)",error);
-               return;
+               return -EINVAL;
        }
 #ifdef CONFIG_ATM_CLIP
        atm_clip_init();
index be9d1867a5ac1c4e63c10f3c9196b2ed90d15f11..f942bfd45cbd60cc682a037604447b736832bac5 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $Id: br_fdb.c,v 1.4 2000/02/24 06:16:45 davem Exp $
+ *     $Id: br_fdb.c,v 1.5 2000/11/08 05:16:40 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -43,6 +43,7 @@ static __inline__ int has_expired(struct net_bridge *br,
 
 static __inline__ void copy_fdb(struct __fdb_entry *ent, struct net_bridge_fdb_entry *f)
 {
+       memset(ent, 0, sizeof(struct __fdb_entry));
        memcpy(ent->mac_addr, f->addr.addr, ETH_ALEN);
        ent->port_no = f->dst?f->dst->port_no:0;
        ent->is_local = f->is_local;
index 295cfc973ffd2c5a8b9bb8d32cf9002717f8f02b..08c58f19fe496ea7ed1db4085bd9e6c9e50bc66b 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $Id: br_if.c,v 1.4 2000/10/05 01:58:16 davem Exp $
+ *     $Id: br_if.c,v 1.5 2000/11/08 05:16:40 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -279,12 +279,8 @@ int br_get_bridge_ifindices(int *indices, int num)
 /* called under ioctl_lock */
 void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
 {
-       int i;
        struct net_bridge_port *p;
 
-       for (i=0;i<256;i++)
-               ifindices[i] = 0;
-
        p = br->port_list;
        while (p != NULL) {
                ifindices[p->port_no] = p->dev->ifindex;
index 4d04aec66f57b71a5986c1748e0c3c66056df0e2..840b3641eae6182abf63913dad871e872895d13a 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $Id: br_ioctl.c,v 1.3 2000/10/05 01:58:16 davem Exp $
+ *     $Id: br_ioctl.c,v 1.4 2000/11/08 05:16:40 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -53,6 +53,7 @@ static int br_ioctl_device(struct net_bridge *br,
        {
                struct __bridge_info b;
 
+               memset(&b, 0, sizeof(struct __bridge_info));
                memcpy(&b.designated_root, &br->designated_root, 8);
                memcpy(&b.bridge_id, &br->bridge_id, 8);
                b.root_path_cost = br->root_path_cost;
@@ -81,8 +82,12 @@ static int br_ioctl_device(struct net_bridge *br,
 
        case BRCTL_GET_PORT_LIST:
        {
+               int i;
                int indices[256];
 
+               for (i=0;i<256;i++)
+                       indices[i] = 0;
+
                br_get_port_ifindices(br, indices);
                if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
                        return -EFAULT;
@@ -124,6 +129,7 @@ static int br_ioctl_device(struct net_bridge *br,
                if ((pt = br_get_port(br, arg1)) == NULL)
                        return -EINVAL;
 
+               memset(&p, 0, sizeof(struct __port_info));
                memcpy(&p.designated_root, &pt->designated_root, 8);
                memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
                p.port_id = pt->port_id;
@@ -189,8 +195,12 @@ static int br_ioctl_deviceless(unsigned int cmd,
 
        case BRCTL_GET_BRIDGES:
        {
+               int i;
                int indices[64];
 
+               for (i=0;i<64;i++)
+                       indices[i] = 0;
+
                if (arg1 > 64)
                        arg1 = 64;
                arg1 = br_get_bridge_ifindices(indices, arg1);
index a29c21a8a8cf3b11dc8e8b2cf24616028a52b171..0bd1b40047de577bb9aa4dddbf9291d51d5cc61c 100644 (file)
@@ -204,12 +204,16 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
 {
        struct cmsghdr *cm = (struct cmsghdr*)msg->msg_control;
 
-       int fdmax = (msg->msg_controllen - sizeof(struct cmsghdr))/sizeof(int);
+       int fdmax = 0;
        int fdnum = scm->fp->count;
        struct file **fp = scm->fp->fp;
        int *cmfptr;
        int err = 0, i;
 
+       if (msg->msg_controllen > sizeof(struct cmsghdr))
+               fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr))
+                        / sizeof(int));
+
        if (fdnum < fdmax)
                fdmax = fdnum;
 
@@ -245,7 +249,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
                        msg->msg_controllen -= cmlen;
                }
        }
-       if (i < fdnum)
+       if (i < fdnum || (fdnum && fdmax <= 0))
                msg->msg_flags |= MSG_CTRUNC;
 
        /*
index e1832fd8c2e04710dcb285b66b280abf292ea7f8..e643a39eb63586be516af6fb5f2709b6412f2ab7 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: route.c,v 1.48 2000/08/10 01:17:13 davem Exp $
+ *     $Id: route.c,v 1.49 2000/11/03 01:11:58 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1902,22 +1902,22 @@ ctl_table ipv6_route_table[] = {
          &proc_dointvec},
        {NET_IPV6_ROUTE_GC_MIN_INTERVAL, "gc_min_interval",
          &ip6_rt_gc_min_interval, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies},
+         &proc_dointvec_jiffies, &sysctl_jiffies},
        {NET_IPV6_ROUTE_GC_TIMEOUT, "gc_timeout",
          &ip6_rt_gc_timeout, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies},
+         &proc_dointvec_jiffies, &sysctl_jiffies},
        {NET_IPV6_ROUTE_GC_INTERVAL, "gc_interval",
          &ip6_rt_gc_interval, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies},
+         &proc_dointvec_jiffies, &sysctl_jiffies},
        {NET_IPV6_ROUTE_GC_ELASTICITY, "gc_elasticity",
          &ip6_rt_gc_elasticity, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies},
+         &proc_dointvec_jiffies, &sysctl_jiffies},
        {NET_IPV6_ROUTE_MTU_EXPIRES, "mtu_expires",
          &ip6_rt_mtu_expires, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies},
+         &proc_dointvec_jiffies, &sysctl_jiffies},
        {NET_IPV6_ROUTE_MIN_ADVMSS, "min_adv_mss",
          &ip6_rt_min_advmss, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies},
+         &proc_dointvec_jiffies, &sysctl_jiffies},
         {0}
 };
 
index 0070c5813e29282bb6d2bc674ce927d5cb78dfef..0c798e495b4bf011ca4158201064a293b2c664aa 100644 (file)
@@ -3,6 +3,6 @@
 #
 
 bool '  IPX: Full internal IPX network' CONFIG_IPX_INTERN
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  dep_tristate '  IPX: SPX networking (EXPERIMENTAL)' CONFIG_SPX $CONFIG_IPX
-fi
+#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+#  dep_tristate '  IPX: SPX networking (EXPERIMENTAL)' CONFIG_SPX $CONFIG_IPX
+#fi
index a26afe191a7a99116209c1ae83851be608b7a9cb..7908d726c7fa1d01f490c45623408a37445788f6 100644 (file)
@@ -58,7 +58,7 @@ It sends the data to the socket indicated by desc->buf.
 static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
 {
        int written;
-       unsigned long kaddr;
+       char *kaddr;
        unsigned long count = desc->count;
        struct socket *sock = (struct socket *) desc->buf;
        mm_segment_t old_fs;
@@ -69,7 +69,7 @@ static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned
        set_fs(KERNEL_DS);
 
        kaddr = kmap(page);
-       written = SendBuffer_async(sock,(char *)kaddr + offset,size);
+       written = SendBuffer_async(sock, kaddr + offset, size);
        kunmap(page);
        set_fs(old_fs);
        if (written < 0) {