diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/Configure.help linux-2.4.26-pre6/Documentation/Configure.help
--- linux-2.4.25/Documentation/Configure.help	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/Documentation/Configure.help	2004-03-25 00:22:03.000000000 +0000
@@ -2085,6 +2085,40 @@ CONFIG_BLK_DEV_ATARAID_HPT
   If you choose to compile this as a module, the module will be called
   hptraid.o.
 
+CMD/Silicon Image Medley Software RAID
+CONFIG_BLK_DEV_ATARAID_MEDLEY
+  Say Y or M if you have a Silicon Image 3112 SATA RAID controller,
+  a CMD680 based controller, or another IDE RAID controller that uses
+  CMD's Medley software RAID, and want Linux to use the software RAID
+  feature of this card.  This driver uses /dev/ataraid/dXpY (X and Y
+  numbers) as device names.
+
+  This driver currently only supports RAID0 (striped) mode, so if you
+  are using RAID1 (mirroring) this will not work for you. In that
+  case, you may want to try the Silicon Image Medley Software RAID
+  driver (below).
+
+  Support for mirroring is planned in the future.
+
+  If you choose to compile this as a module, the module will be called
+  medley.o.
+
+Silicon Image Medley Software RAID (old driver)
+CONFIG_BLK_DEV_ATARAID_SII
+  Say Y or M if you have a Silicon Image SATARaid controller
+  and want Linux to use the softwareraid feature of this card.
+  This driver uses /dev/ataraid/dXpY (X and Y numbers) as device
+  names.
+
+  This driver does not reliably detect all Medley RAID sets, and could
+  be dangerous if you have a striped set with disks of different size.
+
+  You should use the new Medley RAID driver (above), unless you use
+  RAID1 (mirroring), which the new driver does not yet support.
+
+  If you choose to compile this as a module, the module will be called
+  silraid.o.
+
 Support for Acer PICA 1 chipset
 CONFIG_ACER_PICA_61
   This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
@@ -6206,17 +6240,6 @@ CONFIG_IP_SCTP
 
   If in doubt, say N.
 
-SCTP: Use old checksum (Adler-32)
-CONFIG_SCTP_ADLER32
-  RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
-  This has been deprecated and replaced by an algorithm now referred
-  to as crc32c.
-
-  If you say Y, this will use the Adler-32 algorithm, this might be 
-  useful for interoperation with downlevel peers. 
-
-  If unsure, say N.  
-
 SCTP: Debug messages
 CONFIG_SCTP_DBG_MSG
   If you say Y, this will enable verbose debugging messages. 
@@ -6234,6 +6257,29 @@ CONFIG_SCTP_DBG_OBJCNT
 
   If unsure, say N
 
+#choice
+SCTP: HMAC algorithm
+CONFIG_SCTP_HMAC_NONE
+  Choose an HMAC algorithm to be used during association establishment.
+  It can be one of SHA1, MD5 or NONE. It is advised to use either HMAC-MD5
+  or HMAC-SHA1.
+  See configuration for Cryptographic API and enable these algorithms
+  to make usable by SCTP.
+
+SCTP: SHA1 HMAC algorithm
+CONFIG_SCTP_HMAC_SHA1
+  Enable the use of HMAC-SHA1 during association establishment.  It 
+  is advised to use either HMAC-MD5 or HMAC-SHA1.
+  See configuration for Cryptographic API and enable these algorithms
+  to make usable by SCTP.
+
+SCTP: MD5 HMAC algorithm
+config SCTP_HMAC_MD5
+  Enable the use of HMAC-MD5 during association establishment.  It is 
+  advised to use either HMAC-MD5 or HMAC-SHA1.
+  See configuration for Cryptographic API and enable these algorithms
+  to make usable by SCTP.
+
 Kernel httpd acceleration
 CONFIG_KHTTPD
   The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
@@ -10237,6 +10283,19 @@ CONFIG_AIRO_CS
   say M here and read <file:Documentation/modules.txt>.  The module
   will be called airo_cs.o.
 
+Atmel at76c502/at76c504 PCMCIA cards
+CONFIG_PCMCIA_ATMEL
+  A driver for PCMCIA 802.11 wireless cards based on the 
+  Atmel fast-vnet chips. This driver supports standard
+  Linux wireless extensions. 
+
+  Many  cards based on this chipset do not have flash memory
+  and need their firmware loaded at start-up. If yours is 
+  one of these, you will need to provide a firmware image
+  to be loaded into the card by the driver. The Atmel
+  firmware package can be downloaded from
+  http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz
+
 Aviator/Raytheon 2.4MHz wireless support
 CONFIG_PCMCIA_RAYCS
   Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
@@ -12358,6 +12417,16 @@ CONFIG_B44
   <file:Documentation/networking/net-modules.txt>.  The module will be
   called b44.
 
+nForce Ethernet support (EXPERIMENTAL)
+CONFIG_FORCEDETH
+  If you have a network (Ethernet) controller of this type, say Y and
+  read the Ethernet-HOWTO, available from
+  <http://www.tldp.org/docs.html#howto>.
+
+  To compile this driver as a module, choose M here and read
+  <file:Documentation/networking/net-modules.txt>.  The module will be
+  called forcedeth.o.
+
 CS89x0 support (Daynaport CS and LC cards)
 CONFIG_CS89x0
   Support for CS89x0 chipset based Ethernet cards. If you have a
@@ -19919,14 +19988,6 @@ CONFIG_ACPI_DEBUG
   of verbosity. Saying Y enables these statements. This will increase
   your kernel size by around 50K.
 
-ACPI Relaxed AML Checking
-CONFIG_ACPI_RELAXED_AML
-  If you say `Y' here, the ACPI interpreter will relax its checking
-  for valid AML and will ignore some AML mistakes, such as off-by-one
-  errors in region sizes.  Some laptops may require this option.  In
-  particular, many Toshiba laptops require this for correct operation
-  of the AC module.
-
 ACPI Button
 CONFIG_ACPI_BUTTON
   This driver registers for events based on buttons, such as the
@@ -23541,7 +23602,7 @@ CONFIG_OKTAGON_SCSI
   If you have the BSC Oktagon SCSI disk controller for the Amiga, say
   Y to this question.  If you're in doubt about whether you have one,
   see the picture at
-  <http://amiga.multigraph.com/photos/oktagon.html>.
+  <http://amiga.resource.cx/exp/search.pl?product=oktagon>.
 
 Atari native SCSI support
 CONFIG_ATARI_SCSI
@@ -28701,6 +28762,13 @@ CONFIG_CRYPTO_CAST6
   The CAST6 encryption algorithm (synonymous with CAST-256) is
   described in RFC2612.
 
+CONFIG_CRYPTO_ARC4
+  ARC4 cipher algorithm.
+  
+  This is a stream cipher using keys ranging from 8 bits to 2048
+  bits in length.  ARC4 is commonly used in protocols such as WEP 
+  and SSL.
+
 CONFIG_CRYPTO_DEFLATE
   This is the Deflate algorithm (RFC1951), specified for use in
   IPSec with the IPCOMP protocol (RFC3173, RFC2394).
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/crypto/api-intro.txt linux-2.4.26-pre6/Documentation/crypto/api-intro.txt
--- linux-2.4.25/Documentation/crypto/api-intro.txt	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/Documentation/crypto/api-intro.txt	2004-03-25 00:22:28.172709104 +0000
@@ -185,6 +185,8 @@ Original developers of the crypto algori
   Matthew Skala (Twofish)
   Dag Arne Osvik (Serpent)
   Brian Gladman (AES)
+  Kartikey Mahendra Bhatt (CAST6)
+  Jon Oberheide (ARC4)
 
 SHA1 algorithm contributors:
   Jean-Francois Dive
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/kernel-parameters.txt linux-2.4.26-pre6/Documentation/kernel-parameters.txt
--- linux-2.4.25/Documentation/kernel-parameters.txt	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/Documentation/kernel-parameters.txt	2004-03-25 00:22:36.086506024 +0000
@@ -73,16 +73,21 @@ running once the system is up.
 		off	Disable ACPI
 		ht	Limit ACPI to boot-time LAPIC enumeration for HT,
 			disabling the run-time AML interpreter.
+		strict	Be less tolerant of platforms that are not
+			strictly ACPI specification compliant.
 
-	acpi_pic_sci=	[HW,ACPI] ACPI System Conrol Interrupt trigger mode
-		level	Force PIC-mode SCI to Level Trigger (default)
-		edge	Force PIC-mode SCI to Edge Trigger
+	acpi_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
+			Format: { level | edge |  high | low }
  
 	acpi_irq_balance	ACPI will balance active IRQs
 	acpi_irq_nobalance	ACPI will not move active IRQs
 	acpi_irq_pci=	If irq_balance, Clear listed IRQs for use by PCI
 	acpi_irq_isa=	If irq_balance, Mark listed IRQs used by ISA
 
+	acpi_osi=	[HW,ACPI] empty param disables _OSI
+
+	acpi_serialize	[HW,ACPI] force serialization of AML methods
+
 	ad1816=		[HW,SOUND]
 
 	ad1848=		[HW,SOUND]
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/networking/bonding.txt linux-2.4.26-pre6/Documentation/networking/bonding.txt
--- linux-2.4.25/Documentation/networking/bonding.txt	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/Documentation/networking/bonding.txt	2004-03-25 00:18:32.000000000 +0000
@@ -21,7 +21,7 @@ userspace tools, please follow the links
 
 Table of Contents
 =================
- 
+
 Installation
 Bond Configuration
 Module Parameters
@@ -31,6 +31,7 @@ Verifying Bond Configuration
 Frequently Asked Questions
 High Availability
 Promiscuous Sniffing notes
+8021q VLAN support
 Limitations
 Resources and Links
 
@@ -66,7 +67,7 @@ of the -I option on the ifenslave compil
 /usr/include/linux.
 
 To install ifenslave.c, do:
-    # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave 
+    # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave
     # cp ifenslave /sbin/ifenslave
 
 
@@ -74,10 +75,10 @@ Bond Configuration
 ==================
 
 You will need to add at least the following line to /etc/modules.conf
-so the bonding driver will automatically load when the bond0 interface is 
-configured. Refer to the modules.conf manual page for specific modules.conf 
-syntax details. The Module Parameters section of this document describes each 
-bonding driver parameter. 
+so the bonding driver will automatically load when the bond0 interface is
+configured. Refer to the modules.conf manual page for specific modules.conf
+syntax details. The Module Parameters section of this document describes each
+bonding driver parameter.
 
 	alias bond0 bonding
 
@@ -113,7 +114,7 @@ bonding interface (bond1), use MASTER=bo
 network interface be a slave of bond1.
 
 Restart the networking subsystem or just bring up the bonding device if your
-administration tools allow it. Otherwise, reboot. On Red Hat distros you can 
+administration tools allow it. Otherwise, reboot. On Red Hat distros you can
 issue `ifup bond0' or `/etc/rc.d/init.d/network restart'.
 
 If the administration tools of your distribution do not support
@@ -128,30 +129,26 @@ manually configure the bonding device wi
 
 (use appropriate values for your network above)
 
-You can then create a script containing these commands and place it in the 
+You can then create a script containing these commands and place it in the
 appropriate rc directory.
 
 If you specifically need all network drivers loaded before the bonding driver,
-adding the following line to modules.conf will cause the network driver for 
+adding the following line to modules.conf will cause the network driver for
 eth0 and eth1 to be loaded before the bonding driver.
 
 probeall bond0 eth0 eth1 bonding
 
-Be careful not to reference bond0 itself at the end of the line, or modprobe 
+Be careful not to reference bond0 itself at the end of the line, or modprobe
 will die in an endless recursive loop.
 
-To have device characteristics (such as MTU size) propagate to slave devices, 
-set the bond characteristics before enslaving the device.  The characteristics 
-are propagated during the enslave process.
-
-If running SNMP agents, the bonding driver should be loaded before any network 
-drivers participating in a bond. This requirement is due to the the interface 
-index (ipAdEntIfIndex) being associated to the first interface found with a 
-given IP address. That is, there is only one ipAdEntIfIndex for each IP 
-address. For example, if eth0 and eth1 are slaves of bond0 and the driver for 
-eth0 is loaded before the bonding driver, the interface for the IP address 
-will be associated with the eth0 interface. This configuration is shown below, 
-the IP address 192.168.1.1 has an interface index of 2 which indexes to eth0 
+If running SNMP agents, the bonding driver should be loaded before any network
+drivers participating in a bond. This requirement is due to the the interface
+index (ipAdEntIfIndex) being associated to the first interface found with a
+given IP address. That is, there is only one ipAdEntIfIndex for each IP
+address. For example, if eth0 and eth1 are slaves of bond0 and the driver for
+eth0 is loaded before the bonding driver, the interface for the IP address
+will be associated with the eth0 interface. This configuration is shown below,
+the IP address 192.168.1.1 has an interface index of 2 which indexes to eth0
 in the ifDescr table (ifDescr.2).
 
      interfaces.ifTable.ifEntry.ifDescr.1 = lo
@@ -189,10 +186,10 @@ functions such as Interface_Scan_Next wi
 Module Parameters
 =================
 
-Optional parameters for the bonding driver can be supplied as command line 
-arguments to the insmod command. Typically, these parameters are specified in 
-the file /etc/modules.conf (see the manual page for modules.conf). The 
-available bonding driver parameters are listed below. If a parameter is not 
+Optional parameters for the bonding driver can be supplied as command line
+arguments to the insmod command. Typically, these parameters are specified in
+the file /etc/modules.conf (see the manual page for modules.conf). The
+available bonding driver parameters are listed below. If a parameter is not
 specified the default value is used. When initially configuring a bond, it
 is recommended "tail -f /var/log/messages" be run in a separate window to
 watch for bonding driver error messages.
@@ -202,19 +199,19 @@ parameters be specified, otherwise serio
 during link failures.
 
 arp_interval
- 
-        Specifies the ARP monitoring frequency in milli-seconds. 
-        If ARP monitoring is used in a load-balancing mode (mode 0 or 2), the 
-        switch should be configured in a mode that evenly distributes packets 
-        across all links - such as round-robin. If the switch is configured to 
-        distribute the packets in an XOR fashion, all replies from the ARP 
-        targets will be received on the same link which could cause the other 
+
+        Specifies the ARP monitoring frequency in milli-seconds.
+        If ARP monitoring is used in a load-balancing mode (mode 0 or 2), the
+        switch should be configured in a mode that evenly distributes packets
+        across all links - such as round-robin. If the switch is configured to
+        distribute the packets in an XOR fashion, all replies from the ARP
+        targets will be received on the same link which could cause the other
         team members to fail. ARP monitoring should not be used in conjunction
-        with miimon. A value of 0 disables ARP monitoring. The default value 
+        with miimon. A value of 0 disables ARP monitoring. The default value
         is 0.
- 
+
 arp_ip_target
- 
+
 	Specifies the ip addresses to use when arp_interval is > 0. These
 	are the targets of the ARP request sent to determine the health of
 	the link to the targets. Specify these values in ddd.ddd.ddd.ddd
@@ -223,8 +220,8 @@ arp_ip_target
 	maximum number of targets that can be specified is set at 16.
 
 downdelay
- 
-        Specifies the delay time in milli-seconds to disable a link after a 
+
+        Specifies the delay time in milli-seconds to disable a link after a
         link failure has been detected. This should be a multiple of miimon
         value, otherwise the value will be rounded. The default value is 0.
 
@@ -247,7 +244,7 @@ max_bonds
 	and bond2 will be created.  The default value is 1.
 
 miimon
- 
+
         Specifies the frequency in milli-seconds that MII link monitoring
         will occur. A value of zero disables MII link monitoring. A value
         of 100 is a good starting point. See High Availability section for
@@ -258,7 +255,7 @@ mode
 	Specifies one of the bonding policies. The default is
 	round-robin (balance-rr).  Possible values are (you can use
 	either the text or numeric option):
- 
+
 	balance-rr or 0
 
 		Round-robin policy: Transmit in a sequential order
@@ -273,7 +270,7 @@ mode
 		externally visible on only one port (network adapter)
 		to avoid confusing the switch.  This mode provides
 		fault tolerance.
- 
+
 	balance-xor or 2
 
 		XOR policy: Transmit based on [(source MAC address
@@ -293,7 +290,7 @@ mode
 		groups that share the same speed and duplex settings.
 		Transmits and receives on all slaves in the active
 		aggregator.
- 
+
 		Pre-requisites:
 
 		1. Ethtool support in the base drivers for retrieving the
@@ -317,7 +314,7 @@ mode
 		Ethtool support in the base drivers for retrieving the
 		speed of each slave.
 
-	balance-alb or 6 
+	balance-alb or 6
 
 		Adaptive load balancing: includes balance-tlb + receive
 		load balancing (rlb) for IPV4 traffic and does not require
@@ -327,7 +324,7 @@ mode
 		overwrites the src hw address with the unique hw address of
 		one of the slaves in the bond such that different clients
 		use different hw addresses for the server.
-		
+
 		Receive traffic from connections created by the server is
 		also balanced. When the server sends an ARP Request the
 		bonding driver copies and saves the client's IP information
@@ -363,25 +360,11 @@ mode
 		2. Base driver support for setting the hw address of a
 		device also when it is open. This is required so that there
 		will always be one slave in the team using the bond hw
-		address (the current_slave) while having a unique hw
-		address for each slave in the bond. If the current_slave
-		fails it's hw address is swapped with the new current_slave
+		address (the curr_active_slave) while having a unique hw
+		address for each slave in the bond. If the curr_active_slave
+		fails it's hw address is swapped with the new curr_active_slave
 		that was chosen.
 
-multicast
-
-        Option specifying the mode of operation for multicast support.
-        Possible values are:
-
-	disabled or 0
-		Disabled (no multicast support)
-
-        active or 1
-		Enabled on active slave only, useful in active-backup mode
-
-	all or 2
-		Enabled on all slaves, this is the default
-
 primary
 
         A string (eth0, eth2, etc) to equate to a primary device. If this
@@ -397,11 +380,11 @@ primary
         primary is only valid in active-backup mode.
 
 updelay
- 
-        Specifies the delay time in milli-seconds to enable a link after a 
+
+        Specifies the delay time in milli-seconds to enable a link after a
         link up status has been detected. This should be a multiple of miimon
         value, otherwise the value will be rounded. The default value is 0.
- 
+
 use_carrier
 
         Specifies whether or not miimon should use MII or ETHTOOL
@@ -529,20 +512,20 @@ Verifying Bond Configuration
 ----------------------------
 The bonding driver information files reside in the /proc/net/bonding directory.
 
-Sample contents of /proc/net/bonding/bond0 after the driver is loaded with 
+Sample contents of /proc/net/bonding/bond0 after the driver is loaded with
 parameters of mode=0 and miimon=1000 is shown below.
- 
+
         Bonding Mode: load balancing (round-robin)
         Currently Active Slave: eth0
         MII Status: up
         MII Polling Interval (ms): 1000
         Up Delay (ms): 0
         Down Delay (ms): 0
- 
+
         Slave Interface: eth1
         MII Status: up
         Link Failure Count: 1
- 
+
         Slave Interface: eth0
         MII Status: up
         Link Failure Count: 1
@@ -550,34 +533,34 @@ parameters of mode=0 and miimon=1000 is 
 2) Network verification
 -----------------------
 The network configuration can be verified using the ifconfig command. In
-the example below, the bond0 interface is the master (MASTER) while eth0 and 
-eth1 are slaves (SLAVE). Notice all slaves of bond0 have the same MAC address 
+the example below, the bond0 interface is the master (MASTER) while eth0 and
+eth1 are slaves (SLAVE). Notice all slaves of bond0 have the same MAC address
 (HWaddr) as bond0 for all modes except TLB and ALB that require a unique MAC
 address for each slave.
 
 [root]# /sbin/ifconfig
-bond0     Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4  
+bond0     Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4
           inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
           UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
           RX packets:7224794 errors:0 dropped:0 overruns:0 frame:0
           TX packets:3286647 errors:1 dropped:0 overruns:1 carrier:0
-          collisions:0 txqueuelen:0 
+          collisions:0 txqueuelen:0
 
-eth0      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4  
+eth0      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4
           inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
           UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
           RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0
           TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0
-          collisions:0 txqueuelen:100 
-          Interrupt:10 Base address:0x1080 
+          collisions:0 txqueuelen:100
+          Interrupt:10 Base address:0x1080
 
-eth1      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4  
+eth1      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4
           inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
           UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
           RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0
           TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0
-          collisions:0 txqueuelen:100 
-          Interrupt:9 Base address:0x1400 
+          collisions:0 txqueuelen:100
+          Interrupt:9 Base address:0x1400
 
 
 Frequently Asked Questions
@@ -605,9 +588,9 @@ Frequently Asked Questions
 
 5.  What happens when a slave link dies?
 
-	If your ethernet cards support MII or ETHTOOL link status monitoring 
-        and the MII monitoring has been enabled in the driver (see description 
-        of module parameters), there will be no adverse consequences. This 
+	If your ethernet cards support MII or ETHTOOL link status monitoring
+        and the MII monitoring has been enabled in the driver (see description
+        of module parameters), there will be no adverse consequences. This
         release of the bonding driver knows how to get the MII information and
 	enables or disables its slaves according to their link status.
 	See section on High Availability for additional information.
@@ -615,15 +598,15 @@ Frequently Asked Questions
 	For ethernet cards not supporting MII status, the arp_interval and
         arp_ip_target parameters must be specified for bonding to work
         correctly. If packets have not been sent or received during the
-        specified arp_interval durration, an ARP request is sent to the
+        specified arp_interval duration, an ARP request is sent to the
         targets to generate send and receive traffic. If after this
         interval, either the successful send and/or receive count has not
         incremented, the next slave in the sequence will become the active
         slave.
 
 	If neither mii_monitor and arp_interval is configured, the bonding
-	driver will not handle this situation very well. The driver will 
-	continue to send packets but some packets will be lost. Retransmits 
+	driver will not handle this situation very well. The driver will
+	continue to send packets but some packets will be lost. Retransmits
 	will cause serious degradation of performance (in the case when one
 	of two slave links fails, 50% packets will be lost, which is a serious
 	problem for both TCP and UDP).
@@ -636,9 +619,9 @@ Frequently Asked Questions
 
 7.  Which switches/systems does it work with?
 
-	In round-robin and XOR mode, it works with systems that support 
+	In round-robin and XOR mode, it works with systems that support
 	trunking:
-	
+
 	* Many Cisco switches and routers (look for EtherChannel support).
 	* SunTrunking software.
 	* Alteon AceDirector switches / WebOS (use Trunks).
@@ -646,7 +629,7 @@ Frequently Asked Questions
 	  models (450) can define trunks between ports on different physical
 	  units.
 	* Linux bonding, of course !
-	
+
 	In 802.3ad mode, it works with with systems that support IEEE 802.3ad
 	Dynamic Link Aggregation:
 
@@ -667,32 +650,24 @@ Frequently Asked Questions
 	is then passed to all following slaves and remains persistent (even if
 	the the first slave is removed) until the bonding device is brought
 	down or reconfigured.
-	
+
 	If you wish to change the MAC address, you can set it with ifconfig:
 
 	  # ifconfig bond0 hw ether 00:11:22:33:44:55
 
 	The MAC address can be also changed by bringing down/up the device
 	and then changing its slaves (or their order):
-	
+
 	  # ifconfig bond0 down ; modprobe -r bonding
 	  # ifconfig bond0 .... up
 	  # ifenslave bond0 eth...
 
 	This method will automatically take the address from the next slave
 	that will be added.
-	
-	To restore your slaves' MAC addresses, you need to detach them
-	from the bond (`ifenslave -d bond0 eth0'), set them down
-	(`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for
-	example) and reload them to get the MAC addresses from their
-	eeproms. If the driver is shared by several devices, you need
-	to turn them all down. Another solution is to look for the MAC
-	address at boot time (dmesg or tail /var/log/messages) and to
-	reset it by hand with ifconfig :
 
-	  # ifconfig eth0 down
-	  # ifconfig eth0 hw ether 00:20:40:60:80:A0
+	To restore your slaves' MAC addresses, you need to detach them
+	from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then
+	restore the MAC addresses that the slaves had before they were enslaved.
 
 9.  Which transmit polices can be used?
 
@@ -729,27 +704,27 @@ High Availability
 =================
 
 To implement high availability using the bonding driver, the driver needs to be
-compiled as a module, because currently it is the only way to pass parameters 
+compiled as a module, because currently it is the only way to pass parameters
 to the driver. This may change in the future.
 
-High availability is achieved by using MII or ETHTOOL status reporting. You 
-need to verify that all your interfaces support MII or ETHTOOL link status 
-reporting.  On Linux kernel 2.2.17, all the 100 Mbps capable drivers and 
-yellowfin gigabit driver support MII. To determine if ETHTOOL link reporting 
-is available for interface eth0, type "ethtool eth0" and the "Link detected:" 
-line should contain the correct link status. If your system has an interface 
-that does not support MII or ETHTOOL status reporting, a failure of its link 
-will not be detected! A message indicating MII and ETHTOOL is not supported by 
-a network driver is logged when the bonding driver is loaded with a non-zero 
+High availability is achieved by using MII or ETHTOOL status reporting. You
+need to verify that all your interfaces support MII or ETHTOOL link status
+reporting.  On Linux kernel 2.2.17, all the 100 Mbps capable drivers and
+yellowfin gigabit driver support MII. To determine if ETHTOOL link reporting
+is available for interface eth0, type "ethtool eth0" and the "Link detected:"
+line should contain the correct link status. If your system has an interface
+that does not support MII or ETHTOOL status reporting, a failure of its link
+will not be detected! A message indicating MII and ETHTOOL is not supported by
+a network driver is logged when the bonding driver is loaded with a non-zero
 miimon value.
 
 The bonding driver can regularly check all its slaves links using the ETHTOOL
-IOCTL (ETHTOOL_GLINK command) or by checking the MII status registers. The 
-check interval is specified by the module argument "miimon" (MII monitoring). 
-It takes an integer that represents the checking time in milliseconds. It 
-should not come to close to (1000/HZ) (10 milli-seconds on i386) because it 
-may then reduce the system interactivity. A value of 100 seems to be a good 
-starting point. It means that a dead link will be detected at most 100 
+IOCTL (ETHTOOL_GLINK command) or by checking the MII status registers. The
+check interval is specified by the module argument "miimon" (MII monitoring).
+It takes an integer that represents the checking time in milliseconds. It
+should not come to close to (1000/HZ) (10 milli-seconds on i386) because it
+may then reduce the system interactivity. A value of 100 seems to be a good
+starting point. It means that a dead link will be detected at most 100
 milli-seconds after it goes down.
 
 Example:
@@ -761,7 +736,7 @@ Or, put the following lines in /etc/modu
    alias bond0 bonding
    options bond0 miimon=100
 
-There are currently two policies for high availability. They are dependent on 
+There are currently two policies for high availability. They are dependent on
 whether:
 
    a) hosts are connected to a single host or switch that support trunking
@@ -811,7 +786,7 @@ Example 2 : host to switch at twice the 
      # ifenslave bond0 eth0 eth1
 
 
-2) High Availability on two or more switches (or a single switch without 
+2) High Availability on two or more switches (or a single switch without
    trunking support)
 ---------------------------------------------------------------------------
 This mode is more problematic because it relies on the fact that there
@@ -857,7 +832,7 @@ point of failure" solution.
 
 In this configuration, there is an ISL - Inter Switch Link (could be a trunk),
 several servers (host1, host2 ...) attached to both switches each, and one or
-more ports to the outside world (port3...). One an only one slave on each host
+more ports to the outside world (port3...). One and only one slave on each host
 is active at a time, while all links are still monitored (the system can
 detect a failure of active and backup links).
 
@@ -870,10 +845,10 @@ by another external mechanism, it is goo
 connected to one switch and host2's to the other. Such system will survive
 a failure of a single host, cable, or switch. The worst thing that may happen
 in the case of a switch failure is that half of the hosts will be temporarily
-unreachable until the other switch expires its tables. 
+unreachable until the other switch expires its tables.
 
 Example 2: Using multiple ethernet cards connected to a switch to configure
-           NIC failover (switch is not required to support trunking). 
+           NIC failover (switch is not required to support trunking).
 
 
           +----------+                          +----------+
@@ -947,6 +922,41 @@ capacity aggregating; but it works fine 
 just ignore all the warnings it emits.
 
 
+8021q VLAN support
+==================
+
+It is possible to configure VLAN devices over a bond interface using the 8021q
+driver. However, only packets coming from the 8021q driver and passing through
+bonding will be tagged by default. Self generated packets, like bonding's
+learning packets or ARP packets generated by either ALB mode or the ARP
+monitor mechanism, are tagged internally by bonding itself. As a result,
+bonding has to "learn" what VLAN IDs are configured on top of it, and it uses
+those IDs to tag self generated packets.
+
+For simplicity reasons, and to support the use of adapters that can do VLAN
+hardware acceleration offloding, the bonding interface declares itself as
+fully hardware offloaing capable, it gets the add_vid/kill_vid notifications
+to gather the necessary information, and it propagates those actions to the
+slaves.
+In case of mixed adapter types, hardware accelerated tagged packets that should
+go through an adapter that is not offloading capable are "un-accelerated" by the
+bonding driver so the VLAN tag sits in the regular location.
+
+VLAN interfaces *must* be added on top of a bonding interface only after
+enslaving at least one slave. This is because until the first slave is added the
+bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by
+the VLAN interface when it is created.
+
+Notice that a problem would occur if all slaves are released from a bond that
+still has VLAN interfaces on top of it. When later coming to add new slaves, the
+bonding interface would get a HW address from the first slave, which might not
+match that of the VLAN interfaces. It is recommended that either all VLANs are
+removed and then re-added, or to manually set the bonding interface's HW
+address so it matches the VLAN's. (Note: changing a VLAN interface's HW address
+would set the underlying device -- i.e. the bonding interface -- to promiscouos
+mode, which might not be what you want).
+
+
 Limitations
 ===========
 The main limitations are :
@@ -957,7 +967,7 @@ The main limitations are :
     servers, but may be useful when the front switches send multicast
     information on their links (e.g. VRRP), or even health-check the servers.
     Use the arp_interval/arp_ip_target parameters to count incoming/outgoing
-    frames.  
+    frames.
 
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/networking/ifenslave.c linux-2.4.26-pre6/Documentation/networking/ifenslave.c
--- linux-2.4.25/Documentation/networking/ifenslave.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/Documentation/networking/ifenslave.c	2004-03-25 00:18:00.000000000 +0000
@@ -4,8 +4,6 @@
  *	This program controls the Linux implementation of running multiple
  *	network interfaces in parallel.
  *
- * Usage:	ifenslave [-v] master-interface < slave-interface [metric <N>] > ...
- *
  * Author:	Donald Becker <becker@cesdis.gsfc.nasa.gov>
  *		Copyright 1994-1996 Donald Becker
  *
@@ -90,24 +88,30 @@
  * 	 - For opt_c: slave should not be set to the master's setting
  *	   while it is running. It was already set during enslave. To
  *	   simplify things, it is now handeled separately.
+ *
+ *    - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	 - Code cleanup and style changes
+ *	   set version to 1.1.0
  */
 
-#define APP_VERSION	"1.0.12"
-#define APP_RELDATE	"June 30, 2003"
+#define APP_VERSION	"1.1.0"
+#define APP_RELDATE	"December 1, 2003"
 #define APP_NAME	"ifenslave"
 
 static char *version =
-APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ") "  "\nDonald Becker (becker@cesdis.gsfc.nasa.gov).\n"
-"detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
-"2.4 kernel support added on 2001/02/16 by Chad N. Tindel (ctindel at ieee dot org.\n";
+APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n"
+"o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n"
+"o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
+"o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n"
+"  (ctindel at ieee dot org).\n";
 
 static const char *usage_msg =
-"Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\n"
-"       ifenslave -c master-interface slave-if\n";
+"Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n"
+"       ifenslave -d   <master-if> <slave-if> [<slave-if>...]\n"
+"       ifenslave -c   <master-if> <slave-if>\n"
+"       ifenslave --help\n";
 
-static const char *howto_msg =
-"Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\n"
-"       ifenslave -c master-interface slave-if\n"
+static const char *help_msg =
 "\n"
 "       To create a bond device, simply follow these three steps :\n"
 "       - ensure that the required drivers are properly loaded :\n"
@@ -115,18 +119,32 @@ static const char *howto_msg =
 "       - assign an IP address to the bond device :\n"
 "         # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
 "       - attach all the interfaces you need to the bond device :\n"
-"         # ifenslave bond0 eth0 eth1 eth2\n"
+"         # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n"
 "         If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
 "         interfaces attached AFTER this assignment will get the same MAC addr.\n"
-"\n"
-"       To detach a dead interface without setting the bond device down :\n"
-"         # ifenslave -d bond0 eth1\n"
+"         (except for ALB/TLB modes)\n"
 "\n"
 "       To set the bond device down and automatically release all the slaves :\n"
 "         # ifconfig bond0 down\n"
 "\n"
+"       To detach a dead interface without setting the bond device down :\n"
+"         # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n"
+"\n"
 "       To change active slave :\n"
-"         # ifenslave -c bond0 eth0\n"
+"         # ifenslave {-c|--change-active} bond0 eth0\n"
+"\n"
+"       To show master interface info\n"
+"         # ifenslave bond0\n"
+"\n"
+"       To show all interfaces info\n"
+"       # ifenslave {-a|--all-interfaces}\n"
+"\n"
+"       To be more verbose\n"
+"       # ifenslave {-v|--verbose} ...\n"
+"\n"
+"       # ifenslave {-u|--usage}   Show usage\n"
+"       # ifenslave {-V|--version} Show version\n"
+"       # ifenslave {-h|--help}    This message\n"
 "\n";
 
 #include <unistd.h>
@@ -153,476 +171,332 @@ typedef __uint8_t u8;		/* ditto */
 #include <linux/ethtool.h>
 
 struct option longopts[] = {
- /* { name  has_arg  *flag  val } */
-    {"all-interfaces", 0, 0, 'a'},	/* Show all interfaces. */
-    {"force",       0, 0, 'f'},		/* Force the operation. */
-    {"help", 		0, 0, '?'},		/* Give help */
-	{"howto",       0, 0, 'h'},     /* Give some more help */
-    {"receive-slave", 0, 0, 'r'},	/* Make a receive-only slave.  */
-    {"verbose", 	0, 0, 'v'},		/* Report each action taken.  */
-    {"version", 	0, 0, 'V'},		/* Emit version information.  */
-    {"detach",       0, 0, 'd'},	/* Detach a slave interface. */
-    {"change-active", 0, 0, 'c'},	/* Change the active slave.  */
-    { 0, 0, 0, 0 }
+	/* { name  has_arg  *flag  val } */
+	{"all-interfaces",	0, 0, 'a'},	/* Show all interfaces. */
+	{"change-active",	0, 0, 'c'},	/* Change the active slave.  */
+	{"detach",		0, 0, 'd'},	/* Detach a slave interface. */
+	{"force",		0, 0, 'f'},	/* Force the operation. */
+	{"help",		0, 0, 'h'},	/* Give help */
+	{"usage",		0, 0, 'u'},	/* Give usage */
+	{"verbose",		0, 0, 'v'},	/* Report each action taken. */
+	{"version",		0, 0, 'V'},	/* Emit version information. */
+	{ 0, 0, 0, 0}
 };
 
 /* Command-line flags. */
 unsigned int
-opt_a = 0,					/* Show-all-interfaces flag. */
-opt_f = 0,					/* Force the operation. */
-opt_r = 0,					/* Set up a Rx-only slave. */
-opt_d = 0,					/* detach a slave interface. */
-opt_c = 0,					/* change-active-slave flag. */
-verbose = 0,					/* Verbose flag. */
-opt_version = 0,
-opt_howto = 0;
-int skfd = -1;					/* AF_INET socket for ioctl() calls.	*/
+opt_a = 0,	/* Show-all-interfaces flag. */
+opt_c = 0,	/* Change-active-slave flag. */
+opt_d = 0,	/* Detach a slave interface. */
+opt_f = 0,	/* Force the operation. */
+opt_h = 0,	/* Help */
+opt_u = 0,	/* Usage */
+opt_v = 0,	/* Verbose flag. */
+opt_V = 0;	/* Version */
+
+int skfd = -1;		/* AF_INET socket for ioctl() calls.*/
+int abi_ver = 0;	/* userland - kernel ABI version */
+int hwaddr_set = 0;	/* Master's hwaddr is set */
+int saved_errno;
+
+struct ifreq master_mtu, master_flags, master_hwaddr;
+struct ifreq slave_mtu, slave_flags, slave_hwaddr;
+
+struct dev_ifr {
+	struct ifreq *req_ifr;
+	char *req_name;
+	int req_type;
+};
+
+struct dev_ifr master_ifra[] = {
+	{&master_mtu,     "SIOCGIFMTU",     SIOCGIFMTU},
+	{&master_flags,   "SIOCGIFFLAGS",   SIOCGIFFLAGS},
+	{&master_hwaddr,  "SIOCGIFHWADDR",  SIOCGIFHWADDR},
+	{NULL, "", 0}
+};
+
+struct dev_ifr slave_ifra[] = {
+	{&slave_mtu,     "SIOCGIFMTU",     SIOCGIFMTU},
+	{&slave_flags,   "SIOCGIFFLAGS",   SIOCGIFFLAGS},
+	{&slave_hwaddr,  "SIOCGIFHWADDR",  SIOCGIFHWADDR},
+	{NULL, "", 0}
+};
 
 static void if_print(char *ifname);
-static int get_abi_ver(char *master_ifname);
+static int get_drv_info(char *master_ifname);
+static int get_if_settings(char *ifname, struct dev_ifr ifra[]);
+static int get_slave_flags(char *slave_ifname);
+static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr);
+static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr);
+static int set_slave_mtu(char *slave_ifname, int mtu);
+static int set_if_flags(char *ifname, short flags);
+static int set_if_up(char *ifname, short flags);
+static int set_if_down(char *ifname, short flags);
+static int clear_if_addr(char *ifname);
+static int set_if_addr(char *master_ifname, char *slave_ifname);
+static int change_active(char *master_ifname, char *slave_ifname);
+static int enslave(char *master_ifname, char *slave_ifname);
+static int release(char *master_ifname, char *slave_ifname);
+#define v_print(fmt, args...)	\
+	if (opt_v)		\
+		fprintf(stderr, fmt, ## args )
 
-int
-main(int argc, char **argv)
+int main(int argc, char *argv[])
 {
-	struct ifreq  ifr2, if_hwaddr, if_ipaddr, if_metric, if_mtu, if_dstaddr;
-	struct ifreq  if_netmask, if_brdaddr, if_flags;
-	int rv, goterr = 0;
-	int c, errflag = 0;
-	sa_family_t master_family;
 	char **spp, *master_ifname, *slave_ifname;
-	int hwaddr_notset;
-	int abi_ver = 0;
+	int c, i, rv;
+	int res = 0;
+	int exclusive = 0;
 
-	while ((c = getopt_long(argc, argv, "acdfrvV?h", longopts, 0)) != EOF)
+	while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) {
 		switch (c) {
-		case 'a': opt_a++; break;
-		case 'f': opt_f++; break;
-		case 'r': opt_r++; break;
-		case 'd': opt_d++; break;
-		case 'c': opt_c++; break;
-		case 'v': verbose++;		break;
-		case 'V': opt_version++;	break;
-		case 'h': opt_howto++;	break;
-		case '?': errflag++;
-		}
+		case 'a': opt_a++; exclusive++; break;
+		case 'c': opt_c++; exclusive++; break;
+		case 'd': opt_d++; exclusive++; break;
+		case 'f': opt_f++; exclusive++; break;
+		case 'h': opt_h++; exclusive++; break;
+		case 'u': opt_u++; exclusive++; break;
+		case 'v': opt_v++; break;
+		case 'V': opt_V++; exclusive++; break;
 
-	/* option check */
-	if (opt_c)
-		if(opt_a || opt_f || opt_r || opt_d || verbose || opt_version ||
-		   opt_howto || errflag ) {
+		case '?':
 			fprintf(stderr, usage_msg);
-			return 2;
+			res = 2;
+			goto out;
 		}
+	}
 
-	if (errflag) {
+	/* options check */
+	if (exclusive > 1) {
 		fprintf(stderr, usage_msg);
-		return 2;
+		res = 2;
+		goto out;
 	}
 
-	if (opt_howto) {
-		fprintf(stderr, howto_msg);
-		return 0;
+	if (opt_v || opt_V) {
+		printf(version);
+		if (opt_V) {
+			res = 0;
+			goto out;
+		}
 	}
 
-	if (verbose || opt_version) {
-		printf(version);
-		if (opt_version)
-			exit(0);
+	if (opt_u) {
+		printf(usage_msg);
+		res = 0;
+		goto out;
 	}
 
-	/* Open a basic socket. */
-	if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
-		perror("socket");
-		exit(-1);
+	if (opt_h) {
+		printf(usage_msg);
+		printf(help_msg);
+		res = 0;
+		goto out;
 	}
 
-	if (verbose)
-		fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n",
-				argc, optind, argv[optind]);
+	/* Open a basic socket */
+	if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+		perror("socket");
+		res = 1;
+		goto out;
+	}
 
-	/* No remaining args means show all interfaces. */
-	if (optind == argc) {
-		if_print((char *)NULL);
-		(void) close(skfd);
-		exit(0);
+	if (opt_a) {
+		if (optind == argc) {
+			/* No remaining args */
+			/* show all interfaces */
+			if_print((char *)NULL);
+			goto out;
+		} else {
+			/* Just show usage */
+			fprintf(stderr, usage_msg);
+			res = 2;
+			goto out;
+		}
 	}
 
-	/* Copy the interface name. */
+	/* Copy the interface name */
 	spp = argv + optind;
 	master_ifname = *spp++;
-	slave_ifname = *spp++;
 
-	/* Check command line. */
-	if (opt_c) {
-		char **tempp = spp;
-		if ((master_ifname == NULL)||(slave_ifname == NULL)||(*tempp++ != NULL)) {
-			fprintf(stderr, usage_msg);
-			(void) close(skfd);
-			return 2;
-		}
+	if (master_ifname == NULL) {
+		fprintf(stderr, usage_msg);
+		res = 2;
+		goto out;
 	}
 
-	/* A single args means show the configuration for this interface. */
-	if (slave_ifname == NULL) {
-		if_print(master_ifname);
-		(void) close(skfd);
-		exit(0);
+	/* exchange abi version with bonding module */
+	res = get_drv_info(master_ifname);
+	if (res) {
+		fprintf(stderr,
+			"Master '%s': Error: handshake with driver failed. "
+			"Aborting\n",
+			master_ifname);
+		goto out;
 	}
 
-	/* exchange abi version with bonding driver */
-	abi_ver = get_abi_ver(master_ifname);
-	if (abi_ver < 0) {
-		(void) close(skfd);
-		exit(1);
-	}
-
-	/* Get the vitals from the master interface. */
-	{
-		struct ifreq *ifra[7] = { &if_ipaddr, &if_mtu, &if_dstaddr,
-								  &if_brdaddr, &if_netmask, &if_flags,
-								  &if_hwaddr };
-		const char *req_name[7] = {
-			"IP address", "MTU", "destination address",
-			"broadcast address", "netmask", "status flags",
-			"hardware address" };
-		const int ioctl_req_type[7] = {
-			SIOCGIFADDR, SIOCGIFMTU, SIOCGIFDSTADDR,
-			SIOCGIFBRDADDR, SIOCGIFNETMASK, SIOCGIFFLAGS,
-			SIOCGIFHWADDR };
-		int i;
-
-		for (i = 0; i < 7; i++) {
-			strncpy(ifra[i]->ifr_name, master_ifname, IFNAMSIZ);
-			if (ioctl(skfd, ioctl_req_type[i], ifra[i]) < 0) {
-				fprintf(stderr,
-						"Something broke getting the master's %s: %s.\n",
-						req_name[i], strerror(errno));
-			}
-		}
-
-		/* check if master is up; if not then fail any operation */
-		if (!(if_flags.ifr_flags & IFF_UP)) {
-			fprintf(stderr, "Illegal operation; the specified master interface '%s' is not up.\n", master_ifname);
-			(void) close(skfd);
-			exit (1);
-		}
+	slave_ifname = *spp++;
 
-		hwaddr_notset = 1; /* assume master's address not set yet */
-		for (i = 0; hwaddr_notset && (i < 6); i++) {
-			hwaddr_notset &= ((unsigned char *)if_hwaddr.ifr_hwaddr.sa_data)[i] == 0;
+	if (slave_ifname == NULL) {
+		if (opt_d || opt_c) {
+			fprintf(stderr, usage_msg);
+			res = 2;
+			goto out;
 		}
 
-		/* The family '1' is ARPHRD_ETHER for ethernet. */
-		if (if_hwaddr.ifr_hwaddr.sa_family != 1 && !opt_f) {
-			fprintf(stderr, "The specified master interface '%s' is not"
-					" ethernet-like.\n  This program is designed to work"
-					" with ethernet-like network interfaces.\n"
-					" Use the '-f' option to force the operation.\n",
-					master_ifname);
-			(void) close(skfd);
-			exit (1);
-		}
-		master_family = if_hwaddr.ifr_hwaddr.sa_family;
-		if (verbose) {
-			unsigned char *hwaddr = (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data;
-			printf("The current hardware address (SIOCGIFHWADDR) of %s is type %d  "
-				   "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname,
-				   if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
-				   hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
-		}
+		/* A single arg means show the
+		 * configuration for this interface
+		 */
+		if_print(master_ifname);
+		goto out;
 	}
 
+	res = get_if_settings(master_ifname, master_ifra);
+	if (res) {
+		/* Probably a good reason not to go on */
+		fprintf(stderr,
+			"Master '%s': Error: get settings failed: %s. "
+			"Aborting\n",
+			master_ifname, strerror(res));
+		goto out;
+	}
 
-	/* do this when enslaving interfaces */
-	do {
-		if (opt_d) {  /* detach a slave interface from the master */
-			strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
-			strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
-			if ((ioctl(skfd, SIOCBONDRELEASE, &if_flags) < 0) &&
-				(ioctl(skfd, BOND_RELEASE_OLD, &if_flags) < 0)) {
-					fprintf(stderr,	"SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.\n",
-							slave_ifname, master_ifname, strerror(errno));
-			}
-			else if (abi_ver < 1) {
-			      	/* The driver is using an old ABI, so we'll set the interface
-				 * down to avoid any conflicts due to same IP/MAC
-				 */
-				strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
-				if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
-					int saved_errno = errno;
-					fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
-						strerror(saved_errno));
-				}
-				else {
-					ifr2.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
-					if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
-						int saved_errno = errno;
-						fprintf(stderr, "Shutting down interface %s failed: %s\n",
-							slave_ifname, strerror(saved_errno));
-					}
-				}
-			}
-		} else if (opt_c) { /* change primary slave */
-			strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
-			strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
-			if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &if_flags) < 0) &&
-			    (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &if_flags) < 0)) {
-				fprintf(stderr,	"SIOCBONDCHANGEACTIVE: %s.\n", strerror(errno));
-			}
-		} else {  /* attach a slave interface to the master */
-
-			strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
-			if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
-				int saved_errno = errno;
-				fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
-						strerror(saved_errno));
-				(void) close(skfd);
-				return 1;
-			}
-
-			if ((ifr2.ifr_flags & IFF_SLAVE) && !opt_r) {
-				fprintf(stderr, "%s is already a slave\n", slave_ifname);
-				(void) close(skfd);
-				return 1;
-			}
-
-			/* if hwaddr_notset, assign the slave hw address to the master */
-			if (hwaddr_notset) {
-				/* assign the slave hw address to the
-				 * master since it currently does not
-				 * have one; otherwise, slaves may
-				 * have different hw addresses in
-				 * active-backup mode as seen when enslaving
-				 * using "ifenslave bond0 eth0 eth1" because
-				 * hwaddr_notset is set outside this loop.
-				 * TODO: put this and the "else" portion in
-				 *       a function.
-				 */
-				/* get the slaves MAC address */
-				strncpy(if_hwaddr.ifr_name, slave_ifname,
-					IFNAMSIZ);
-				rv = ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr);
-				if (-1 == rv) {
-					fprintf(stderr, "Could not get MAC "
-						"address of %s: %s\n",
-						slave_ifname,
-						strerror(errno));
-					strncpy(if_hwaddr.ifr_name,
-						master_ifname, IFNAMSIZ);
-					goterr = 1;
-				}
-
-				if (!goterr) {
-					if (abi_ver < 1) {
-						/* In ABI versions older than 1, the
-						 * master's set_mac routine couldn't
-						 * work if it was up, because it
-						 * used the default ethernet set_mac
-						 * function.
-						 */
-						/* bring master down */
-						if_flags.ifr_flags &= ~IFF_UP;
-						if (ioctl(skfd, SIOCSIFFLAGS,
-								&if_flags) < 0) {
-							goterr = 1;
-							fprintf(stderr,
-								"Shutting down "
-								"interface %s failed: "
-								"%s\n",
-								master_ifname,
-								strerror(errno));
-						}
-					}
-
-					strncpy(if_hwaddr.ifr_name,
-						master_ifname, IFNAMSIZ);
-					if (ioctl(skfd, SIOCSIFHWADDR,
-							&if_hwaddr) < 0) {
-						fprintf(stderr,
-							"Could not set MAC "
-							"address of %s: %s\n",
-							master_ifname,
-							strerror(errno));
-						goterr=1;
-					} else {
-						hwaddr_notset = 0;
-					}
-
-					if (abi_ver < 1) {
-						/* bring master back up */
-						if_flags.ifr_flags |= IFF_UP;
-						if (ioctl(skfd, SIOCSIFFLAGS,
-							  &if_flags) < 0) {
-							fprintf(stderr,
-								"Bringing up interface "
-								"%s failed: %s\n",
-								master_ifname,
-								strerror(errno));
-						}
-					}
-				}
-			} else if (abi_ver < 1) { /* if (hwaddr_notset) */
-
-			      	/* The driver is using an old ABI, so we'll set the interface
-				 * down and assign the master's hwaddr to it
-				 */
-				if (ifr2.ifr_flags & IFF_UP) {
-					ifr2.ifr_flags &= ~IFF_UP;
-					if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
-						int saved_errno = errno;
-						fprintf(stderr, "Shutting down interface %s failed: %s\n",
-							slave_ifname, strerror(saved_errno));
-					}
-				}
-
-				strncpy(if_hwaddr.ifr_name, slave_ifname, IFNAMSIZ);
-				if (ioctl(skfd, SIOCSIFHWADDR, &if_hwaddr) < 0) {
-					int saved_errno = errno;
-					fprintf(stderr, "SIOCSIFHWADDR on %s failed: %s\n", if_hwaddr.ifr_name,
-						strerror(saved_errno));
-					if (saved_errno == EBUSY)
-						fprintf(stderr, "  The slave device %s is busy: it must be"
-							" idle before running this command.\n", slave_ifname);
-					else if (saved_errno == EOPNOTSUPP)
-						fprintf(stderr, "  The slave device you specified does not support"
-							" setting the MAC address.\n  Your kernel likely does not"
-							" support slave devices.\n");
-					else if (saved_errno == EINVAL)
-						fprintf(stderr, "  The slave device's address type does not match"
-							" the master's address type.\n");
-				} else {
-					if (verbose) {
-						unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
-						printf("Slave's (%s) hardware address set to "
-							   "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", slave_ifname,
-							   hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
-					}
-				}
-			}
+	/* check if master is indeed a master;
+	 * if not then fail any operation
+	 */
+	if (!(master_flags.ifr_flags & IFF_MASTER)) {
+		fprintf(stderr,
+			"Illegal operation; the specified interface '%s' "
+			"is not a master. Aborting\n",
+			master_ifname);
+		res = 1;
+		goto out;
+	}
 
-			if (*spp  &&  !strcmp(*spp, "metric")) {
-				if (*++spp == NULL) {
-					fprintf(stderr, usage_msg);
-					(void) close(skfd);
-					exit(2);
-				}
-				if_metric.ifr_metric = atoi(*spp);
-				strncpy(if_metric.ifr_name, slave_ifname, IFNAMSIZ);
-				if (ioctl(skfd, SIOCSIFMETRIC, &if_metric) < 0) {
-					fprintf(stderr, "SIOCSIFMETRIC on %s: %s\n", slave_ifname,
-							strerror(errno));
-					goterr = 1;
-				}
-				spp++;
-			}
+	/* check if master is up; if not then fail any operation */
+	if (!(master_flags.ifr_flags & IFF_UP)) {
+		fprintf(stderr,
+			"Illegal operation; the specified master interface "
+			"'%s' is not up.\n",
+			master_ifname);
+		res = 1;
+		goto out;
+	}
 
-			if (strncpy(if_ipaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
-				|| ioctl(skfd, SIOCSIFADDR, &if_ipaddr) < 0) {
-				fprintf(stderr,
-						"Something broke setting the slave's address: %s.\n",
-						strerror(errno));
-			} else {
-				if (verbose) {
-					unsigned char *ipaddr = if_ipaddr.ifr_addr.sa_data;
-					printf("Set the slave's (%s) IP address to %d.%d.%d.%d.\n",
-						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
-				}
-			}
+	/* Only for enslaving */
+	if (!opt_c && !opt_d) {
+		sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family;
+		unsigned char *hwaddr =
+			(unsigned char *)master_hwaddr.ifr_hwaddr.sa_data;
 
-			if (strncpy(if_mtu.ifr_name, slave_ifname, IFNAMSIZ) <= 0
-				|| ioctl(skfd, SIOCSIFMTU, &if_mtu) < 0) {
-				fprintf(stderr, "Something broke setting the slave MTU: %s.\n",
-						strerror(errno));
-			} else {
-				if (verbose)
-					printf("Set the slave's (%s) MTU to %d.\n", slave_ifname, if_mtu.ifr_mtu);
-			}
+		/* The family '1' is ARPHRD_ETHER for ethernet. */
+		if (master_family != 1 && !opt_f) {
+			fprintf(stderr,
+				"Illegal operation: The specified master "
+				"interface '%s' is not ethernet-like.\n "
+				"This program is designed to work with "
+				"ethernet-like network interfaces.\n "
+				"Use the '-f' option to force the "
+				"operation.\n",
+				master_ifname);
+			res = 1;
+			goto out;
+		}
 
-			if (strncpy(if_dstaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
-				|| ioctl(skfd, SIOCSIFDSTADDR, &if_dstaddr) < 0) {
-				fprintf(stderr, "Error setting the slave (%s) with SIOCSIFDSTADDR: %s.\n",
-						slave_ifname, strerror(errno));
-			} else {
-				if (verbose) {
-					unsigned char *ipaddr = if_dstaddr.ifr_dstaddr.sa_data;
-					printf("Set the slave's (%s) destination address to %d.%d.%d.%d.\n",
-						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
-				}
+		/* Check master's hw addr */
+		for (i = 0; i < 6; i++) {
+			if (hwaddr[i] != 0) {
+				hwaddr_set = 1;
+				break;
 			}
+		}
 
-			if (strncpy(if_brdaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
-				|| ioctl(skfd, SIOCSIFBRDADDR, &if_brdaddr) < 0) {
-				fprintf(stderr,
-						"Something broke setting the slave (%s) broadcast address: %s.\n",
-						slave_ifname, strerror(errno));
-			} else {
-				if (verbose) {
-					unsigned char *ipaddr = if_brdaddr.ifr_broadaddr.sa_data;
-					printf("Set the slave's (%s) broadcast address to %d.%d.%d.%d.\n",
-						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
-				}
-			}
+		if (hwaddr_set) {
+			v_print("current hardware address of master '%s' "
+				"is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+				"type %d\n",
+				master_ifname,
+				hwaddr[0], hwaddr[1],
+				hwaddr[2], hwaddr[3],
+				hwaddr[4], hwaddr[5],
+				master_family);
+		}
+	}
 
-			if (strncpy(if_netmask.ifr_name, slave_ifname, IFNAMSIZ) <= 0
-				|| ioctl(skfd, SIOCSIFNETMASK, &if_netmask) < 0) {
-				fprintf(stderr,
-						"Something broke setting the slave (%s) netmask: %s.\n",
-						slave_ifname, strerror(errno));
-			} else {
-				if (verbose) {
-					unsigned char *ipaddr = if_netmask.ifr_netmask.sa_data;
-					printf("Set the slave's (%s) netmask to %d.%d.%d.%d.\n",
-						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+	/* Accepts only one slave */
+	if (opt_c) {
+		/* change active slave */
+		res = get_slave_flags(slave_ifname);
+		if (res) {
+			fprintf(stderr,
+				"Slave '%s': Error: get flags failed. "
+				"Aborting\n",
+				slave_ifname);
+			goto out;
+		}
+		res = change_active(master_ifname, slave_ifname);
+		if (res) {
+			fprintf(stderr,
+				"Master '%s', Slave '%s': Error: "
+				"Change active failed\n",
+				master_ifname, slave_ifname);
+		}
+	} else {
+		/* Accept multiple slaves */
+		do {
+			if (opt_d) {
+				/* detach a slave interface from the master */
+				rv = get_slave_flags(slave_ifname);
+				if (rv) {
+					/* Can't work with this slave. */
+					/* remember the error and skip it*/
+					fprintf(stderr,
+						"Slave '%s': Error: get flags "
+						"failed. Skipping\n",
+						slave_ifname);
+					res = rv;
+					continue;
 				}
-			}
-
-			if (abi_ver < 1) {
-
-			      	/* The driver is using an old ABI, so we'll set the interface
-				 * up before enslaving it
-				 */
-				ifr2.ifr_flags |= IFF_UP;
-				if ((ifr2.ifr_flags &= ~(IFF_SLAVE | IFF_MASTER)) == 0
-					|| strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ) <= 0
-					|| ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
-						fprintf(stderr,
-							"Something broke setting the slave (%s) flags: %s.\n",
-							slave_ifname, strerror(errno));
-				} else {
-					if (verbose)
-						printf("Set the slave's (%s) flags %4.4x.\n",
-							slave_ifname, if_flags.ifr_flags);
+				rv = release(master_ifname, slave_ifname);
+				if (rv) {
+					fprintf(stderr,
+						"Master '%s', Slave '%s': Error: "
+						"Release failed\n",
+						master_ifname, slave_ifname);
+					res = rv;
 				}
 			} else {
-				/* the bonding module takes care of setting the slave's mac address
-			 	 * and opening its interface
-			 	 */
-				if (ifr2.ifr_flags & IFF_UP) { /* the interface will need to be down */
-					ifr2.ifr_flags &= ~IFF_UP;
-					if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
-						int saved_errno = errno;
-						fprintf(stderr, "Shutting down interface %s failed: %s\n",
-							slave_ifname, strerror(saved_errno));
-					}
+				/* attach a slave interface to the master */
+				rv = get_if_settings(slave_ifname, slave_ifra);
+				if (rv) {
+					/* Can't work with this slave. */
+					/* remember the error and skip it*/
+					fprintf(stderr,
+						"Slave '%s': Error: get "
+						"settings failed: %s. "
+						"Skipping\n",
+						slave_ifname, strerror(rv));
+					res = rv;
+					continue;
 				}
-			}
-
-			/* Do the real thing */
-			if (!opt_r) {
-				strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
-				strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
-				if ((ioctl(skfd, SIOCBONDENSLAVE, &if_flags) < 0) &&
-				    (ioctl(skfd, BOND_ENSLAVE_OLD, &if_flags) < 0)) {
-					fprintf(stderr,	"SIOCBONDENSLAVE: %s.\n", strerror(errno));
+				rv = enslave(master_ifname, slave_ifname);
+				if (rv) {
+					fprintf(stderr,
+						"Master '%s', Slave '%s': Error: "
+						"Enslave failed\n",
+						master_ifname, slave_ifname);
+					res = rv;
 				}
 			}
-		}
-	} while ( (slave_ifname = *spp++) != NULL);
+		} while ((slave_ifname = *spp++) != NULL);
+	}
 
-	/* Close the socket. */
-	(void) close(skfd);
+out:
+	if (skfd >= 0) {
+		close(skfd);
+	}
 
-	return(goterr);
+	return res;
 }
 
 static short mif_flags;
@@ -631,35 +505,34 @@ static short mif_flags;
 static int if_getconfig(char *ifname)
 {
 	struct ifreq ifr;
-	int metric, mtu;			/* Parameters of the master interface. */
+	int metric, mtu;	/* Parameters of the master interface. */
 	struct sockaddr dstaddr, broadaddr, netmask;
+	unsigned char *hwaddr;
 
 	strcpy(ifr.ifr_name, ifname);
 	if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
 		return -1;
 	mif_flags = ifr.ifr_flags;
 	printf("The result of SIOCGIFFLAGS on %s is %x.\n",
-		   ifname, ifr.ifr_flags);
+	       ifname, ifr.ifr_flags);
 
 	strcpy(ifr.ifr_name, ifname);
 	if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
 		return -1;
 	printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
-		   ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
-		   ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
+	       ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
+	       ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
 
 	strcpy(ifr.ifr_name, ifname);
 	if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
 		return -1;
 
-	{
-		/* Gotta convert from 'char' to unsigned for printf().  */
-		unsigned char *hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;
-		printf("The result of SIOCGIFHWADDR is type %d  "
-			   "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
-			   ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
-			   hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
-	}
+	/* Gotta convert from 'char' to unsigned for printf(). */
+	hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;
+	printf("The result of SIOCGIFHWADDR is type %d  "
+	       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+	       ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
+	       hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
 
 	strcpy(ifr.ifr_name, ifname);
 	if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
@@ -691,7 +564,7 @@ static int if_getconfig(char *ifname)
 	} else
 		netmask = ifr.ifr_netmask;
 
-	return(0);
+	return 0;
 }
 
 static void if_print(char *ifname)
@@ -705,15 +578,16 @@ static void if_print(char *ifname)
 		ifc.ifc_len = sizeof(buff);
 		ifc.ifc_buf = buff;
 		if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
-			fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
+			perror("SIOCGIFCONF failed");
 			return;
 		}
 
 		ifr = ifc.ifc_req;
 		for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
 			if (if_getconfig(ifr->ifr_name) < 0) {
-				fprintf(stderr, "%s: unknown interface.\n",
-						ifr->ifr_name);
+				fprintf(stderr,
+					"%s: unknown interface.\n",
+					ifr->ifr_name);
 				continue;
 			}
 
@@ -721,16 +595,18 @@ static void if_print(char *ifname)
 			/*ife_print(&ife);*/
 		}
 	} else {
-		if (if_getconfig(ifname) < 0)
-			fprintf(stderr, "%s: unknown interface.\n", ifname);
+		if (if_getconfig(ifname) < 0) {
+			fprintf(stderr,
+				"%s: unknown interface.\n", ifname);
+		}
 	}
 }
 
-static int get_abi_ver(char *master_ifname)
+static int get_drv_info(char *master_ifname)
 {
 	struct ifreq ifr;
 	struct ethtool_drvinfo info;
-	int abi_ver = 0;
+	char *endptr;
 
 	memset(&ifr, 0, sizeof(ifr));
 	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
@@ -739,24 +615,487 @@ static int get_abi_ver(char *master_ifna
 	info.cmd = ETHTOOL_GDRVINFO;
 	strncpy(info.driver, "ifenslave", 32);
 	snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
-	if (ioctl(skfd, SIOCETHTOOL, &ifr) >= 0) {
-		char *endptr;
 
-		abi_ver = strtoul(info.fw_version, &endptr, 0);
-		if (*endptr) {
-			fprintf(stderr, "Error: got invalid string as an ABI "
-				"version from the bonding module\n");
-			return -1;
+	if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) {
+		if (errno == EOPNOTSUPP) {
+			goto out;
 		}
+
+		saved_errno = errno;
+		v_print("Master '%s': Error: get bonding info failed %s\n",
+			master_ifname, strerror(saved_errno));
+		return 1;
 	}
 
-	if (verbose) {
-        	printf("ABI ver is %d\n", abi_ver);
+	abi_ver = strtoul(info.fw_version, &endptr, 0);
+	if (*endptr) {
+                v_print("Master '%s': Error: got invalid string as an ABI "
+			"version from the bonding module\n",
+			master_ifname);
+		return 1;
 	}
-	return abi_ver;
+
+out:
+	v_print("ABI ver is %d\n", abi_ver);
+
+	return 0;
 }
 
+static int change_active(char *master_ifname, char *slave_ifname)
+{
+	struct ifreq ifr;
+	int res = 0;
 
+	if (!(slave_flags.ifr_flags & IFF_SLAVE)) {
+		fprintf(stderr,
+			"Illegal operation: The specified slave interface "
+			"'%s' is not a slave\n",
+			slave_ifname);
+		return 1;
+	}
+
+	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
+	strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
+	if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) &&
+	    (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) {
+		saved_errno = errno;
+		v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: "
+			"%s\n",
+			master_ifname, strerror(saved_errno));
+		res = 1;
+	}
+
+	return res;
+}
+
+static int enslave(char *master_ifname, char *slave_ifname)
+{
+	struct ifreq ifr;
+	int res = 0;
+
+	if (slave_flags.ifr_flags & IFF_SLAVE) {
+		fprintf(stderr,
+			"Illegal operation: The specified slave interface "
+			"'%s' is already a slave\n",
+			slave_ifname);
+		return 1;
+	}
+
+	res = set_if_down(slave_ifname, slave_flags.ifr_flags);
+	if (res) {
+		fprintf(stderr,
+			"Slave '%s': Error: bring interface down failed\n",
+			slave_ifname);
+		return res;
+	}
+
+	if (abi_ver < 2) {
+		/* Older bonding versions would panic if the slave has no IP
+		 * address, so get the IP setting from the master.
+		 */
+		res = set_if_addr(master_ifname, slave_ifname);
+		if (res) {
+			fprintf(stderr,
+				"Slave '%s': Error: set address failed\n",
+				slave_ifname);
+			return res;
+		}
+	} else {
+		res = clear_if_addr(slave_ifname);
+		if (res) {
+			fprintf(stderr,
+				"Slave '%s': Error: clear address failed\n",
+				slave_ifname);
+			return res;
+		}
+	}
+
+	if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) {
+		res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu);
+		if (res) {
+			fprintf(stderr,
+				"Slave '%s': Error: set MTU failed\n",
+				slave_ifname);
+			return res;
+		}
+	}
+
+	if (hwaddr_set) {
+		/* Master already has an hwaddr
+		 * so set it's hwaddr to the slave
+		 */
+		if (abi_ver < 1) {
+			/* The driver is using an old ABI, so
+			 * the application sets the slave's
+			 * hwaddr
+			 */
+			res = set_slave_hwaddr(slave_ifname,
+					       &(master_hwaddr.ifr_hwaddr));
+			if (res) {
+				fprintf(stderr,
+					"Slave '%s': Error: set hw address "
+					"failed\n",
+					slave_ifname);
+				goto undo_mtu;
+			}
+
+			/* For old ABI the application needs to bring the
+			 * slave back up
+			 */
+			res = set_if_up(slave_ifname, slave_flags.ifr_flags);
+			if (res) {
+				fprintf(stderr,
+					"Slave '%s': Error: bring interface "
+					"down failed\n",
+					slave_ifname);
+				goto undo_slave_mac;
+			}
+		}
+		/* The driver is using a new ABI,
+		 * so the driver takes care of setting
+		 * the slave's hwaddr and bringing
+		 * it up again
+		 */
+	} else {
+		/* No hwaddr for master yet, so
+		 * set the slave's hwaddr to it
+		 */
+		if (abi_ver < 1) {
+			/* For old ABI, the master needs to be
+			 * down before setting it's hwaddr
+			 */
+			res = set_if_down(master_ifname, master_flags.ifr_flags);
+			if (res) {
+				fprintf(stderr,
+					"Master '%s': Error: bring interface "
+					"down failed\n",
+					master_ifname);
+				goto undo_mtu;
+			}
+		}
+
+		res = set_master_hwaddr(master_ifname,
+					&(slave_hwaddr.ifr_hwaddr));
+		if (res) {
+			fprintf(stderr,
+				"Master '%s': Error: set hw address "
+				"failed\n",
+				master_ifname);
+			goto undo_mtu;
+		}
+
+		if (abi_ver < 1) {
+			/* For old ABI, bring the master
+			 * back up
+			 */
+			res = set_if_up(master_ifname, master_flags.ifr_flags);
+			if (res) {
+				fprintf(stderr,
+					"Master '%s': Error: bring interface "
+					"up failed\n",
+					master_ifname);
+				goto undo_master_mac;
+			}
+		}
+
+		hwaddr_set = 1;
+	}
+
+	/* Do the real thing */
+	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
+	strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
+	if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) &&
+	    (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) {
+		saved_errno = errno;
+		v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n",
+			master_ifname, strerror(saved_errno));
+		res = 1;
+	}
+
+	if (res) {
+		goto undo_master_mac;
+	}
+
+	return 0;
+
+/* rollback (best effort) */
+undo_master_mac:
+	set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr));
+	hwaddr_set = 0;
+	goto undo_mtu;
+undo_slave_mac:
+	set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr));
+undo_mtu:
+	set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu);
+	return res;
+}
+
+static int release(char *master_ifname, char *slave_ifname)
+{
+	struct ifreq ifr;
+	int res = 0;
+
+	if (!(slave_flags.ifr_flags & IFF_SLAVE)) {
+		fprintf(stderr,
+			"Illegal operation: The specified slave interface "
+			"'%s' is not a slave\n",
+			slave_ifname);
+		return 1;
+	}
+
+	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
+	strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
+	if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) &&
+	    (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) {
+		saved_errno = errno;
+		v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n",
+			master_ifname, strerror(saved_errno));
+		return 1;
+	} else if (abi_ver < 1) {
+		/* The driver is using an old ABI, so we'll set the interface
+		 * down to avoid any conflicts due to same MAC/IP
+		 */
+		res = set_if_down(slave_ifname, slave_flags.ifr_flags);
+		if (res) {
+			fprintf(stderr,
+				"Slave '%s': Error: bring interface "
+				"down failed\n",
+				slave_ifname);
+		}
+	}
+
+	/* set to default mtu */
+	set_slave_mtu(slave_ifname, 1500);
+
+	return res;
+}
+
+static int get_if_settings(char *ifname, struct dev_ifr ifra[])
+{
+	int i;
+	int res = 0;
+
+	for (i = 0; ifra[i].req_ifr; i++) {
+		strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ);
+		res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr);
+		if (res < 0) {
+			saved_errno = errno;
+			v_print("Interface '%s': Error: %s failed: %s\n",
+				ifname, ifra[i].req_name,
+				strerror(saved_errno));
+
+			return saved_errno;
+		}
+	}
+
+	return 0;
+}
+
+static int get_slave_flags(char *slave_ifname)
+{
+	int res = 0;
+
+	strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ);
+	res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags);
+	if (res < 0) {
+		saved_errno = errno;
+		v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n",
+			slave_ifname, strerror(saved_errno));
+	} else {
+		v_print("Slave %s: flags %04X.\n",
+			slave_ifname, slave_flags.ifr_flags);
+	}
+
+	return res;
+}
+
+static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr)
+{
+	unsigned char *addr = (unsigned char *)hwaddr->sa_data;
+	struct ifreq ifr;
+	int res = 0;
+
+	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
+	memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr));
+	res = ioctl(skfd, SIOCSIFHWADDR, &ifr);
+	if (res < 0) {
+		saved_errno = errno;
+		v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n",
+			master_ifname, strerror(saved_errno));
+		return res;
+	} else {
+		v_print("Master '%s': hardware address set to "
+			"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+			master_ifname, addr[0], addr[1], addr[2],
+			addr[3], addr[4], addr[5]);
+	}
+
+	return res;
+}
+
+static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr)
+{
+	unsigned char *addr = (unsigned char *)hwaddr->sa_data;
+	struct ifreq ifr;
+	int res = 0;
+
+	strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
+	memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr));
+	res = ioctl(skfd, SIOCSIFHWADDR, &ifr);
+	if (res < 0) {
+		saved_errno = errno;
+
+		v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n",
+			slave_ifname, strerror(saved_errno));
+
+		if (saved_errno == EBUSY) {
+			v_print("  The device is busy: it must be idle "
+				"before running this command.\n");
+		} else if (saved_errno == EOPNOTSUPP) {
+			v_print("  The device does not support setting "
+				"the MAC address.\n"
+				"  Your kernel likely does not support slave "
+				"devices.\n");
+		} else if (saved_errno == EINVAL) {
+			v_print("  The device's address type does not match "
+				"the master's address type.\n");
+		}
+		return res;
+	} else {
+		v_print("Slave '%s': hardware address set to "
+			"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+			slave_ifname, addr[0], addr[1], addr[2],
+			addr[3], addr[4], addr[5]);
+	}
+
+	return res;
+}
+
+static int set_slave_mtu(char *slave_ifname, int mtu)
+{
+	struct ifreq ifr;
+	int res = 0;
+
+	ifr.ifr_mtu = mtu;
+	strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
+
+	res = ioctl(skfd, SIOCSIFMTU, &ifr);
+	if (res < 0) {
+		saved_errno = errno;
+		v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n",
+			slave_ifname, strerror(saved_errno));
+	} else {
+		v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu);
+	}
+
+	return res;
+}
+
+static int set_if_flags(char *ifname, short flags)
+{
+	struct ifreq ifr;
+	int res = 0;
+
+	ifr.ifr_flags = flags;
+	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+	res = ioctl(skfd, SIOCSIFFLAGS, &ifr);
+	if (res < 0) {
+		saved_errno = errno;
+		v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n",
+			ifname, strerror(saved_errno));
+	} else {
+		v_print("Interface '%s': flags set to %04X.\n", ifname, flags);
+	}
+
+	return res;
+}
+
+static int set_if_up(char *ifname, short flags)
+{
+	return set_if_flags(ifname, flags | IFF_UP);
+}
+
+static int set_if_down(char *ifname, short flags)
+{
+	return set_if_flags(ifname, flags & ~IFF_UP);
+}
+
+static int clear_if_addr(char *ifname)
+{
+	struct ifreq ifr;
+	int res = 0;
+
+	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	ifr.ifr_addr.sa_family = AF_INET;
+	memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data));
+
+	res = ioctl(skfd, SIOCSIFADDR, &ifr);
+	if (res < 0) {
+		saved_errno = errno;
+		v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n",
+			ifname, strerror(saved_errno));
+	} else {
+		v_print("Interface '%s': address cleared\n", ifname);
+	}
+
+	return res;
+}
+
+static int set_if_addr(char *master_ifname, char *slave_ifname)
+{
+	struct ifreq ifr;
+	int res;
+	unsigned char *ipaddr;
+	int i;
+	struct {
+		char *req_name;
+		char *desc;
+		int g_ioctl;
+		int s_ioctl;
+	} ifra[] = {
+		{"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR},
+		{"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR},
+		{"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR},
+		{"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK},
+		{NULL, NULL, 0, 0},
+	};
+
+	for (i = 0; ifra[i].req_name; i++) {
+		strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
+		res = ioctl(skfd, ifra[i].g_ioctl, &ifr);
+		if (res < 0) {
+			int saved_errno = errno;
+
+			v_print("Interface '%s': Error: SIOCG%s failed: %s\n",
+				master_ifname, ifra[i].req_name,
+				strerror(saved_errno));
+
+			ifr.ifr_addr.sa_family = AF_INET;
+			memset(ifr.ifr_addr.sa_data, 0,
+			       sizeof(ifr.ifr_addr.sa_data));
+		}
+
+		strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
+		res = ioctl(skfd, ifra[i].s_ioctl, &ifr);
+		if (res < 0) {
+			int saved_errno = errno;
+
+			v_print("Interface '%s': Error: SIOCS%s failed: %s\n",
+				slave_ifname, ifra[i].req_name,
+				strerror(saved_errno));
+
+			return res;
+		}
+
+		ipaddr = ifr.ifr_addr.sa_data;
+		v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n",
+			slave_ifname, ifra[i].desc,
+			ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+	}
+
+	return 0;
+}
 
 /*
  * Local variables:
@@ -768,3 +1107,4 @@ static int get_abi_ver(char *master_ifna
  *  compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave"
  * End:
  */
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/networking/ip-sysctl.txt linux-2.4.26-pre6/Documentation/networking/ip-sysctl.txt
--- linux-2.4.25/Documentation/networking/ip-sysctl.txt	2003-06-13 14:51:29.000000000 +0000
+++ linux-2.4.26-pre6/Documentation/networking/ip-sysctl.txt	2004-03-25 00:19:27.000000000 +0000
@@ -481,6 +481,55 @@ arp_filter - BOOLEAN
 	conf/{all,interface}/arp_filter is set to TRUE,
 	it will be disabled otherwise
 
+arp_announce - INTEGER
+	Define different restriction levels for announcing the local
+	source IP address from IP packets in ARP requests sent on
+	interface:
+	0 - (default) Use any local address, configured on any interface
+	1 - Try to avoid local addresses that are not in the target's
+	subnet for this interface. This mode is useful when target
+	hosts reachable via this interface require the source IP
+	address in ARP requests to be part of their logical network
+	configured on the receiving interface. When we generate the
+	request we will check all our subnets that include the
+	target IP and will preserve the source address if it is from
+	such subnet. If there is no such subnet we select source
+	address according to the rules for level 2.
+	2 - Always use the best local address for this target.
+	In this mode we ignore the source address in the IP packet
+	and try to select local address that we prefer for talks with
+	the target host. Such local address is selected by looking
+	for primary IP addresses on all our subnets on the outgoing
+	interface that include the target IP address. If no suitable
+	local address is found we select the first local address
+	we have on the outgoing interface or on all other interfaces,
+	with the hope we will receive reply for our request and
+	even sometimes no matter the source IP address we announce.
+
+	The max value from conf/{all,interface}/arp_announce is used.
+
+	Increasing the restriction level gives more chance for
+	receiving answer from the resolved target while decreasing
+	the level announces more valid sender's information.
+
+arp_ignore - INTEGER
+	Define different modes for sending replies in response to
+	received ARP requests that resolve local target IP addresses:
+	0 - (default): reply for any local target IP address, configured
+	on any interface
+	1 - reply only if the target IP address is local address
+	configured on the incoming interface
+	2 - reply only if the target IP address is local address
+	configured on the incoming interface and both with the
+	sender's IP address are part from same subnet on this interface
+	3 - do not reply for local addresses configured with scope host,
+	only resolutions for global and link addresses are replied
+	4-7 - reserved
+	8 - do not reply for all local addresses
+
+	The max value from conf/{all,interface}/arp_ignore is used
+	when ARP request is received on the {interface}
+
 tag - INTEGER
 	Allows you to write a number, which can be used as required.
 	Default value is 0.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/MAINTAINERS linux-2.4.26-pre6/MAINTAINERS
--- linux-2.4.25/MAINTAINERS	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/MAINTAINERS	2004-03-25 00:20:30.000000000 +0000
@@ -166,7 +166,7 @@ ACPI
 P:	Len Brown
 M:	len.brown@intel.com
 L:	acpi-devel@lists.sourceforge.net
-W:	http://sf.net/projects/acpi/
+W:	http://acpi.sourceforge.net/
 S:	Maintained
 
 AD1816 SOUND DRIVER
@@ -1081,8 +1081,8 @@ LANMEDIA WAN CARD DRIVER
 P:      Andrew Stanley-Jones
 M:      asj@lanmedia.com
 W:      http://www.lanmedia.com/
-S:      Supported
- 
+S:      Orphan
+
 LAPB module
 P:	Henner Eisen
 M:	eis@baty.hanse.de
@@ -1456,9 +1456,9 @@ S:	Maintained
 
 PERMEDIA 3 FRAMEBUFFER DRIVER
 P:	Romain Dolbeau
-M:	dolbeau@irisa.fr
+M:	dolbeau@caps-entreprise.com
 L:	linux-fbdev-devel@lists.sourceforge.net
-W:	http://www.irisa.fr/prive/dolbeau/pm3fb/pm3fb.html
+W:	http://www.caps-entreprise.com/private/dolbeau/pm3fb/pm3fb.html
 S:	Maintained
 
 PHILIPS NINO PALM PC
@@ -1626,6 +1626,12 @@ M:	Kai.Makisara@kolumbus.fi
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
+SCTP PROTOCOL
+P:	Sridhar Samudrala	
+M:	sri@us.ibm.com
+L:	lksctp-developers@lists.sourceforge.net
+S:	Supported
+
 SCx200 CPU SUPPORT
 P:	Christer Weinigel
 M:	christer@weinigel.se
@@ -2067,8 +2073,8 @@ W:	http://www.kroah.com/linux/
 S:	Maintained
 
 USB SUBSYSTEM
-P:	Greg Kroah-Hartman
-M:	greg@kroah.com
+P:	Pete Zaitcev
+M:	zaitcev@redhat.com
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 W:	http://www.linux-usb.org
@@ -2104,7 +2110,6 @@ S:	Maintained
 
 VIA 82Cxxx AUDIO DRIVER
 P:	Jeff Garzik
-L:	linux-via@gtf.org
 S:	Odd fixes
 
 VIA RHINE NETWORK DRIVER
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Makefile linux-2.4.26-pre6/Makefile
--- linux-2.4.25/Makefile	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/Makefile	2004-03-25 00:20:47.000000000 +0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 25
-EXTRAVERSION =
+SUBLEVEL = 26
+EXTRAVERSION = -pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -223,7 +223,8 @@ CLEAN_FILES = \
 	drivers/tc/lk201-map.c \
 	net/khttpd/make_times_h \
 	net/khttpd/times.h \
-	submenu*
+	submenu* \
+	drivers/ieee1394/oui.c
 # directories removed with 'make clean'
 CLEAN_DIRS = \
 	modules
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/defconfig linux-2.4.26-pre6/arch/i386/defconfig
--- linux-2.4.25/arch/i386/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/defconfig	2004-03-25 00:17:36.000000000 +0000
@@ -2,7 +2,6 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_X86=y
-CONFIG_ISA=y
 # CONFIG_SBUS is not set
 CONFIG_UID16=y
 
@@ -31,12 +30,14 @@ CONFIG_MPENTIUMIII=y
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
 # CONFIG_MELAN is not set
 # CONFIG_MCRUSOE is not set
 # CONFIG_MWINCHIPC6 is not set
 # CONFIG_MWINCHIP2 is not set
 # CONFIG_MWINCHIP3D is not set
 # CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
 CONFIG_X86_WP_WORKS_OK=y
 CONFIG_X86_INVLPG=y
 CONFIG_X86_CMPXCHG=y
@@ -46,26 +47,29 @@ CONFIG_X86_POPAD_OK=y
 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_X86_L1_CACHE_SHIFT=5
-CONFIG_X86_TSC=y
+CONFIG_X86_HAS_TSC=y
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_PGE=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_F00F_WORKS_OK=y
 CONFIG_X86_MCE=y
 # CONFIG_TOSHIBA is not set
 # CONFIG_I8K is not set
 # CONFIG_MICROCODE is not set
 # CONFIG_X86_MSR is not set
 # CONFIG_X86_CPUID is not set
-# CONFIG_EDD is not set
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
 # CONFIG_HIGHMEM64G is not set
+# CONFIG_HIGHMEM is not set
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
-# CONFIG_MULTIQUAD is not set
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=32
+# CONFIG_X86_NUMA is not set
+# CONFIG_X86_TSC_DISABLE is not set
+CONFIG_X86_TSC=y
+CONFIG_HAVE_DEC_LOCK=y
 
 #
 # General setup
@@ -79,6 +83,7 @@ CONFIG_PCI=y
 CONFIG_PCI_GOANY=y
 CONFIG_PCI_BIOS=y
 CONFIG_PCI_DIRECT=y
+CONFIG_ISA=y
 CONFIG_PCI_NAMES=y
 # CONFIG_EISA is not set
 # CONFIG_MCA is not set
@@ -100,7 +105,6 @@ CONFIG_CARDBUS=y
 # CONFIG_HOTPLUG_PCI_COMPAQ is not set
 # CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
 # CONFIG_HOTPLUG_PCI_IBM is not set
-# CONFIG_HOTPLUG_PCI_ACPI is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
@@ -109,10 +113,17 @@ CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
+# CONFIG_OOM_KILLER is not set
 CONFIG_PM=y
 # CONFIG_APM is not set
 
 #
+# ACPI Support
+#
+# CONFIG_ACPI is not set
+CONFIG_ACPI_BOOT=y
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -137,12 +148,14 @@ CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_STATS is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -224,15 +237,6 @@ CONFIG_BLK_DEV_IDE=y
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
 # CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
@@ -246,8 +250,8 @@ CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_CMD640=y
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
-CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_GENERIC is not set
 CONFIG_IDEPCI_SHARE_IRQ=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -256,30 +260,29 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_ADMA100 is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_CMD680 is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
 CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+CONFIG_BLK_DEV_RZ1000=y
+# CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
@@ -291,6 +294,7 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
 # SCSI support
@@ -325,12 +329,14 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -370,6 +376,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
 
 #
 # PCMCIA SCSI adapter support
@@ -429,16 +436,19 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_NET_ISA is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
 # CONFIG_CS89x0 is not set
 # CONFIG_TULIP is not set
-# CONFIG_TC35815 is not set
 # CONFIG_DE4X5 is not set
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
 CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
 # CONFIG_LNE390 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -450,10 +460,11 @@ CONFIG_EEPRO100=y
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_NEW_RX_RESET is not set
+# CONFIG_8139_OLD_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
@@ -465,10 +476,12 @@ CONFIG_EEPRO100=y
 #
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_FDDI is not set
@@ -542,6 +555,7 @@ CONFIG_PCMCIA_RAYCS=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -583,13 +597,22 @@ CONFIG_PSMOUSE=y
 # Input core support is needed for joysticks
 #
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
 # CONFIG_AMD_RNG is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_DTLK is not set
@@ -605,9 +628,16 @@ CONFIG_AGP_INTEL=y
 CONFIG_AGP_I810=y
 CONFIG_AGP_VIA=y
 CONFIG_AGP_AMD=y
+# CONFIG_AGP_AMD_K8 is not set
 CONFIG_AGP_SIS=y
 CONFIG_AGP_ALI=y
 # CONFIG_AGP_SWORKS is not set
+# CONFIG_AGP_NVIDIA is not set
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -616,10 +646,12 @@ CONFIG_DRM=y
 #
 CONFIG_DRM_NEW=y
 CONFIG_DRM_TDFX=y
+# CONFIG_DRM_GAMMA is not set
 # CONFIG_DRM_R128 is not set
 CONFIG_DRM_RADEON=y
 CONFIG_DRM_I810=y
 CONFIG_DRM_I810_XFREE_41=y
+# CONFIG_DRM_I830 is not set
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 
@@ -627,7 +659,9 @@ CONFIG_DRM_I810_XFREE_41=y
 # PCMCIA character devices
 #
 # CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_SYNCLINK_CS is not set
 # CONFIG_MWAVE is not set
+# CONFIG_OBMOUSE is not set
 
 #
 # Multimedia devices
@@ -638,6 +672,7 @@ CONFIG_DRM_I810_XFREE_41=y
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_REISERFS_FS is not set
@@ -647,6 +682,9 @@ CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
@@ -664,6 +702,9 @@ CONFIG_RAMFS=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_NTFS_FS is not set
@@ -683,6 +724,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -691,9 +737,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -707,7 +755,6 @@ CONFIG_LOCKD=y
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 # CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
@@ -727,6 +774,7 @@ CONFIG_VGA_CONSOLE=y
 # Sound
 #
 CONFIG_SOUND=y
+# CONFIG_SOUND_ALI5455 is not set
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
@@ -738,6 +786,7 @@ CONFIG_SOUND_ES1371=y
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_FORTE is not set
 # CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_RME96XX is not set
 # CONFIG_SOUND_SONICVIBES is not set
@@ -748,6 +797,8 @@ CONFIG_SOUND_ES1371=y
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -760,7 +811,6 @@ CONFIG_USB=y
 #
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_LONG_TIMEOUT is not set
 
 #
 # USB Host Controller Drivers
@@ -768,13 +818,15 @@ CONFIG_USB=y
 # CONFIG_USB_EHCI_HCD is not set
 CONFIG_USB_UHCI_ALT=y
 # CONFIG_USB_OHCI is not set
+# CONFIG_USB_SL811HS_ALT is not set
+# CONFIG_USB_SL811HS is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_MIDI is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
@@ -783,6 +835,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_HP8200e is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
@@ -799,7 +852,10 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_KBD is not set
 # CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
 
 #
 # USB Imaging devices
@@ -837,39 +893,20 @@ CONFIG_USB_STORAGE=y
 # USB Serial Converter support
 #
 # CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
 
 #
 # USB Miscellaneous drivers
 #
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_TIGL is not set
 # CONFIG_USB_BRLVGER is not set
+# CONFIG_USB_LCD is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
 
 #
 # Bluetooth support
@@ -880,3 +917,16 @@ CONFIG_USB_STORAGE=y
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/acpi.c linux-2.4.26-pre6/arch/i386/kernel/acpi.c
--- linux-2.4.25/arch/i386/kernel/acpi.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/acpi.c	2004-03-25 00:21:30.000000000 +0000
@@ -49,14 +49,16 @@
 
 #define PREFIX			"ACPI: "
 
-int acpi_lapic = 0;
-int acpi_ioapic = 0;
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
 
+acpi_interrupt_flags acpi_sci_flags __initdata;
+int acpi_sci_override_gsi __initdata;
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_BOOT
 int acpi_noirq __initdata = 0;  /* skip ACPI IRQ initialization */
 int acpi_ht __initdata = 1;     /* enable HT */
 
@@ -214,6 +216,54 @@ acpi_parse_ioapic (
 	return 0;
 }
 
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_parse_sci_int_src_ovr(u8 bus_irq, u16 polarity, u16 trigger, u32 global_irq)
+{
+	if (trigger == 0)	/* compatible SCI trigger is level */
+		trigger = 3;
+
+	if (polarity == 0)	/* compatible SCI polarity is low */
+		polarity = 3;
+
+	/* Command-line over-ride via acpi_sci= */
+	if (acpi_sci_flags.trigger)
+		trigger = acpi_sci_flags.trigger;
+
+	if (acpi_sci_flags.polarity)
+		polarity = acpi_sci_flags.polarity;
+
+	mp_override_legacy_irq(bus_irq, polarity, trigger, global_irq);
+
+	/*
+	 * stash over-ride to indicate we've been here
+	 * and for later update of acpi_fadt
+	 */
+	acpi_sci_override_gsi = global_irq;
+	return;
+}
+
+static int __init
+acpi_parse_fadt(unsigned long phys, unsigned long size)
+{
+        struct fadt_descriptor_rev2 *fadt =0;
+
+        fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
+        if (!fadt) {
+                printk(KERN_WARNING PREFIX "Unable to map FADT\n");
+                return 0;
+        }
+
+#ifdef  CONFIG_ACPI_INTERPRETER
+        /* initialize sci_int early for INT_SRC_OVR MADT parsing */
+        acpi_fadt.sci_int = fadt->sci_int;
+#endif
+
+        return 0;
+}
+
 
 static int __init
 acpi_parse_int_src_ovr (
@@ -227,6 +277,13 @@ acpi_parse_int_src_ovr (
 
 	acpi_table_print_madt_entry(header);
 
+	if (intsrc->bus_irq == acpi_fadt.sci_int) {
+		acpi_parse_sci_int_src_ovr(intsrc->bus_irq,
+			intsrc->flags.polarity, intsrc->flags.trigger,
+			intsrc->global_irq);
+		return 0;
+	}
+
 	mp_override_legacy_irq (
 		intsrc->bus_irq,
 		intsrc->flags.polarity,
@@ -307,7 +364,7 @@ acpi_find_rsdp (void)
  * 	acpi_lapic = 1 if LAPIC found
  *	acpi_ioapic = 1 if IOAPIC found
  *	if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
- *	if acpi_blacklisted() acpi_disabled = 1;
+ *	if acpi_blacklisted() disable_acpi()
  *	acpi_irq_model=...
  *	...
  *
@@ -334,14 +391,14 @@ acpi_boot_init (void)
 	 */
 	result = acpi_table_init();
 	if (result) {
-		acpi_disabled = 1;
+		disable_acpi();
 		return result;
 	}
 
 	result = acpi_blacklisted();
 	if (result) {
 		printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
-		acpi_disabled = 1;
+		disable_acpi();
 		return result;
 	}
 
@@ -444,6 +501,9 @@ acpi_boot_init (void)
 	/* Build a default routing table for legacy (ISA) interrupts. */
 	mp_config_acpi_legacy_irqs();
 
+	/* Record sci_int for use when looking for MADT sci_int override */
+	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
+
 	result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
 	if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
@@ -451,6 +511,13 @@ acpi_boot_init (void)
 		return result;
 	}
 
+	/*
+	 * If BIOS did not supply an INT_SRC_OVR for the SCI
+	 * pretend we got one so we can set the SCI flags.
+	 */
+	if (!acpi_sci_override_gsi)
+		acpi_parse_sci_int_src_ovr(acpi_fadt.sci_int, 0, 0, acpi_fadt.sci_int);
+
 	result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
 	if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
@@ -472,17 +539,15 @@ acpi_boot_init (void)
 	return 0;
 }
 
-#endif /*CONFIG_ACPI_BOOT*/
 
 #ifdef	CONFIG_ACPI_BUS
 /*
- * "acpi_pic_sci=level" (current default)
- * programs the PIC-mode SCI to Level Trigger.
- * (NO-OP if the BIOS set Level Trigger already)
- *
- * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
- * it may require Edge Trigger -- use "acpi_pic_sci=edge"
- * (NO-OP if the BIOS set Edge Trigger already)
+ * acpi_pic_sci_set_trigger()
+ *
+ * use ELCR to set PIC-mode trigger type for SCI
+ *
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
+ * it may require Edge Trigger -- use "acpi_sci=edge"
  *
  * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
  * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
@@ -490,52 +555,33 @@ acpi_boot_init (void)
  * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
  */
 
-static __initdata int	acpi_pic_sci_trigger;	/* 0: level, 1: edge */
-
 void __init
-acpi_pic_sci_set_trigger(unsigned int irq)
+acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 {
 	unsigned char mask = 1 << (irq & 7);
 	unsigned int port = 0x4d0 + (irq >> 3);
 	unsigned char val = inb(port);
 
-	
+
 	printk(PREFIX "IRQ%d SCI:", irq);
 	if (!(val & mask)) {
 		printk(" Edge");
 
-		if (!acpi_pic_sci_trigger) {
+		if (trigger == 3) {
 			printk(" set to Level");
 			outb(val | mask, port);
 		}
 	} else {
 		printk(" Level");
 
-		if (acpi_pic_sci_trigger) {
+		if (trigger == 1) {
 			printk(" set to Edge");
-			outb(val | mask, port);
+			outb(val & ~mask, port);
 		}
 	}
 	printk(" Trigger.\n");
 }
 
-int __init
-acpi_pic_sci_setup(char *str)
-{
-	while (str && *str) {
-		if (strncmp(str, "level", 5) == 0)
-			acpi_pic_sci_trigger = 0;	/* force level trigger */
-		if (strncmp(str, "edge", 4) == 0)
-			acpi_pic_sci_trigger = 1;	/* force edge trigger */
-		str = strchr(str, ',');
-		if (str)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("acpi_pic_sci=", acpi_pic_sci_setup);
-
 #endif /* CONFIG_ACPI_BUS */
 
 
@@ -656,7 +702,8 @@ void acpi_restore_state_mem (void)
 void __init acpi_reserve_bootmem(void)
 {
 	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
-	printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address);
+	if (!acpi_wakeup_address)
+		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
 }
 
 void do_suspend_lowlevel_s4bios(int resume)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/dmi_scan.c linux-2.4.26-pre6/arch/i386/kernel/dmi_scan.c
--- linux-2.4.25/arch/i386/kernel/dmi_scan.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/dmi_scan.c	2004-03-25 00:19:05.000000000 +0000
@@ -482,13 +482,13 @@ static __init int print_if_true(struct d
 
 
 #ifdef	CONFIG_ACPI_BOOT
-extern int acpi_disabled, acpi_force, acpi_ht;
+extern int acpi_force;
 
-static __init __attribute__((unused)) int acpi_disable(struct dmi_blacklist *d) 
+static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) 
 { 
 	if (!acpi_force) { 
 		printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); 
-		acpi_disabled = 1;
+		disable_acpi();
 	} else { 
 		printk(KERN_NOTICE 
 		       "Warning: DMI blacklist says broken, but acpi forced\n"); 
@@ -504,7 +504,7 @@ static __init __attribute__((unused)) in
 { 
 	if (!acpi_force) { 
 		printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); 
-		acpi_disabled = 1; 
+		disable_acpi();
 		acpi_ht = 1; 
 	} else { 
 		printk(KERN_NOTICE 
@@ -839,7 +839,7 @@ static __initdata struct dmi_blacklist d
 	 *	Boxes that need ACPI disabled
 	 */
 
-	{ acpi_disable, "IBM Thinkpad", {
+	{ dmi_disable_acpi, "IBM Thinkpad", {
 			MATCH(DMI_BOARD_VENDOR, "IBM"),
 			MATCH(DMI_BOARD_NAME, "2629H1G"),
 			NO_MATCH, NO_MATCH }},
@@ -968,8 +968,7 @@ static __init void dmi_check_blacklist(v
 			if (disable && !acpi_force) { 
 				printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
 				printk(KERN_NOTICE "You can enable it with acpi=force\n");
-				acpi_disabled = 1; 
-				acpi_ht = 0;
+				disable_acpi();
 			} 
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/i386_ksyms.c linux-2.4.26-pre6/arch/i386/kernel/i386_ksyms.c
--- linux-2.4.25/arch/i386/kernel/i386_ksyms.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/i386_ksyms.c	2004-03-25 00:22:24.000000000 +0000
@@ -146,6 +146,10 @@ EXPORT_SYMBOL(smp_call_function);
 
 /* TLB flushing */
 EXPORT_SYMBOL(flush_tlb_page);
+
+/* HT support */
+EXPORT_SYMBOL(smp_num_siblings);
+EXPORT_SYMBOL(cpu_sibling_map);
 #endif
 
 #ifdef CONFIG_X86_IO_APIC
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/microcode.c linux-2.4.26-pre6/arch/i386/kernel/microcode.c
--- linux-2.4.25/arch/i386/kernel/microcode.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/microcode.c	2004-03-25 00:18:20.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *	Intel CPU Microcode Update driver for Linux
  *
- *	Copyright (C) 2000 Tigran Aivazian
+ *	Copyright (C) 2000-2004 Tigran Aivazian
  *
  *	This driver allows to upgrade microcode on Intel processors
  *	belonging to IA-32 family - PentiumPro, Pentium II, 
@@ -64,6 +64,10 @@
  *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
  *		because we no longer hold a copy of applied microcode 
  *		in kernel memory.
+ *	1.14	23 Feb 2004 Tigran Aivazian <tigran@veritas.com>
+ *		Restored devfs regular file entry point which was
+ *		accidentally removed when back-porting changes from the 2.6
+ *		version of the driver.
  */
 
 
@@ -73,6 +77,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/miscdevice.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 
@@ -84,8 +89,8 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) mi
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
 MODULE_LICENSE("GPL");
 
-#define MICROCODE_VERSION 	"1.13"
-#define MICRO_DEBUG 		1
+#define MICROCODE_VERSION 	"1.14"
+#define MICRO_DEBUG 		0
 #if MICRO_DEBUG
 #define dprintk(x...) printk(KERN_INFO x)
 #else
@@ -470,6 +475,7 @@ static int microcode_ioctl (struct inode
 	return -EINVAL;
 }
 
+/* shared between misc device and devfs regular file */
 static struct file_operations microcode_fops = {
 	.owner		= THIS_MODULE,
 	.write		= microcode_write,
@@ -483,29 +489,38 @@ static struct miscdevice microcode_dev =
 	.fops		= &microcode_fops,
 };
 
+static devfs_handle_t devfs_handle;
+
 static int __init microcode_init (void)
 {
 	int error;
 
 	error = misc_register(&microcode_dev);
-	if (error) {
+	if (error)
 		printk(KERN_ERR
 			"microcode: can't misc_register on minor=%d\n",
 			MICROCODE_MINOR);
-		return error;
+	devfs_handle = devfs_register(NULL, "cpu/microcode",
+			DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR, 
+			&microcode_fops, NULL);
+	if (devfs_handle == NULL && error) {
+		printk(KERN_ERR "microcode: failed to devfs_register()\n");
+		goto out;
 	}
-
+	error = 0;
 	printk(KERN_INFO 
-		"IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", 
-		MICROCODE_VERSION);
-	return 0;
+		"IA-32 Microcode Update Driver: v"
+		MICROCODE_VERSION " <tigran@veritas.com>\n");
+out:
+	return error;
 }
 
 static void __exit microcode_exit (void)
 {
 	misc_deregister(&microcode_dev);
-	printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", 
-			MICROCODE_VERSION);
+	devfs_unregister(devfs_handle);
+	printk(KERN_INFO "IA-32 Microcode Update Driver v" 
+		MICROCODE_VERSION " unregistered\n");
 }
 
 module_init(microcode_init)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/mpparse.c linux-2.4.26-pre6/arch/i386/kernel/mpparse.c
--- linux-2.4.25/arch/i386/kernel/mpparse.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/mpparse.c	2004-03-25 00:18:45.000000000 +0000
@@ -34,6 +34,9 @@
 
 /* Have we found an MP table */
 int smp_found_config;
+#ifdef	CONFIG_SMP
+extern unsigned int max_cpus;
+#endif
 
 /*
  * Various Linux-internal data structures created from the
@@ -229,11 +232,19 @@ void __init MP_processor_info (struct mp
 		boot_cpu_logical_apicid = logical_apicid;
 	}
 
-	if (num_processors >= NR_CPUS){
-		printk(KERN_WARNING "NR_CPUS limit of %i reached. Cannot "
-			"boot CPU(apicid 0x%x).\n", NR_CPUS, m->mpc_apicid);
+#ifdef	CONFIG_SMP
+	if (num_processors >= NR_CPUS) {
+		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+			" Processor ignored.\n", NR_CPUS);
+		return;
+	}
+	if (num_processors >= max_cpus) {
+		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+			" Processor ignored.\n", max_cpus);
 		return;
 	}
+#endif
+
 	num_processors++;
 
 	if (m->mpc_apicid > MAX_APICS) {
@@ -1118,7 +1129,7 @@ void __init mp_override_legacy_irq (
 	 *      erroneously sets the trigger to level, resulting in a HUGE 
 	 *      increase of timer interrupts!
 	 */
-	if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3))
+	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
 	intsrc.mpc_type = MP_INTSRC;
@@ -1139,7 +1150,7 @@ void __init mp_override_legacy_irq (
 	 * Otherwise create a new entry (e.g. global_irq == 2).
 	 */
 	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) 
+		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
 			&& (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) {
 			mp_irqs[i] = intsrc;
 			found = 1;
@@ -1200,13 +1211,14 @@ void __init mp_config_acpi_legacy_irqs (
 	 */
 	for (i = 0; i < 16; i++) {
 
-		if (i == 2) continue;			/* Don't connect IRQ2 */
+		if (i == 2)
+			continue;			/* Don't connect IRQ2 */
 
 		mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC;
 		mp_irqs[mp_irq_entries].mpc_irqflag = 0;	/* Conforming */
 		mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS;
 		mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
-		mp_irqs[mp_irq_entries].mpc_irqtype = i ? mp_INT : mp_ExtINT;   /* 8259A to #0 */
+		mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT;
 		mp_irqs[mp_irq_entries].mpc_srcbusirq = i;	   /* Identity mapped */
 		mp_irqs[mp_irq_entries].mpc_dstirq = i;
 
@@ -1227,70 +1239,6 @@ void __init mp_config_acpi_legacy_irqs (
 
 extern FADT_DESCRIPTOR acpi_fadt;
 
-void __init mp_config_ioapic_for_sci(int irq)
-{
-	int ioapic;
-	int ioapic_pin;
-	struct acpi_table_madt* madt;
-	struct acpi_table_int_src_ovr *entry = NULL;
-	acpi_interrupt_flags flags;
-	void *madt_end;
-	acpi_status status;
-
-	/*
-	 * Ensure that if there is an interrupt source override entry
-	 * for the ACPI SCI, we leave it as is. Unfortunately this involves
-	 * walking the MADT again.
-	 */
-	status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING,
-		(struct acpi_table_header **) &madt);
-	if (ACPI_SUCCESS(status)) {
-		madt_end = (void *) (unsigned long)madt + madt->header.length;
-
-		entry = (struct acpi_table_int_src_ovr *)
-                ((unsigned long) madt + sizeof(struct acpi_table_madt));
-
-		while ((void *) entry < madt_end) {
-                	if (entry->header.type == ACPI_MADT_INT_SRC_OVR &&
-			    acpi_fadt.sci_int == entry->bus_irq)
-				goto found;
-			
-                	entry = (struct acpi_table_int_src_ovr *)
-                	        ((unsigned long) entry + entry->header.length);
-        	}
-	}
-	/*
-	 * Although the ACPI spec says that the SCI should be level/low
-	 * don't reprogram it unless there is an explicit MADT OVR entry
-	 * instructing us to do so -- otherwise we break Tyan boards which
-	 * have the SCI wired edge/high but no MADT OVR.
-	 */
-	return;
-
-found:
-	/*
-	 * See the note at the end of ACPI 2.0b section
-	 * 5.2.10.8 for what this is about.
-	 */
-	flags = entry->flags;
-	acpi_fadt.sci_int = entry->global_irq;
-	irq = entry->global_irq;
-	
-	ioapic = mp_find_ioapic(irq);
-
-	ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
-
-	/*
-	 * MPS INTI flags:
-	 *  trigger: 0=default, 1=edge, 3=level
-	 *  polarity: 0=default, 1=high, 3=low
-	 * Per ACPI spec, default for SCI means level/low.
-	 */
-	io_apic_set_pci_routing(ioapic, ioapic_pin, irq, 
-		(flags.trigger == 1 ? 0 : 1), (flags.polarity == 1 ? 0 : 1));
-}
-
-
 #ifdef CONFIG_ACPI_PCI
 
 void __init mp_parse_prt (void)
@@ -1349,7 +1297,7 @@ void __init mp_parse_prt (void)
 			continue;
 		}
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 			entry->irq = irq;
 			continue;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/pci-irq.c linux-2.4.26-pre6/arch/i386/kernel/pci-irq.c
--- linux-2.4.25/arch/i386/kernel/pci-irq.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/pci-irq.c	2004-03-25 00:22:26.000000000 +0000
@@ -595,6 +595,7 @@ static __init int intel_router_probe(str
 		case PCI_DEVICE_ID_INTEL_82801E_0:
 		case PCI_DEVICE_ID_INTEL_82801EB_0:
 		case PCI_DEVICE_ID_INTEL_ESB_0:
+		case PCI_DEVICE_ID_INTEL_ICH6_0:
 			r->name = "PIIX/ICH";
 			r->get = pirq_piix_get;
 			r->set = pirq_piix_set;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/setup.c linux-2.4.26-pre6/arch/i386/kernel/setup.c
--- linux-2.4.25/arch/i386/kernel/setup.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/setup.c	2004-03-25 00:19:45.000000000 +0000
@@ -187,6 +187,7 @@ EXPORT_SYMBOL(acpi_disabled);
 #ifdef	CONFIG_ACPI_BOOT
 extern	int __initdata acpi_ht;
 int acpi_force __initdata = 0;
+extern acpi_interrupt_flags	acpi_sci_flags;
 #endif
 
 extern int blk_nohighio;
@@ -831,27 +832,43 @@ static void __init parse_cmdline_early (
 				}
 			}
 		}
+#ifdef	CONFIG_SMP
+		/*
+		 * If the BIOS enumerates physical processors before logical,
+		 * maxcpus=N at enumeration-time can be used to disable HT.
+		 */
+		else if (!memcmp(from, "maxcpus=", 8)) {
+			extern unsigned int max_cpus;
+
+			max_cpus = simple_strtoul(from + 8, NULL, 0);
+		}
+#endif
 
 #ifdef CONFIG_ACPI_BOOT
 		/* "acpi=off" disables both ACPI table parsing and interpreter */
 		else if (!memcmp(from, "acpi=off", 8)) {
-			acpi_ht = 0;
-			acpi_disabled = 1;
+			disable_acpi();
 		}
 
 		/* acpi=force to over-ride black-list */
 		else if (!memcmp(from, "acpi=force", 10)) { 
 			acpi_force = 1;
-			acpi_ht=1;
+			acpi_ht = 1;
 			acpi_disabled = 0;
 		} 
 
 		/* Limit ACPI to boot-time only, still enabled HT */
 		else if (!memcmp(from, "acpi=ht", 7)) { 
+			if (!acpi_force)
+				disable_acpi();
 			acpi_ht = 1; 
-			if (!acpi_force) acpi_disabled = 1; 
 		} 
 
+		/* acpi=strict disables out-of-spec workarounds */
+		else if (!memcmp(from, "acpi=strict", 11)) {
+			acpi_strict = 1;
+		}
+
 		else if (!memcmp(from, "pci=noacpi", 10)) { 
 			acpi_noirq_set();
 		}
@@ -859,6 +876,16 @@ static void __init parse_cmdline_early (
                 /* disable IO-APIC */
                 else if (!memcmp(from, "noapic", 6))
                         disable_ioapic_setup();
+
+		else if (!memcmp(from, "acpi_sci=edge", 13))
+			acpi_sci_flags.trigger =  1;
+		else if (!memcmp(from, "acpi_sci=level", 14))
+			acpi_sci_flags.trigger = 3;
+		else if (!memcmp(from, "acpi_sci=high", 13))
+			acpi_sci_flags.polarity = 1;
+		else if (!memcmp(from, "acpi_sci=low", 12))
+			acpi_sci_flags.polarity = 3;
+
 #endif
 		/*
 		 * highmem=size forces highmem to be exactly 'size' bytes.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/smpboot.c linux-2.4.26-pre6/arch/i386/kernel/smpboot.c
--- linux-2.4.25/arch/i386/kernel/smpboot.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/kernel/smpboot.c	2004-03-25 00:19:51.000000000 +0000
@@ -51,7 +51,7 @@
 static int smp_b_stepping;
 
 /* Setup configured maximum number of CPUs to activate */
-static int max_cpus = NR_CPUS;
+unsigned int max_cpus = NR_CPUS;
 
 /* Total count of live CPUs */
 int smp_num_cpus = 1;
@@ -77,10 +77,6 @@ int smp_threads_ready;
  *
  * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
  * activation entirely (the MPS table probe still happens, though).
- *
- * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- * greater than 0, limits the maximum number of CPUs activated in
- * SMP mode to <NUM>.
  */
 
 static int __init nosmp(char *str)
@@ -91,14 +87,6 @@ static int __init nosmp(char *str)
 
 __setup("nosmp", nosmp);
 
-static int __init maxcpus(char *str)
-{
-	get_option(&str, &max_cpus);
-	return 1;
-}
-
-__setup("maxcpus=", maxcpus);
-
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -1120,8 +1108,6 @@ void __init smp_boot_cpus(void)
 
 		if (!(phys_cpu_present_map & apicid_to_phys_cpu_present(apicid)))
 			continue;
-		if (max_cpus <= cpucount+1)
-			continue;
 
 		do_boot_cpu(apicid);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/mm/init.c linux-2.4.26-pre6/arch/i386/mm/init.c
--- linux-2.4.25/arch/i386/mm/init.c	2003-06-13 14:51:29.000000000 +0000
+++ linux-2.4.26-pre6/arch/i386/mm/init.c	2004-03-25 00:21:13.000000000 +0000
@@ -510,7 +510,15 @@ void __init mem_init(void)
 
 	if (!mem_map)
 		BUG();
-	
+#ifdef CONFIG_HIGHMEM
+	/* check that fixmap and pkmap do not overlap */
+	if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
+		printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n");
+		printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
+				PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START);
+		BUG();
+	}
+#endif
 	set_max_mapnr_init();
 
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/ia32/ia32_signal.c linux-2.4.26-pre6/arch/ia64/ia32/ia32_signal.c
--- linux-2.4.25/arch/ia64/ia32/ia32_signal.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/ia32/ia32_signal.c	2004-03-25 00:17:08.000000000 +0000
@@ -615,7 +615,7 @@ sys32_rt_sigtimedwait (sigset32_t *uthes
 			return -EFAULT;
 	}
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
+	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL, sigsetsize);
 	set_fs(old_fs);
 	if (ret >= 0 && uinfo) {
 		if (copy_siginfo_to_user32(uinfo, &info))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/Makefile linux-2.4.26-pre6/arch/ia64/kernel/Makefile
--- linux-2.4.25/arch/ia64/kernel/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/Makefile	2004-03-25 00:22:24.000000000 +0000
@@ -11,7 +11,7 @@ all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
 
-export-objs := ia64_ksyms.o
+export-objs := ia64_ksyms.o unwind.o
 
 obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_lsapic.o ivt.o \
 	 machvec.o pal.o process.o perfmon.o ptrace.o sal.o salinfo.o semaphore.o setup.o	 \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/acpi.c linux-2.4.26-pre6/arch/ia64/kernel/acpi.c
--- linux-2.4.25/arch/ia64/kernel/acpi.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/acpi.c	2004-03-25 00:19:54.000000000 +0000
@@ -65,8 +65,6 @@ void (*pm_power_off) (void);
 
 unsigned char acpi_kbd_controller_present = 1;
 
-int acpi_disabled __initdata;	/* XXX this shouldn't be needed---we can't boot without ACPI! */
-
 const char *
 acpi_get_sysname (void)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/ia64_ksyms.c linux-2.4.26-pre6/arch/ia64/kernel/ia64_ksyms.c
--- linux-2.4.25/arch/ia64/kernel/ia64_ksyms.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/ia64_ksyms.c	2004-03-25 00:19:39.000000000 +0000
@@ -170,6 +170,8 @@ EXPORT_SYMBOL(pfm_install_alternate_sysw
 EXPORT_SYMBOL(pfm_remove_alternate_syswide_subsystem);
 #endif
 
+#ifdef CONFIG_ACPI
 #include <linux/acpi.h>
 extern acpi_status acpi_hp_csr_space(acpi_handle, u64 *, u64 *);
 EXPORT_SYMBOL(acpi_hp_csr_space);
+#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/mca.c linux-2.4.26-pre6/arch/ia64/kernel/mca.c
--- linux-2.4.25/arch/ia64/kernel/mca.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/mca.c	2004-03-25 00:19:43.000000000 +0000
@@ -6,7 +6,7 @@
  * Copyright (C) 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
- * Copyright (C) 2002 Dell Computer Corporation
+ * Copyright (C) 2002 Dell Inc.
  * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
  *
  * Copyright (C) 2002 Intel
@@ -18,7 +18,7 @@
  * Copyright (C) 2000 Intel
  * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com)
  *
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
  *
  * 03/04/15 D. Mosberger Added INIT backtrace support.
@@ -40,6 +40,14 @@
  * 2003-12-08 Keith Owens <kaos@sgi.com>
  *            smp_call_function() must not be called from interrupt context (can
  *            deadlock on tasklist_lock).  Use keventd to call smp_call_function().
+ *
+ * 2004-02-01 Keith Owens <kaos@sgi.com>
+ *            Avoid deadlock when using printk() for MCA and INIT records.
+ *            Delete all record printing code, moved to salinfo_decode in user space.
+ *            Mark variables and functions static where possible.
+ *            Delete dead variables and functions.
+ *            Reorder to remove the need for forward declarations and to consolidate
+ *            related code.
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -67,9 +75,12 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 
-#undef MCA_PRT_XTRA_DATA
+#if defined(IA64_MCA_DEBUG_INFO)
+# define IA64_MCA_DEBUG(fmt...)	printk(fmt)
+#else
+# define IA64_MCA_DEBUG(fmt...)
+#endif
 
-#define print_symbol(fmt, addr)	printk(fmt, "(no symbol)");
 extern void show_stack(struct task_struct *);
 
 typedef struct ia64_fptr {
@@ -77,7 +88,7 @@ typedef struct ia64_fptr {
 	unsigned long gp;
 } ia64_fptr_t;
 
-ia64_mc_info_t			ia64_mc_info;
+/* Used by mca_asm.S */
 ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;
 ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;
 u64				ia64_mca_proc_state_dump[512];
@@ -85,54 +96,17 @@ u64				ia64_mca_stack[1024] __attribute_
 u64				ia64_mca_stackframe[32];
 u64				ia64_mca_bspstore[1024];
 u64				ia64_init_stack[INIT_TASK_SIZE/8] __attribute__((aligned(16)));
-u64				ia64_os_mca_recovery_successful;
 u64				ia64_mca_serialize;
-static void			ia64_mca_wakeup_ipi_wait(void);
-static void			ia64_mca_wakeup(int cpu);
-static void			ia64_mca_wakeup_all(void);
-static void			ia64_log_init(int);
+
+/* In mca_asm.S */
 extern void			ia64_monarch_init_handler (void);
 extern void			ia64_slave_init_handler (void);
-static u64			ia64_log_get(int sal_info_type, u8 **buffer);
-extern struct hw_interrupt_type	irq_type_iosapic_level;
-
-struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS];
-
-static struct irqaction cmci_irqaction = {
-	.handler =	ia64_mca_cmc_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"cmc_hndlr"
-};
-
-static struct irqaction cmcp_irqaction = {
-	.handler =	ia64_mca_cmc_int_caller,
-	.flags =	SA_INTERRUPT,
-	.name =		"cmc_poll"
-};
-
-static struct irqaction mca_rdzv_irqaction = {
-	.handler =	ia64_mca_rendez_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"mca_rdzv"
-};
 
-static struct irqaction mca_wkup_irqaction = {
-	.handler =	ia64_mca_wakeup_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"mca_wkup"
-};
+static ia64_mc_info_t		ia64_mc_info;
 
-static struct irqaction mca_cpe_irqaction = {
-	.handler =	ia64_mca_cpe_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"cpe_hndlr"
-};
+extern struct hw_interrupt_type	irq_type_iosapic_level;
 
-static struct irqaction mca_cpep_irqaction = {
-	.handler =	ia64_mca_cpe_int_caller,
-	.flags =	SA_INTERRUPT,
-	.name =		"cpe_poll"
-};
+struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS];
 
 #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
 #define MIN_CPE_POLL_INTERVAL (2*60*HZ)  /* 2 minutes */
@@ -156,69 +130,163 @@ static int cmc_polling_enabled = 1;
  */
 static int cpe_poll_enabled = 1;
 
-extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size);
+extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
 
 static struct tq_struct	cmc_disable_tq, cmc_enable_tq;
 
 /*
+ * IA64_MCA log support
+ */
+#define IA64_MAX_LOGS		2	/* Double-buffering for nested MCAs */
+#define IA64_MAX_LOG_TYPES      4   /* MCA, INIT, CMC, CPE */
+
+typedef struct ia64_state_log_s
+{
+	spinlock_t	isl_lock;
+	int		isl_index;
+	unsigned long	isl_count;
+	ia64_err_rec_t  *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
+} ia64_state_log_t;
+
+static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
+
+#define IA64_LOG_ALLOCATE(it, size) \
+	{ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \
+		(ia64_err_rec_t *)alloc_bootmem(size); \
+	ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \
+		(ia64_err_rec_t *)alloc_bootmem(size);}
+#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
+#define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
+#define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
+#define IA64_LOG_NEXT_INDEX(it)    ia64_state_log[it].isl_index
+#define IA64_LOG_CURR_INDEX(it)    1 - ia64_state_log[it].isl_index
+#define IA64_LOG_INDEX_INC(it) \
+    {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \
+    ia64_state_log[it].isl_count++;}
+#define IA64_LOG_INDEX_DEC(it) \
+    ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
+#define IA64_LOG_NEXT_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
+#define IA64_LOG_CURR_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
+#define IA64_LOG_COUNT(it)         ia64_state_log[it].isl_count
+
+/*
+ * ia64_log_init
+ *	Reset the OS ia64 log buffer
+ * Inputs   :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
+ * Outputs	:	None
+ */
+static void
+ia64_log_init(int sal_info_type)
+{
+	u64	max_size = 0;
+
+	IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
+	IA64_LOG_LOCK_INIT(sal_info_type);
+
+	// SAL will tell us the maximum size of any error record of this type
+	max_size = ia64_sal_get_state_info_size(sal_info_type);
+	if (!max_size)
+		/* alloc_bootmem() doesn't like zero-sized allocations! */
+		return;
+
+	// set up OS data structures to hold error info
+	IA64_LOG_ALLOCATE(sal_info_type, max_size);
+	memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size);
+	memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size);
+}
+
+/*
+ * ia64_log_get
+ *
+ *	Get the current MCA log from SAL and copy it into the OS log buffer.
+ *
+ *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
+ *              irq_safe    whether you can use printk at this point
+ *  Outputs :   size        (total record length)
+ *              *buffer     (ptr to error record)
+ *
+ */
+static u64
+ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
+{
+	sal_log_record_header_t     *log_buffer;
+	u64                         total_len = 0;
+	int                         s;
+
+	IA64_LOG_LOCK(sal_info_type);
+
+	/* Get the process state information */
+	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
+
+	total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
+
+	if (total_len) {
+		IA64_LOG_INDEX_INC(sal_info_type);
+		IA64_LOG_UNLOCK(sal_info_type);
+		if (irq_safe) {
+			IA64_MCA_DEBUG("%s: SAL error record type %d retrieved. "
+				       "Record length = %ld\n", __FUNCTION__, sal_info_type, total_len);
+		}
+		*buffer = (u8 *) log_buffer;
+		return total_len;
+	} else {
+		IA64_LOG_UNLOCK(sal_info_type);
+		return 0;
+	}
+}
+
+/*
  *  ia64_mca_log_sal_error_record
  *
- *  This function retrieves a specified error record type from SAL,
- *  wakes up any processes waiting for error records, and sends it to
- *  the system log.
+ *  This function retrieves a specified error record type from SAL
+ *  and wakes up any processes waiting for error records.
  *
  *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT)
- *  Outputs :   platform error status
  */
-int
-ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init)
+static void
+ia64_mca_log_sal_error_record(int sal_info_type)
 {
 	u8 *buffer;
 	u64 size;
-	int platform_err;
+	int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT;
+	static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
 
-	size = ia64_log_get(sal_info_type, &buffer);
+	size = ia64_log_get(sal_info_type, &buffer, irq_safe);
 	if (!size)
-		return 0;
+		return;
 
-	/* TODO:
-	 * 1. analyze error logs to determine recoverability
-	 * 2. perform error recovery procedures, if applicable
-	 * 3. set ia64_os_mca_recovery_successful flag, if applicable
-	 */
+	salinfo_log_wakeup(sal_info_type, buffer, size, irq_safe);
+
+	if (irq_safe)
+		printk(KERN_INFO "CPU %d: SAL log contains %s error record\n",
+			smp_processor_id(),
+			sal_info_type < ARRAY_SIZE(rec_name) ? rec_name[sal_info_type] : "UNKNOWN");
 
-	salinfo_log_wakeup(sal_info_type, buffer, size);
-	platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
 	/* Clear logs from corrected errors in case there's no user-level logger */
 	if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC)
 		ia64_sal_clear_state_info(sal_info_type);
-
-	return platform_err;
 }
 
 /*
  * platform dependent error handling
  */
 #ifndef PLATFORM_MCA_HANDLERS
-void
-mca_handler_platform (void)
-{
-
-}
 
-void
+static void
 ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
-	IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n",
-		       smp_processor_id(), cpe_irq);
+	IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n",
+		       __FUNCTION__, smp_processor_id(), cpe_irq);
 
 	/* SAL spec states this should run w/ interrupts enabled */
 	local_irq_enable();
 
 	/* Get the CMC error record and log it */
-	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0);
+	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
 }
 
+#define print_symbol(fmt, addr)	printk(fmt, "(no symbol)");
+
 static void
 show_min_state (pal_min_state_area_t *minstate)
 {
@@ -357,7 +425,7 @@ fetch_min_state (pal_min_state_area_t *m
 	PUT_NAT_BIT(sw->caller_unat, &pt->r30);	PUT_NAT_BIT(sw->caller_unat, &pt->r31);
 }
 
-void
+static void
 init_handler_platform (pal_min_state_area_t *ms,
 		       struct pt_regs *pt, struct switch_stack *sw)
 {
@@ -404,45 +472,7 @@ init_handler_platform (pal_min_state_are
 	while (1);			/* hang city if no debugger */
 }
 
-/*
- * ia64_mca_init_platform
- *
- *  External entry for platform specific MCA initialization.
- *
- *  Inputs
- *      None
- *
- *  Outputs
- *      None
- */
-void
-ia64_mca_init_platform (void)
-{
-
-}
-
-/*
- *  ia64_mca_check_errors
- *
- *  External entry to check for error records which may have been posted by SAL
- *  for a prior failure.
- *
- *  Inputs  :   None
- *
- *  Outputs :   None
- */
-int
-ia64_mca_check_errors (void)
-{
-	/*
-	 *  If there is an MCA error record pending, get it and log it.
-	 */
-	printk("CPU %d: checking for saved MCA error records\n", smp_processor_id());
-	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 1);
-
-	return 0;
-}
-
+#ifdef CONFIG_ACPI
 /*
  * ia64_mca_register_cpev
  *
@@ -462,14 +492,15 @@ ia64_mca_register_cpev (int cpev)
 
 	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0);
 	if (isrv.status) {
-		printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected "
-		       "Platform Error interrupt vector with SAL.\n");
+		printk(KERN_ERR "Failed to register Corrected Platform "
+		       "Error interrupt vector with SAL (status %ld)\n", isrv.status);
 		return;
 	}
 
-	IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "
-		       "vector %#x setup and enabled\n", cpev);
+	IA64_MCA_DEBUG("%s: corrected platform error "
+		       "vector %#x setup and enabled\n", __FUNCTION__, cpev);
 }
+#endif /* CONFIG_ACPI */
 
 #endif /* PLATFORM_MCA_HANDLERS */
 
@@ -495,12 +526,12 @@ ia64_mca_cmc_vector_setup (void)
 	cmcv.cmcv_vector	= IA64_CMC_VECTOR;
 	ia64_set_cmcv(cmcv.cmcv_regval);
 
-	IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected "
+	IA64_MCA_DEBUG("%s: CPU %d corrected "
 		       "machine check vector %#x setup and enabled.\n",
-		       smp_processor_id(), IA64_CMC_VECTOR);
+		       __FUNCTION__, smp_processor_id(), IA64_CMC_VECTOR);
 
-	IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n",
-		       smp_processor_id(), ia64_get_cmcv());
+	IA64_MCA_DEBUG("%s: CPU %d CMCV = %#016lx\n",
+		       __FUNCTION__, smp_processor_id(), ia64_get_cmcv());
 }
 
 /*
@@ -515,7 +546,7 @@ ia64_mca_cmc_vector_setup (void)
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_vector_disable (void *dummy)
 {
 	cmcv_reg_t	cmcv;
@@ -525,9 +556,9 @@ ia64_mca_cmc_vector_disable (void *dummy
 	cmcv.cmcv_mask = 1; /* Mask/disable interrupt */
 	ia64_set_cmcv(cmcv.cmcv_regval);
 
-	IA64_MCA_DEBUG("ia64_mca_cmc_vector_disable: CPU %d corrected "
+	IA64_MCA_DEBUG("%s: CPU %d corrected "
 		       "machine check vector %#x disabled.\n",
-		       smp_processor_id(), cmcv.cmcv_vector);
+		       __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector);
 }
 
 /*
@@ -542,7 +573,7 @@ ia64_mca_cmc_vector_disable (void *dummy
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_vector_enable (void *dummy)
 {
 	cmcv_reg_t	cmcv;
@@ -552,63 +583,9 @@ ia64_mca_cmc_vector_enable (void *dummy)
 	cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */
 	ia64_set_cmcv(cmcv.cmcv_regval);
 
-	IA64_MCA_DEBUG("ia64_mca_cmc_vector_enable: CPU %d corrected "
+	IA64_MCA_DEBUG("%s: CPU %d corrected "
 		       "machine check vector %#x enabled.\n",
-		       smp_processor_id(), cmcv.cmcv_vector);
-}
-
-
-#if defined(MCA_TEST)
-
-sal_log_processor_info_t	slpi_buf;
-
-void
-mca_test(void)
-{
-	slpi_buf.valid.psi_static_struct = 1;
-	slpi_buf.valid.num_cache_check = 1;
-	slpi_buf.valid.num_tlb_check = 1;
-	slpi_buf.valid.num_bus_check = 1;
-	slpi_buf.valid.processor_static_info.minstate = 1;
-	slpi_buf.valid.processor_static_info.br = 1;
-	slpi_buf.valid.processor_static_info.cr = 1;
-	slpi_buf.valid.processor_static_info.ar = 1;
-	slpi_buf.valid.processor_static_info.rr = 1;
-	slpi_buf.valid.processor_static_info.fr = 1;
-
-	ia64_os_mca_dispatch();
-}
-
-#endif /* #if defined(MCA_TEST) */
-
-
-/*
- *  verify_guid
- *
- *  Compares a test guid to a target guid and returns result.
- *
- *  Inputs
- *      test_guid *     (ptr to guid to be verified)
- *      target_guid *   (ptr to standard guid to be verified against)
- *
- *  Outputs
- *      0               (test verifies against target)
- *      non-zero        (test guid does not verify)
- */
-static int
-verify_guid (efi_guid_t *test, efi_guid_t *target)
-{
-	int     rc;
-#ifdef IA64_MCA_DEBUG_INFO
-	char out[40];
-#endif
-
-	if ((rc = efi_guidcmp(*test, *target))) {
-		IA64_MCA_DEBUG(KERN_DEBUG
-			       "verify_guid: invalid GUID = %s\n",
-			       efi_guid_unparse(test, out));
-	}
-	return rc;
+		       __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector);
 }
 
 /*
@@ -642,225 +619,39 @@ ia64_mca_cmc_vector_enable_keventd(void 
 }
 
 /*
- * ia64_mca_init
- *
- *  Do all the system level mca specific initialization.
- *
- *	1. Register spinloop and wakeup request interrupt vectors
- *
- *	2. Register OS_MCA handler entry point
- *
- *	3. Register OS_INIT handler entry point
- *
- *  4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
+ * ia64_mca_wakeup_ipi_wait
  *
- *  Note that this initialization is done very early before some kernel
- *  services are available.
+ *	Wait for the inter-cpu interrupt to be sent by the
+ *	monarch processor once it is done with handling the
+ *	MCA.
  *
  *  Inputs  :   None
- *
  *  Outputs :   None
  */
-void __init
-ia64_mca_init(void)
+static void
+ia64_mca_wakeup_ipi_wait(void)
 {
-	ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
-	ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
-	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
-	int i;
-	s64 rc;
-	struct ia64_sal_retval isrv;
-	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
+	int	irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
+	int	irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
+	u64	irr = 0;
 
-	IA64_MCA_DEBUG("ia64_mca_init: begin\n");
-
-	INIT_TQUEUE(&cmc_disable_tq, ia64_mca_cmc_vector_disable_keventd, NULL);
-	INIT_TQUEUE(&cmc_enable_tq, ia64_mca_cmc_vector_enable_keventd, NULL);
-
-	/* initialize recovery success indicator */
-	ia64_os_mca_recovery_successful = 0;
-
-	/* Clear the Rendez checkin flag for all cpus */
-	for(i = 0 ; i < NR_CPUS; i++)
-		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
-
-	/*
-	 * Register the rendezvous spinloop and wakeup mechanism with SAL
-	 */
-
-	/* Register the rendezvous interrupt vector with SAL */
-	while (1) {
-		isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
-					      SAL_MC_PARAM_MECHANISM_INT,
-					      IA64_MCA_RENDEZ_VECTOR,
-					      timeout,
-					      SAL_MC_PARAM_RZ_ALWAYS);
-		rc = isrv.status;
-		if (rc == 0)
-			break;
-		if (rc == -2) {
-			printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from "
-				"%ld to %ld\n", timeout, isrv.v0);
-			timeout = isrv.v0;
-			continue;
-		}
-		printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt "
-		       "with SAL.  rc = %ld\n", rc);
-		return;
-	}
-
-	/* Register the wakeup interrupt vector with SAL */
-	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
-				      SAL_MC_PARAM_MECHANISM_INT,
-				      IA64_MCA_WAKEUP_VECTOR,
-				      0, 0);
-	rc = isrv.status;
-	if (rc) {
-		printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL.  "
-		       "rc = %ld\n", rc);
-		return;
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n");
-
-	ia64_mc_info.imi_mca_handler        = ia64_tpa(mca_hldlr_ptr->fp);
-	/*
-	 * XXX - disable SAL checksum by setting size to 0; should be
-	 *	ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch);
-	 */
-	ia64_mc_info.imi_mca_handler_size	= 0;
-
-	/* Register the os mca handler with SAL */
-	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
-				       ia64_mc_info.imi_mca_handler,
-				       ia64_tpa(mca_hldlr_ptr->gp),
-				       ia64_mc_info.imi_mca_handler_size,
-				       0, 0, 0)))
-	{
-		printk(KERN_ERR "ia64_mca_init: Failed to register os mca handler with SAL.  "
-		       "rc = %ld\n", rc);
-		return;
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",
-		       ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp));
-
-	/*
-	 * XXX - disable SAL checksum by setting size to 0, should be
-	 * IA64_INIT_HANDLER_SIZE
-	 */
-	ia64_mc_info.imi_monarch_init_handler		= ia64_tpa(mon_init_ptr->fp);
-	ia64_mc_info.imi_monarch_init_handler_size	= 0;
-	ia64_mc_info.imi_slave_init_handler		= ia64_tpa(slave_init_ptr->fp);
-	ia64_mc_info.imi_slave_init_handler_size	= 0;
-
-	IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n",
-		       ia64_mc_info.imi_monarch_init_handler);
-
-	/* Register the os init handler with SAL */
-	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
-				       ia64_mc_info.imi_monarch_init_handler,
-				       ia64_tpa(ia64_get_gp()),
-				       ia64_mc_info.imi_monarch_init_handler_size,
-				       ia64_mc_info.imi_slave_init_handler,
-				       ia64_tpa(ia64_get_gp()),
-				       ia64_mc_info.imi_slave_init_handler_size)))
-	{
-		printk(KERN_ERR "ia64_mca_init: Failed to register m/s init handlers with SAL. "
-		       "rc = %ld\n", rc);
-		return;
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n");
-
-	/*
-	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
-	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
-	 */
-	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
-	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
-	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */
-
-	/* Setup the MCA rendezvous interrupt vector */
-	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
-
-	/* Setup the MCA wakeup interrupt vector */
-	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
-
-	/* Setup the CPE interrupt vector */
-	{
-		irq_desc_t *desc;
-		unsigned int irq;
-		int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
-
-		if (cpev >= 0) {
-			for (irq = 0; irq < NR_IRQS; ++irq)
-				if (irq_to_vector(irq) == cpev) {
-					desc = irq_desc(irq);
-					desc->status |= IRQ_PER_CPU;
-					desc->handler = &irq_type_iosapic_level;
-					setup_irq(irq, &mca_cpe_irqaction);
-				}
-			ia64_mca_register_cpev(cpev);
-		}
-	}
-
-	/* Initialize the areas set aside by the OS to buffer the
-	 * platform/processor error states for MCA/INIT/CMC
-	 * handling.
-	 */
-	ia64_log_init(SAL_INFO_TYPE_MCA);
-	ia64_log_init(SAL_INFO_TYPE_INIT);
-	ia64_log_init(SAL_INFO_TYPE_CMC);
-	ia64_log_init(SAL_INFO_TYPE_CPE);
-
-#if defined(MCA_TEST)
-	mca_test();
-#endif /* #if defined(MCA_TEST) */
-
-	printk(KERN_INFO "Mca related initialization done\n");
-
-	/* commented out because this is done elsewhere */
-#if 0
-	/* Do post-failure MCA error logging */
-	ia64_mca_check_errors();
-#endif
-}
-
-/*
- * ia64_mca_wakeup_ipi_wait
- *
- *	Wait for the inter-cpu interrupt to be sent by the
- *	monarch processor once it is done with handling the
- *	MCA.
- *
- *  Inputs  :   None
- *  Outputs :   None
- */
-void
-ia64_mca_wakeup_ipi_wait(void)
-{
-	int	irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
-	int	irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
-	u64	irr = 0;
-
-	do {
-		switch(irr_num) {
-		      case 0:
-			irr = ia64_get_irr0();
-			break;
-		      case 1:
-			irr = ia64_get_irr1();
-			break;
-		      case 2:
-			irr = ia64_get_irr2();
-			break;
-		      case 3:
-			irr = ia64_get_irr3();
-			break;
-		}
-	} while (!(irr & (1UL << irr_bit))) ;
-}
+	do {
+		switch(irr_num) {
+		      case 0:
+			irr = ia64_get_irr0();
+			break;
+		      case 1:
+			irr = ia64_get_irr1();
+			break;
+		      case 2:
+			irr = ia64_get_irr2();
+			break;
+		      case 3:
+			irr = ia64_get_irr3();
+			break;
+		}
+	} while (!(irr & (1UL << irr_bit))) ;
+}
 
 /*
  * ia64_mca_wakeup
@@ -871,7 +662,7 @@ ia64_mca_wakeup_ipi_wait(void)
  *  Inputs  :   cpuid
  *  Outputs :   None
  */
-void
+static void
 ia64_mca_wakeup(int cpu)
 {
 	platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
@@ -887,7 +678,7 @@ ia64_mca_wakeup(int cpu)
  *  Inputs  :   None
  *  Outputs :   None
  */
-void
+static void
 ia64_mca_wakeup_all(void)
 {
 	int cpu;
@@ -912,7 +703,7 @@ ia64_mca_wakeup_all(void)
  *  Inputs  :   None
  *  Outputs :   None
  */
-void
+static void
 ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
 {
 	unsigned long flags;
@@ -937,7 +728,6 @@ ia64_mca_rendez_int_handler(int rendez_i
 	local_irq_restore(flags);
 }
 
-
 /*
  * ia64_mca_wakeup_int_handler
  *
@@ -953,7 +743,7 @@ ia64_mca_rendez_int_handler(int rendez_i
  *  Outputs :   None
  *
  */
-void
+static void
 ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
 {
 }
@@ -972,11 +762,9 @@ ia64_mca_wakeup_int_handler(int wakeup_i
  *  Outputs :   None
  */
 
-void
-ia64_return_to_sal_check(void)
+static void
+ia64_return_to_sal_check(int recover)
 {
-	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
-		&ia64_sal_to_os_handoff_state.proc_state_param;
 
 	/* Copy over some relevant stuff from the sal_to_os_mca_handoff
 	 * so that it can be used at the time of os_mca_to_sal_handoff
@@ -987,15 +775,10 @@ ia64_return_to_sal_check(void)
 	ia64_os_to_sal_handoff_state.imots_sal_check_ra =
 		ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
 
-	/*
-	 * Did we correct the error? At the moment the only error that
-	 * we fix is a TLB error, if any other kind of error occurred
-	 * we must reboot.
-	 */
-	if (psp->cc == 1 && psp->bc == 1 && psp->rc == 1 && psp->uc == 1)
-		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
-	else
+	if (recover)
 		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
+	else
+		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
 
 	/* Default = tell SAL to return to same context */
 	ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;
@@ -1024,16 +807,12 @@ ia64_return_to_sal_check(void)
 void
 ia64_mca_ucmc_handler(void)
 {
-	int platform_err = 0;
+	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
+		&ia64_sal_to_os_handoff_state.proc_state_param;
+	int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc);
 
 	/* Get the MCA error record and log it */
-	platform_err = ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 0);
-
-	/*
-	 *  Do Platform-specific mca error handling if required.
-	 */
-	if (platform_err)
-		mca_handler_platform();
+	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
 
 	/*
 	 *  Wakeup all the processors which are spinning in the rendezvous
@@ -1042,7 +821,7 @@ ia64_mca_ucmc_handler(void)
 	ia64_mca_wakeup_all();
 
 	/* Return to SAL */
-	ia64_return_to_sal_check();
+	ia64_return_to_sal_check(recover);
 }
 
 /*
@@ -1060,21 +839,21 @@ ia64_mca_ucmc_handler(void)
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
 {
 	static unsigned long	cmc_history[CMC_HISTORY_LENGTH];
 	static int		index;
 	static spinlock_t	cmc_history_lock = SPIN_LOCK_UNLOCKED;
 
-	IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n",
-		       cmc_irq, smp_processor_id());
+	IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
+		       __FUNCTION__, cmc_irq, smp_processor_id());
 
 	/* SAL spec states this should run w/ interrupts enabled */
 	local_irq_enable();
 
 	/* Get the CMC error record and log it */
-	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC, 0);
+	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
 
 	spin_lock(&cmc_history_lock);
 	if (!cmc_polling_enabled) {
@@ -1098,7 +877,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, vo
 			 * make sure there's a log somewhere that indicates
 			 * something is generating more than we can handle.
 			 */
-			printk(KERN_WARNING "%s: WARNING: Switching to polling CMC handler, error records may be lost\n", __FUNCTION__);
+			printk(KERN_WARNING "WARNING: Switching to polling CMC handler; error records may be lost\n");
 
 			mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
 
@@ -1114,41 +893,6 @@ ia64_mca_cmc_int_handler(int cmc_irq, vo
 }
 
 /*
- * IA64_MCA log support
- */
-#define IA64_MAX_LOGS		2	/* Double-buffering for nested MCAs */
-#define IA64_MAX_LOG_TYPES      4   /* MCA, INIT, CMC, CPE */
-
-typedef struct ia64_state_log_s
-{
-	spinlock_t	isl_lock;
-	int		isl_index;
-	unsigned long	isl_count;
-	ia64_err_rec_t  *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
-} ia64_state_log_t;
-
-static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
-
-#define IA64_LOG_ALLOCATE(it, size) \
-	{ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \
-		(ia64_err_rec_t *)alloc_bootmem(size); \
-	ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \
-		(ia64_err_rec_t *)alloc_bootmem(size);}
-#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
-#define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
-#define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
-#define IA64_LOG_NEXT_INDEX(it)    ia64_state_log[it].isl_index
-#define IA64_LOG_CURR_INDEX(it)    1 - ia64_state_log[it].isl_index
-#define IA64_LOG_INDEX_INC(it) \
-    {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \
-    ia64_state_log[it].isl_count++;}
-#define IA64_LOG_INDEX_DEC(it) \
-    ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
-#define IA64_LOG_NEXT_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
-#define IA64_LOG_CURR_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
-#define IA64_LOG_COUNT(it)         ia64_state_log[it].isl_count
-
-/*
  *  ia64_mca_cmc_int_caller
  *
  * 	Triggered by sw interrupt from CMC polling routine.  Calls
@@ -1162,7 +906,7 @@ static ia64_state_log_t ia64_state_log[I
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
 	static int start_count = -1;
@@ -1177,14 +921,14 @@ ia64_mca_cmc_int_caller(int cpe_irq, voi
 	ia64_mca_cmc_int_handler(cpe_irq, arg, ptregs);
 
 	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
-		
+
 	if (cpuid < NR_CPUS) {
 		platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
 	} else {
-		/* If no log recored, switch out of polling mode */
+		/* If no log record, switch out of polling mode */
 		if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) {
 
-			printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__);
+			printk(KERN_WARNING "Returning to interrupt driven CMC handler\n");
 			schedule_task(&cmc_enable_tq);
 			cmc_polling_enabled = 0;
 
@@ -1227,7 +971,7 @@ ia64_mca_cmc_poll (unsigned long dummy)
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
 	static int start_count = -1;
@@ -1279,57 +1023,26 @@ ia64_mca_cpe_poll (unsigned long dummy)
 }
 
 /*
- * ia64_mca_late_init
+ * C portion of the OS INIT handler
  *
- *	Opportunity to setup things that require initialization later
- *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
- *	platform doesn't support an interrupt driven mechanism.
+ * Called from ia64_monarch_init_handler
+ *
+ * Inputs: pointer to pt_regs where processor info was saved.
+ *
+ * Returns:
+ *   0 if SAL must warm boot the System
+ *   1 if SAL must return to interrupted context using PAL_MC_RESUME
  *
- *  Inputs  :   None
- *  Outputs :   Status
  */
-static int __init
-ia64_mca_late_init(void)
+void
+ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
 {
-	init_timer(&cmc_poll_timer);
-	cmc_poll_timer.function = ia64_mca_cmc_poll;
+	pal_min_state_area_t *ms;
 
-	/* Reset to the correct state */
-	cmc_polling_enabled = 0;
+	oops_in_progress = 1;	/* avoid deadlock in printk, but it makes recovery dodgy */
 
-	init_timer(&cpe_poll_timer);
-	cpe_poll_timer.function = ia64_mca_cpe_poll;
-
-	/* If platform doesn't support CPEI, get the timer going. */
-	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
-		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
-		ia64_mca_cpe_poll(0UL);
-	}
-
-	return 0;
-}
-
-module_init(ia64_mca_late_init);
-
-/*
- * C portion of the OS INIT handler
- *
- * Called from ia64_monarch_init_handler
- *
- * Inputs: pointer to pt_regs where processor info was saved.
- *
- * Returns:
- *   0 if SAL must warm boot the System
- *   1 if SAL must return to interrupted context using PAL_MC_RESUME
- *
- */
-void
-ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
-{
-	pal_min_state_area_t *ms;
-
-	printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
-		ia64_sal_to_os_handoff_state.proc_state_param);
+	printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
+		ia64_sal_to_os_handoff_state.proc_state_param);
 
 	/*
 	 * Address of minstate area provided by PAL is physical,
@@ -1341,1080 +1054,259 @@ ia64_init_handler (struct pt_regs *pt, s
 	init_handler_platform(ms, pt, sw);	/* call platform specific routines */
 }
 
-/*
- *  ia64_log_prt_guid
- *
- *  Print a formatted GUID.
- *
- * Inputs   :   p_guid      (ptr to the GUID)
- *              prfunc      (print function)
- * Outputs  :   None
- *
- */
-void
-ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc)
-{
-	char out[40];
-	printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out));
-}
-
-static void
-ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc)
+static int __init
+ia64_mca_disable_cpe_polling(char *str)
 {
-	unsigned long i;
-	int j;
-
-	if (!p)
-		return;
-
-	for (i = 0; i < n_ch;) {
-		prfunc("%p ", (void *)p);
-		for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) {
-			prfunc("%02x ", *p);
-		}
-		prfunc("\n");
-	}
+	cpe_poll_enabled = 0;
+	return 1;
 }
 
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
+__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
 
-static void
-ia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc)
-{
-	prfunc("SAL RECORD HEADER:  Record buffer = %p,  header size = %ld\n",
-	       (void *)rh, sizeof(sal_log_record_header_t));
-	ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t),
-			 (prfunc_t)prfunc);
-	prfunc("Total record length = %d\n", rh->len);
-	ia64_log_prt_guid(&rh->platform_guid, prfunc);
-	prfunc("End of SAL RECORD HEADER\n");
-}
+static struct irqaction cmci_irqaction = {
+	.handler =	ia64_mca_cmc_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"cmc_hndlr"
+};
 
-static void
-ia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc)
-{
-	prfunc("SAL SECTION HEADER:  Record buffer = %p,  header size = %ld\n",
-	       (void *)sh, sizeof(sal_log_section_hdr_t));
-	ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t),
-			 (prfunc_t)prfunc);
-	prfunc("Length of section & header = %d\n", sh->len);
-	ia64_log_prt_guid(&sh->guid, prfunc);
-	prfunc("End of SAL SECTION HEADER\n");
-}
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
+static struct irqaction cmcp_irqaction = {
+	.handler =	ia64_mca_cmc_int_caller,
+	.flags =	SA_INTERRUPT,
+	.name =		"cmc_poll"
+};
 
-/*
- * ia64_log_init
- *	Reset the OS ia64 log buffer
- * Inputs   :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- * Outputs	:	None
- */
-void
-ia64_log_init(int sal_info_type)
-{
-	u64	max_size = 0;
+static struct irqaction mca_rdzv_irqaction = {
+	.handler =	ia64_mca_rendez_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"mca_rdzv"
+};
 
-	IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
-	IA64_LOG_LOCK_INIT(sal_info_type);
+static struct irqaction mca_wkup_irqaction = {
+	.handler =	ia64_mca_wakeup_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"mca_wkup"
+};
 
-	// SAL will tell us the maximum size of any error record of this type
-	max_size = ia64_sal_get_state_info_size(sal_info_type);
+#ifdef CONFIG_ACPI
+static struct irqaction mca_cpe_irqaction = {
+	.handler =	ia64_mca_cpe_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"cpe_hndlr"
+};
 
-	// set up OS data structures to hold error info
-	IA64_LOG_ALLOCATE(sal_info_type, max_size);
-	memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size);
-	memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size);
-}
+static struct irqaction mca_cpep_irqaction = {
+	.handler =	ia64_mca_cpe_int_caller,
+	.flags =	SA_INTERRUPT,
+	.name =		"cpe_poll"
+};
+#endif /* CONFIG_ACPI */
 
 /*
- * ia64_log_get
+ * ia64_mca_init
  *
- *	Get the current MCA log from SAL and copy it into the OS log buffer.
+ *  Do all the system level mca specific initialization.
  *
- *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *  Outputs :   size        (total record length)
- *              *buffer     (ptr to error record)
+ *	1. Register spinloop and wakeup request interrupt vectors
  *
- */
-u64
-ia64_log_get(int sal_info_type, u8 **buffer)
-{
-	sal_log_record_header_t     *log_buffer;
-	u64                         total_len = 0;
-	int                         s;
-
-	IA64_LOG_LOCK(sal_info_type);
-
-	/* Get the process state information */
-	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
-
-	total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
-
-	if (total_len) {
-		IA64_LOG_INDEX_INC(sal_info_type);
-		IA64_LOG_UNLOCK(sal_info_type);
-		IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
-			       "Record length = %ld\n", sal_info_type, total_len);
-		*buffer = (u8 *) log_buffer;
-		return total_len;
-	} else {
-		IA64_LOG_UNLOCK(sal_info_type);
-		return 0;
-	}
-}
-
-/*
- *  ia64_log_prt_oem_data
+ *	2. Register OS_MCA handler entry point
  *
- *  Print OEM specific data if included.
+ *	3. Register OS_INIT handler entry point
  *
- * Inputs   :   header_len  (length passed in section header)
- *              sect_len    (default length of section type)
- *              p_data      (ptr to data)
- *			prfunc		(print function)
- * Outputs	:	None
+ *  4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
  *
- */
-void
-ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
-{
-	int oem_data_len, i;
-
-	if ((oem_data_len = header_len - sect_len) > 0) {
-		prfunc(" OEM Specific Data:");
-		for (i = 0; i < oem_data_len; i++, p_data++)
-			prfunc(" %02x", *p_data);
-	}
-	prfunc("\n");
-}
-
-/*
- *  ia64_log_rec_header_print
+ *  Note that this initialization is done very early before some kernel
+ *  services are available.
  *
- *  Log info from the SAL error record header.
+ *  Inputs  :   None
  *
- *  Inputs  :   lh *    (ptr to SAL log error record header)
- *              prfunc  (fn ptr of log output function to use)
  *  Outputs :   None
  */
-void
-ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
-{
-	prfunc("+Err Record ID: %ld    SAL Rev: %2x.%02x\n", lh->id,
-			lh->revision.major, lh->revision.minor);
-	prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x    Severity %d\n",
-			lh->timestamp.slh_month, lh->timestamp.slh_day,
-			lh->timestamp.slh_century, lh->timestamp.slh_year,
-			lh->timestamp.slh_hour, lh->timestamp.slh_minute,
-			lh->timestamp.slh_second, lh->severity);
-}
-
-/*
- * ia64_log_processor_regs_print
- *	Print the contents of the saved processor register(s) in the format
- *		<reg_prefix>[<index>] <value>
- *
- * Inputs	:	regs		(Register save buffer)
- *			reg_num	(# of registers)
- *			reg_class	(application/banked/control/bank1_general)
- *			reg_prefix	(ar/br/cr/b1_gr)
- * Outputs	:	None
- *
- */
-void
-ia64_log_processor_regs_print(u64	*regs,
-			      int	reg_num,
-			      char	*reg_class,
-			      char	*reg_prefix,
-			      prfunc_t	prfunc)
-{
-	int i;
-
-	prfunc("+%s Registers\n", reg_class);
-	for (i = 0; i < reg_num; i++)
-		prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]);
-}
-
-/*
- * ia64_log_processor_fp_regs_print
- *  Print the contents of the saved floating page register(s) in the format
- *      <reg_prefix>[<index>] <value>
- *
- * Inputs:  ia64_fpreg  (Register save buffer)
- *          reg_num     (# of registers)
- *          reg_class   (application/banked/control/bank1_general)
- *          reg_prefix  (ar/br/cr/b1_gr)
- * Outputs: None
- *
- */
-void
-ia64_log_processor_fp_regs_print (struct ia64_fpreg *regs,
-                                  int               reg_num,
-                                  char              *reg_class,
-                                  char              *reg_prefix,
-                                  prfunc_t          prfunc)
+void __init
+ia64_mca_init(void)
 {
+	ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
+	ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
+	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
 	int i;
+	s64 rc;
+	struct ia64_sal_retval isrv;
+	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
 
-	prfunc("+%s Registers\n", reg_class);
-	for (i = 0; i < reg_num; i++)
-		prfunc("+ %s[%d] 0x%lx%016lx\n", reg_prefix, i, regs[i].u.bits[1],
-		       regs[i].u.bits[0]);
-}
-
-static char *pal_mesi_state[] = {
-	"Invalid",
-	"Shared",
-	"Exclusive",
-	"Modified",
-	"Reserved1",
-	"Reserved2",
-	"Reserved3",
-	"Reserved4"
-};
-
-static char *pal_cache_op[] = {
-	"Unknown",
-	"Move in",
-	"Cast out",
-	"Coherency check",
-	"Internal",
-	"Instruction fetch",
-	"Implicit Writeback",
-	"Reserved"
-};
-
-/*
- * ia64_log_cache_check_info_print
- *	Display the machine check information related to cache error(s).
- * Inputs:  i           (Multiple errors are logged, i - index of logged error)
- *          cc_info *   (Ptr to cache check info logged by the PAL and later
- *					 captured by the SAL)
- *          prfunc      (fn ptr of print function to be used for output)
- * Outputs: None
- */
-void
-ia64_log_cache_check_info_print (int                      i,
-                                 sal_log_mod_error_info_t *cache_check_info,
-				 prfunc_t		prfunc)
-{
-	pal_cache_check_info_t  *info;
-	u64                     target_addr;
-
-	if (!cache_check_info->valid.check_info) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]\n",i);
-		return;                 /* If check info data not valid, skip it */
-	}
-
-	info        = (pal_cache_check_info_t *)&cache_check_info->check_info;
-	target_addr = cache_check_info->target_identifier;
-
-	prfunc("+ Cache check info[%d]\n+", i);
-	prfunc("  Level: L%d,",info->level);
-	if (info->mv)
-		prfunc(" Mesi: %s,",pal_mesi_state[info->mesi]);
-	prfunc(" Index: %d,", info->index);
-	if (info->ic)
-		prfunc(" Cache: Instruction,");
-	if (info->dc)
-		prfunc(" Cache: Data,");
-	if (info->tl)
-		prfunc(" Line: Tag,");
-	if (info->dl)
-		prfunc(" Line: Data,");
-	prfunc(" Operation: %s,", pal_cache_op[info->op]);
-	if (info->wiv)
-		prfunc(" Way: %d,", info->way);
-	if (cache_check_info->valid.target_identifier)
-		/* Hope target address is saved in target_identifier */
-		if (info->tv)
-			prfunc(" Target Addr: 0x%lx,", target_addr);
-	if (info->mcc)
-		prfunc(" MC: Corrected");
-	prfunc("\n");
-}
-
-/*
- * ia64_log_tlb_check_info_print
- *	Display the machine check information related to tlb error(s).
- * Inputs:  i           (Multiple errors are logged, i - index of logged error)
- *          tlb_info *  (Ptr to machine check info logged by the PAL and later
- *					 captured by the SAL)
- *          prfunc      (fn ptr of print function to be used for output)
- * Outputs: None
- */
-void
-ia64_log_tlb_check_info_print (int                      i,
-                               sal_log_mod_error_info_t *tlb_check_info,
-                               prfunc_t                 prfunc)
-
-{
-	pal_tlb_check_info_t    *info;
-
-	if (!tlb_check_info->valid.check_info) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]\n", i);
-		return;                 /* If check info data not valid, skip it */
-	}
-
-	info = (pal_tlb_check_info_t *)&tlb_check_info->check_info;
-
-	prfunc("+ TLB Check Info [%d]\n+", i);
-	if (info->itc)
-		prfunc("  Failure: Instruction Translation Cache");
-	if (info->dtc)
-		prfunc("  Failure: Data Translation Cache");
-	if (info->itr) {
-		prfunc("  Failure: Instruction Translation Register");
-		prfunc(" ,Slot: %ld", info->tr_slot);
-	}
-	if (info->dtr) {
-		prfunc("  Failure: Data Translation Register");
-		prfunc(" ,Slot: %ld", info->tr_slot);
-	}
-	if (info->mcc)
-		prfunc(" ,MC: Corrected");
-	prfunc("\n");
-}
-
-/*
- * ia64_log_bus_check_info_print
- *	Display the machine check information related to bus error(s).
- * Inputs:  i           (Multiple errors are logged, i - index of logged error)
- *          bus_info *  (Ptr to machine check info logged by the PAL and later
- *					 captured by the SAL)
- *          prfunc      (fn ptr of print function to be used for output)
- * Outputs: None
- */
-void
-ia64_log_bus_check_info_print (int                      i,
-                               sal_log_mod_error_info_t *bus_check_info,
-                               prfunc_t                 prfunc)
-{
-	pal_bus_check_info_t *info;
-	u64         req_addr;   /* Address of the requestor of the transaction */
-	u64         resp_addr;  /* Address of the responder of the transaction */
-	u64         targ_addr;  /* Address where the data was to be delivered to */
-	/* or obtained from */
-
-	if (!bus_check_info->valid.check_info) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]\n", i);
-		return;                 /* If check info data not valid, skip it */
-	}
+	IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__);
 
-	info      = (pal_bus_check_info_t *)&bus_check_info->check_info;
-	req_addr  = bus_check_info->requestor_identifier;
-	resp_addr = bus_check_info->responder_identifier;
-	targ_addr = bus_check_info->target_identifier;
-
-	prfunc("+ BUS Check Info [%d]\n+", i);
-	prfunc(" Status Info: %d", info->bsi);
-	prfunc(" ,Severity: %d", info->sev);
-	prfunc(" ,Transaction Type: %d", info->type);
-	prfunc(" ,Transaction Size: %d", info->size);
-	if (info->cc)
-		prfunc(" ,Cache-cache-transfer");
-	if (info->ib)
-		prfunc(" ,Error: Internal");
-	if (info->eb)
-		prfunc(" ,Error: External");
-	if (info->mcc)
-		prfunc(" ,MC: Corrected");
-	if (info->tv)
-		prfunc(" ,Target Address: 0x%lx", targ_addr);
-	if (info->rq)
-		prfunc(" ,Requestor Address: 0x%lx", req_addr);
-	if (info->tv)
-		prfunc(" ,Responder Address: 0x%lx", resp_addr);
-	prfunc("\n");
-}
+	INIT_TQUEUE(&cmc_disable_tq, ia64_mca_cmc_vector_disable_keventd, NULL);
+	INIT_TQUEUE(&cmc_enable_tq, ia64_mca_cmc_vector_enable_keventd, NULL);
 
-/*
- *  ia64_log_mem_dev_err_info_print
- *
- *  Format and log the platform memory device error record section data.
- *
- *  Inputs:  mem_dev_err_info * (Ptr to memory device error record section
- *                               returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_mem_dev_err_info_print (sal_log_mem_dev_err_info_t *mdei,
-                                 prfunc_t                   prfunc)
-{
-	prfunc("+ Mem Error Detail: ");
+	/* Clear the Rendez checkin flag for all cpus */
+	for(i = 0 ; i < NR_CPUS; i++)
+		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
 
-	if (mdei->valid.error_status)
-		prfunc(" Error Status: %#lx,", mdei->error_status);
-	if (mdei->valid.physical_addr)
-		prfunc(" Physical Address: %#lx,", mdei->physical_addr);
-	if (mdei->valid.addr_mask)
-		prfunc(" Address Mask: %#lx,", mdei->addr_mask);
-	if (mdei->valid.node)
-		prfunc(" Node: %d,", mdei->node);
-	if (mdei->valid.card)
-		prfunc(" Card: %d,", mdei->card);
-	if (mdei->valid.module)
-		prfunc(" Module: %d,", mdei->module);
-	if (mdei->valid.bank)
-		prfunc(" Bank: %d,", mdei->bank);
-	if (mdei->valid.device)
-		prfunc(" Device: %d,", mdei->device);
-	if (mdei->valid.row)
-		prfunc(" Row: %d,", mdei->row);
-	if (mdei->valid.column)
-		prfunc(" Column: %d,", mdei->column);
-	if (mdei->valid.bit_position)
-		prfunc(" Bit Position: %d,", mdei->bit_position);
-	if (mdei->valid.target_id)
-		prfunc(" ,Target Address: %#lx,", mdei->target_id);
-	if (mdei->valid.requestor_id)
-		prfunc(" ,Requestor Address: %#lx,", mdei->requestor_id);
-	if (mdei->valid.responder_id)
-		prfunc(" ,Responder Address: %#lx,", mdei->responder_id);
-	if (mdei->valid.bus_spec_data)
-		prfunc(" Bus Specific Data: %#lx,", mdei->bus_spec_data);
-	prfunc("\n");
-
-	if (mdei->valid.oem_id) {
-		u8  *p_data = &(mdei->oem_id[0]);
-		int i;
-
-		prfunc(" OEM Memory Controller ID:");
-		for (i = 0; i < 16; i++, p_data++)
-			prfunc(" %02x", *p_data);
-		prfunc("\n");
-	}
+	/*
+	 * Register the rendezvous spinloop and wakeup mechanism with SAL
+	 */
 
-	if (mdei->valid.oem_data) {
-		platform_mem_dev_err_print((int)mdei->header.len,
-				      (int)sizeof(sal_log_mem_dev_err_info_t) - 1,
-				      &(mdei->oem_data[0]), prfunc);
+	/* Register the rendezvous interrupt vector with SAL */
+	while (1) {
+		isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
+					      SAL_MC_PARAM_MECHANISM_INT,
+					      IA64_MCA_RENDEZ_VECTOR,
+					      timeout,
+					      SAL_MC_PARAM_RZ_ALWAYS);
+		rc = isrv.status;
+		if (rc == 0)
+			break;
+		if (rc == -2) {
+			printk(KERN_INFO "Increasing MCA rendezvous timeout from "
+				"%ld to %ld milliseconds\n", timeout, isrv.v0);
+			timeout = isrv.v0;
+			continue;
+		}
+		printk(KERN_ERR "Failed to register rendezvous interrupt "
+		       "with SAL (status %ld)\n", rc);
+		return;
 	}
-}
 
-/*
- *  ia64_log_sel_dev_err_info_print
- *
- *  Format and log the platform SEL device error record section data.
- *
- *  Inputs:  sel_dev_err_info * (Ptr to the SEL device error record section
- *                               returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_sel_dev_err_info_print (sal_log_sel_dev_err_info_t *sdei,
-                                 prfunc_t                   prfunc)
-{
-	int     i;
-
-	prfunc("+ SEL Device Error Detail: ");
-
-	if (sdei->valid.record_id)
-		prfunc(" Record ID: %#x", sdei->record_id);
-	if (sdei->valid.record_type)
-		prfunc(" Record Type: %#x", sdei->record_type);
-	prfunc(" Time Stamp: ");
-	for (i = 0; i < 4; i++)
-		prfunc("%1d", sdei->timestamp[i]);
-	if (sdei->valid.generator_id)
-		prfunc(" Generator ID: %#x", sdei->generator_id);
-	if (sdei->valid.evm_rev)
-		prfunc(" Message Format Version: %#x", sdei->evm_rev);
-	if (sdei->valid.sensor_type)
-		prfunc(" Sensor Type: %#x", sdei->sensor_type);
-	if (sdei->valid.sensor_num)
-		prfunc(" Sensor Number: %#x", sdei->sensor_num);
-	if (sdei->valid.event_dir)
-		prfunc(" Event Direction Type: %#x", sdei->event_dir);
-	if (sdei->valid.event_data1)
-		prfunc(" Data1: %#x", sdei->event_data1);
-	if (sdei->valid.event_data2)
-		prfunc(" Data2: %#x", sdei->event_data2);
-	if (sdei->valid.event_data3)
-		prfunc(" Data3: %#x", sdei->event_data3);
-	prfunc("\n");
-
-}
-
-/*
- *  ia64_log_pci_bus_err_info_print
- *
- *  Format and log the platform PCI bus error record section data.
- *
- *  Inputs:  pci_bus_err_info * (Ptr to the PCI bus error record section
- *                               returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_pci_bus_err_info_print (sal_log_pci_bus_err_info_t *pbei,
-                                 prfunc_t                   prfunc)
-{
-	prfunc("+ PCI Bus Error Detail: ");
-
-	if (pbei->valid.err_status)
-		prfunc(" Error Status: %#lx", pbei->err_status);
-	if (pbei->valid.err_type)
-		prfunc(" Error Type: %#x", pbei->err_type);
-	if (pbei->valid.bus_id)
-		prfunc(" Bus ID: %#x", pbei->bus_id);
-	if (pbei->valid.bus_address)
-		prfunc(" Bus Address: %#lx", pbei->bus_address);
-	if (pbei->valid.bus_data)
-		prfunc(" Bus Data: %#lx", pbei->bus_data);
-	if (pbei->valid.bus_cmd)
-		prfunc(" Bus Command: %#lx", pbei->bus_cmd);
-	if (pbei->valid.requestor_id)
-		prfunc(" Requestor ID: %#lx", pbei->requestor_id);
-	if (pbei->valid.responder_id)
-		prfunc(" Responder ID: %#lx", pbei->responder_id);
-	if (pbei->valid.target_id)
-		prfunc(" Target ID: %#lx", pbei->target_id);
-	if (pbei->valid.oem_data)
-		prfunc("\n");
-
-	if (pbei->valid.oem_data) {
-		platform_pci_bus_err_print((int)pbei->header.len,
-				      (int)sizeof(sal_log_pci_bus_err_info_t) - 1,
-				      &(pbei->oem_data[0]), prfunc);
+	/* Register the wakeup interrupt vector with SAL */
+	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
+				      SAL_MC_PARAM_MECHANISM_INT,
+				      IA64_MCA_WAKEUP_VECTOR,
+				      0, 0);
+	rc = isrv.status;
+	if (rc) {
+		printk(KERN_ERR "Failed to register wakeup interrupt with SAL "
+		       "(status %ld)\n", rc);
+		return;
 	}
-}
 
-/*
- *  ia64_log_smbios_dev_err_info_print
- *
- *  Format and log the platform SMBIOS device error record section data.
- *
- *  Inputs:  smbios_dev_err_info * (Ptr to the SMBIOS device error record
- *                                  section returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_smbios_dev_err_info_print (sal_log_smbios_dev_err_info_t *sdei,
-                                    prfunc_t                      prfunc)
-{
-	u8      i;
+	IA64_MCA_DEBUG("%s: registered MCA rendezvous spinloop and wakeup mech.\n", __FUNCTION__);
 
-	prfunc("+ SMBIOS Device Error Detail: ");
-
-	if (sdei->valid.event_type)
-		prfunc(" Event Type: %#x", sdei->event_type);
-	if (sdei->valid.time_stamp) {
-		prfunc(" Time Stamp: ");
-		for (i = 0; i < 6; i++)
-			prfunc("%d", sdei->time_stamp[i]);
-	}
-	if ((sdei->valid.data) && (sdei->valid.length)) {
-		prfunc(" Data: ");
-		for (i = 0; i < sdei->length; i++)
-			prfunc(" %02x", sdei->data[i]);
-	}
-	prfunc("\n");
-}
+	ia64_mc_info.imi_mca_handler        = ia64_tpa(mca_hldlr_ptr->fp);
+	/*
+	 * XXX - disable SAL checksum by setting size to 0; should be
+	 *	ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch);
+	 */
+	ia64_mc_info.imi_mca_handler_size	= 0;
 
-/*
- *  ia64_log_pci_comp_err_info_print
- *
- *  Format and log the platform PCI component error record section data.
- *
- *  Inputs:  pci_comp_err_info * (Ptr to the PCI component error record section
- *                                returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_pci_comp_err_info_print(sal_log_pci_comp_err_info_t *pcei,
-				 prfunc_t                     prfunc)
-{
-	u32     n_mem_regs, n_io_regs;
-	u64     i, n_pci_data;
-	u64     *p_reg_data;
-	u8      *p_oem_data;
-
-	prfunc("+ PCI Component Error Detail: ");
-
-	if (pcei->valid.err_status)
-		prfunc(" Error Status: %#lx\n", pcei->err_status);
-	if (pcei->valid.comp_info)
-		prfunc(" Component Info: Vendor Id = %#x, Device Id = %#x,"
-		       " Class Code = %#x, Seg/Bus/Dev/Func = %d/%d/%d/%d\n",
-		       pcei->comp_info.vendor_id, pcei->comp_info.device_id,
-		       pcei->comp_info.class_code, pcei->comp_info.seg_num,
-		       pcei->comp_info.bus_num, pcei->comp_info.dev_num,
-		       pcei->comp_info.func_num);
-
-	n_mem_regs = (pcei->valid.num_mem_regs) ? pcei->num_mem_regs : 0;
-	n_io_regs =  (pcei->valid.num_io_regs)  ? pcei->num_io_regs  : 0;
-	p_reg_data = &(pcei->reg_data_pairs[0]);
-	p_oem_data = (u8 *)p_reg_data +
-		(n_mem_regs + n_io_regs) * 2 * sizeof(u64);
-	n_pci_data = p_oem_data - (u8 *)pcei;
-
-	if (n_pci_data > pcei->header.len) {
-		prfunc(" Invalid PCI Component Error Record format: length = %ld, "
-		       " Size PCI Data = %d, Num Mem-Map/IO-Map Regs = %ld/%ld\n",
-		       pcei->header.len, n_pci_data, n_mem_regs, n_io_regs);
+	/* Register the os mca handler with SAL */
+	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
+				       ia64_mc_info.imi_mca_handler,
+				       ia64_tpa(mca_hldlr_ptr->gp),
+				       ia64_mc_info.imi_mca_handler_size,
+				       0, 0, 0)))
+	{
+		printk(KERN_ERR "Failed to register OS MCA handler with SAL "
+		       "(status %ld)\n", rc);
 		return;
 	}
 
-	if (n_mem_regs) {
-		prfunc(" Memory Mapped Registers\n Address \tValue\n");
-		for (i = 0; i < pcei->num_mem_regs; i++) {
-			prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]);
-			p_reg_data += 2;
-		}
-	}
-	if (n_io_regs) {
-		prfunc(" I/O Mapped Registers\n Address \tValue\n");
-		for (i = 0; i < pcei->num_io_regs; i++) {
-			prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]);
-			p_reg_data += 2;
-		}
-	}
-	if (pcei->valid.oem_data) {
-		platform_pci_comp_err_print((int)pcei->header.len, n_pci_data,
-				      p_oem_data, prfunc);
-		prfunc("\n");
-	}
-}
-
-/*
- *  ia64_log_plat_specific_err_info_print
- *
- *  Format and log the platform specifie error record section data.
- *
- *  Inputs:  sel_dev_err_info * (Ptr to the platform specific error record
- *                               section returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_plat_specific_err_info_print (sal_log_plat_specific_err_info_t *psei,
-                                       prfunc_t                         prfunc)
-{
-	prfunc("+ Platform Specific Error Detail: ");
+	IA64_MCA_DEBUG("%s: registered OS MCA handler with SAL at 0x%lx, gp = 0x%lx\n", __FUNCTION__,
+		       ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp));
 
-	if (psei->valid.err_status)
-		prfunc(" Error Status: %#lx", psei->err_status);
-	if (psei->valid.guid) {
-		prfunc(" GUID: ");
-		ia64_log_prt_guid(&psei->guid, prfunc);
-	}
-	if (psei->valid.oem_data) {
-		platform_plat_specific_err_print((int) psei->header.len,
-				      (char *) psei->oem_data - (char *) psei,
-				      &psei->oem_data[0], prfunc);
-	}
-	prfunc("\n");
-}
+	/*
+	 * XXX - disable SAL checksum by setting size to 0, should be
+	 * size of the actual init handler in mca_asm.S.
+	 */
+	ia64_mc_info.imi_monarch_init_handler		= ia64_tpa(mon_init_ptr->fp);
+	ia64_mc_info.imi_monarch_init_handler_size	= 0;
+	ia64_mc_info.imi_slave_init_handler		= ia64_tpa(slave_init_ptr->fp);
+	ia64_mc_info.imi_slave_init_handler_size	= 0;
 
-/*
- *  ia64_log_host_ctlr_err_info_print
- *
- *  Format and log the platform host controller error record section data.
- *
- *  Inputs:  host_ctlr_err_info * (Ptr to the host controller error record
- *                                 section returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_host_ctlr_err_info_print (sal_log_host_ctlr_err_info_t *hcei,
-                                   prfunc_t                     prfunc)
-{
-	prfunc("+ Host Controller Error Detail: ");
+	IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__,
+		       ia64_mc_info.imi_monarch_init_handler);
 
-	if (hcei->valid.err_status)
-		prfunc(" Error Status: %#lx", hcei->err_status);
-	if (hcei->valid.requestor_id)
-		prfunc(" Requestor ID: %#lx", hcei->requestor_id);
-	if (hcei->valid.responder_id)
-		prfunc(" Responder ID: %#lx", hcei->responder_id);
-	if (hcei->valid.target_id)
-		prfunc(" Target ID: %#lx", hcei->target_id);
-	if (hcei->valid.bus_spec_data)
-		prfunc(" Bus Specific Data: %#lx", hcei->bus_spec_data);
-	if (hcei->valid.oem_data) {
-		platform_host_ctlr_err_print((int)hcei->header.len,
-				      (int)sizeof(sal_log_host_ctlr_err_info_t) - 1,
-				      &(hcei->oem_data[0]), prfunc);
+	/* Register the os init handler with SAL */
+	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
+				       ia64_mc_info.imi_monarch_init_handler,
+				       ia64_tpa(ia64_get_gp()),
+				       ia64_mc_info.imi_monarch_init_handler_size,
+				       ia64_mc_info.imi_slave_init_handler,
+				       ia64_tpa(ia64_get_gp()),
+				       ia64_mc_info.imi_slave_init_handler_size)))
+	{
+		printk(KERN_ERR "Failed to register m/s INIT handlers with SAL "
+		       "(status %ld)\n", rc);
+		return;
 	}
-	prfunc("\n");
-}
 
-/*
- *  ia64_log_plat_bus_err_info_print
- *
- *  Format and log the platform bus error record section data.
- *
- *  Inputs:  plat_bus_err_info * (Ptr to the platform bus error record section
- *                                returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_plat_bus_err_info_print (sal_log_plat_bus_err_info_t *pbei,
-                                  prfunc_t                    prfunc)
-{
-	prfunc("+ Platform Bus Error Detail: ");
+	IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__);
 
-	if (pbei->valid.err_status)
-		prfunc(" Error Status: %#lx", pbei->err_status);
-	if (pbei->valid.requestor_id)
-		prfunc(" Requestor ID: %#lx", pbei->requestor_id);
-	if (pbei->valid.responder_id)
-		prfunc(" Responder ID: %#lx", pbei->responder_id);
-	if (pbei->valid.target_id)
-		prfunc(" Target ID: %#lx", pbei->target_id);
-	if (pbei->valid.bus_spec_data)
-		prfunc(" Bus Specific Data: %#lx", pbei->bus_spec_data);
-	if (pbei->valid.oem_data) {
-		platform_plat_bus_err_print((int)pbei->header.len,
-				      (int)sizeof(sal_log_plat_bus_err_info_t) - 1,
-				      &(pbei->oem_data[0]), prfunc);
-	}
-	prfunc("\n");
-}
+	/*
+	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
+	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
+	 */
+	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
+	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */
 
-/*
- *  ia64_log_proc_dev_err_info_print
- *
- *  Display the processor device error record.
- *
- *  Inputs:  sal_log_processor_info_t * (Ptr to processor device error record
- *                                       section body).
- *           prfunc                     (fn ptr of print function to be used
- *                                       for output).
- *  Outputs: None
- */
-void
-ia64_log_proc_dev_err_info_print (sal_log_processor_info_t  *slpi,
-                                  prfunc_t                  prfunc)
-{
-#ifdef MCA_PRT_XTRA_DATA
-	size_t  d_len = slpi->header.len - sizeof(sal_log_section_hdr_t);
-#endif
-	sal_processor_static_info_t *spsi;
-	int                         i;
-	sal_log_mod_error_info_t    *p_data;
+	/* Setup the MCA rendezvous interrupt vector */
+	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
 
-	prfunc("+Processor Device Error Info Section\n");
+	/* Setup the MCA wakeup interrupt vector */
+	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
 
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
+#ifdef CONFIG_ACPI
+	/* Setup the CPE interrupt vector */
 	{
-		char    *p_data = (char *)&slpi->valid;
+		irq_desc_t *desc;
+		unsigned int irq;
+		int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
 
-		prfunc("SAL_PROC_DEV_ERR SECTION DATA:  Data buffer = %p, "
-		       "Data size = %ld\n", (void *)p_data, d_len);
-		ia64_log_hexdump(p_data, d_len, prfunc);
-		prfunc("End of SAL_PROC_DEV_ERR SECTION DATA\n");
+		if (cpev >= 0) {
+			for (irq = 0; irq < NR_IRQS; ++irq)
+				if (irq_to_vector(irq) == cpev) {
+					desc = irq_desc(irq);
+					desc->status |= IRQ_PER_CPU;
+					desc->handler = &irq_type_iosapic_level;
+					setup_irq(irq, &mca_cpe_irqaction);
+				}
+			ia64_mca_register_cpev(cpev);
+		}
 	}
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-	if (slpi->valid.proc_error_map)
-		prfunc(" Processor Error Map: %#lx\n", slpi->proc_error_map);
-
-	if (slpi->valid.proc_state_param)
-		prfunc(" Processor State Param: %#lx\n", slpi->proc_state_parameter);
-
-	if (slpi->valid.proc_cr_lid)
-		prfunc(" Processor LID: %#lx\n", slpi->proc_cr_lid);
+#endif
 
-	/*
-	 *  Note: March 2001 SAL spec states that if the number of elements in any
-	 *  of  the MOD_ERROR_INFO_STRUCT arrays is zero, the entire array is
-	 *  absent. Also, current implementations only allocate space for number of
-	 *  elements used.  So we walk the data pointer from here on.
+	/* Initialize the areas set aside by the OS to buffer the
+	 * platform/processor error states for MCA/INIT/CMC
+	 * handling.
 	 */
-	p_data = &slpi->info[0];
-
-	/* Print the cache check information if any*/
-	for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
-		ia64_log_cache_check_info_print(i, p_data, prfunc);
-
-	/* Print the tlb check information if any*/
-	for (i = 0 ; i < slpi->valid.num_tlb_check; i++, p_data++)
-		ia64_log_tlb_check_info_print(i, p_data, prfunc);
-
-	/* Print the bus check information if any*/
-	for (i = 0 ; i < slpi->valid.num_bus_check; i++, p_data++)
-		ia64_log_bus_check_info_print(i, p_data, prfunc);
-
-	/* Print the reg file check information if any*/
-	for (i = 0 ; i < slpi->valid.num_reg_file_check; i++, p_data++)
-		ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
-				 prfunc);    /* Just hex dump for now */
-
-	/* Print the ms check information if any*/
-	for (i = 0 ; i < slpi->valid.num_ms_check; i++, p_data++)
-		ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
-				 prfunc);    /* Just hex dump for now */
-
-	/* Print CPUID registers if any*/
-	if (slpi->valid.cpuid_info) {
-		u64     *p = (u64 *)p_data;
-
-		prfunc(" CPUID Regs: %#lx %#lx %#lx %#lx\n", p[0], p[1], p[2], p[3]);
-		p_data++;
-	}
+	ia64_log_init(SAL_INFO_TYPE_MCA);
+	ia64_log_init(SAL_INFO_TYPE_INIT);
+	ia64_log_init(SAL_INFO_TYPE_CMC);
+	ia64_log_init(SAL_INFO_TYPE_CPE);
 
-	/* Print processor static info if any */
-	if (slpi->valid.psi_static_struct) {
-		spsi = (sal_processor_static_info_t *)p_data;
-
-		/* Print branch register contents if valid */
-		if (spsi->valid.br)
-			ia64_log_processor_regs_print(spsi->br, 8, "Branch", "br",
-						      prfunc);
-
-		/* Print control register contents if valid */
-		if (spsi->valid.cr)
-			ia64_log_processor_regs_print(spsi->cr, 128, "Control", "cr",
-						      prfunc);
-
-		/* Print application register contents if valid */
-		if (spsi->valid.ar)
-			ia64_log_processor_regs_print(spsi->ar, 128, "Application",
-						      "ar", prfunc);
-
-		/* Print region register contents if valid */
-		if (spsi->valid.rr)
-			ia64_log_processor_regs_print(spsi->rr, 8, "Region", "rr",
-						      prfunc);
-
-		/* Print floating-point register contents if valid */
-		if (spsi->valid.fr)
-			ia64_log_processor_fp_regs_print(spsi->fr, 128, "Floating-point", "fr",
-							 prfunc);
-	}
+	printk(KERN_INFO "MCA related initialization done\n");
 }
 
 /*
- * ia64_log_processor_info_print
+ * ia64_mca_late_init
  *
- *	Display the processor-specific information logged by PAL as a part
- *	of MCA or INIT or CMC.
+ *	Opportunity to setup things that require initialization later
+ *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
+ *	platform doesn't support an interrupt driven mechanism.
  *
- *  Inputs   :  lh      (Pointer of the sal log header which specifies the
- *                       format of SAL state info as specified by the SAL spec).
- *              prfunc  (fn ptr of print function to be used for output).
- * Outputs	:	None
+ *  Inputs  :   None
+ *  Outputs :   Status
  */
-void
-ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc)
+static int __init
+ia64_mca_late_init(void)
 {
-	sal_log_section_hdr_t       *slsh;
-	int                         n_sects;
-	u32                         ercd_pos;
-
-	if (!lh)
-		return;
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-	ia64_log_prt_record_header(lh, prfunc);
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-	if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: "
-			       "truncated SAL CMC error record. len = %d\n",
-			       lh->len);
-		return;
-	}
-
-	/* Print record header info */
-	ia64_log_rec_header_print(lh, prfunc);
-
-	for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
-		/* point to next section header */
-		slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-		ia64_log_prt_section_header(slsh, prfunc);
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-		if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) {
-			IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
-			continue;
-		}
-
-		/*
-		 *  Now process processor device error record section
-		 */
-		ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, printk);
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_log_print: "
-		       "found %d sections in SAL CMC error record. len = %d\n",
-		       n_sects, lh->len);
-	if (!n_sects) {
-		prfunc("No Processor Device Error Info Section found\n");
-		return;
-	}
-}
-
-/*
- *  ia64_log_platform_info_print
- *
- *  Format and Log the SAL Platform Error Record.
- *
- *  Inputs  :   lh      (Pointer to the sal error record header with format
- *                       specified by the SAL spec).
- *              prfunc  (fn ptr of log output function to use)
- *  Outputs :	platform error status
- */
-int
-ia64_log_platform_info_print (sal_log_record_header_t *lh, prfunc_t prfunc)
-{
-	sal_log_section_hdr_t	*slsh;
-	int			n_sects;
-	u32			ercd_pos;
-	int			platform_err = 0;
-
-	if (!lh)
-		return platform_err;
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-	ia64_log_prt_record_header(lh, prfunc);
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-	if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: "
-			       "truncated SAL error record. len = %d\n",
-			       lh->len);
-		return platform_err;
-	}
-
-	/* Print record header info */
-	ia64_log_rec_header_print(lh, prfunc);
-
-	for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
-		/* point to next section header */
-		slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-		ia64_log_prt_section_header(slsh, prfunc);
-
-		if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) != 0) {
-			size_t  d_len = slsh->len - sizeof(sal_log_section_hdr_t);
-			char    *p_data = (char *)&((sal_log_mem_dev_err_info_t *)slsh)->valid;
-
-			prfunc("Start of Platform Err Data Section:  Data buffer = %p, "
-			       "Data size = %ld\n", (void *)p_data, d_len);
-			ia64_log_hexdump(p_data, d_len, prfunc);
-			prfunc("End of Platform Err Data Section\n");
-		}
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
+	init_timer(&cmc_poll_timer);
+	cmc_poll_timer.function = ia64_mca_cmc_poll;
 
-		/*
-		 *  Now process CPE error record section
-		 */
-		if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) == 0) {
-			ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh,
-							 prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Memory Device Error Info Section\n");
-			ia64_log_mem_dev_err_info_print((sal_log_mem_dev_err_info_t *)slsh,
-							prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform SEL Device Error Info Section\n");
-			ia64_log_sel_dev_err_info_print((sal_log_sel_dev_err_info_t *)slsh,
-							prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform PCI Bus Error Info Section\n");
-			ia64_log_pci_bus_err_info_print((sal_log_pci_bus_err_info_t *)slsh,
-							prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform SMBIOS Device Error Info Section\n");
-			ia64_log_smbios_dev_err_info_print((sal_log_smbios_dev_err_info_t *)slsh,
-							   prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform PCI Component Error Info Section\n");
-			ia64_log_pci_comp_err_info_print((sal_log_pci_comp_err_info_t *)slsh,
-							 prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Specific Error Info Section\n");
-			ia64_log_plat_specific_err_info_print((sal_log_plat_specific_err_info_t *)
-							      slsh,
-							      prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Host Controller Error Info Section\n");
-			ia64_log_host_ctlr_err_info_print((sal_log_host_ctlr_err_info_t *)slsh,
-							  prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_BUS_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Bus Error Info Section\n");
-			ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh,
-							 prfunc);
-		} else {
-			IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
-			continue;
-		}
-	}
+	/* Reset to the correct state */
+	cmc_polling_enabled = 0;
 
-	IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %d\n",
-		       n_sects, lh->len);
-	if (!n_sects) {
-		prfunc("No Platform Error Info Sections found\n");
-		return platform_err;
-	}
-	return platform_err;
-}
+	init_timer(&cpe_poll_timer);
+	cpe_poll_timer.function = ia64_mca_cpe_poll;
 
-/*
- * ia64_log_print
- *
- *  Displays the contents of the OS error log information
- *
- *  Inputs   :  info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *              prfunc      (fn ptr of log output function to use)
- * Outputs	:	platform error status
- */
-int
-ia64_log_print(int sal_info_type, prfunc_t prfunc)
-{
-	int platform_err = 0;
-
-	switch(sal_info_type) {
-	      case SAL_INFO_TYPE_MCA:
-		prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id());
-		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		break;
-	      case SAL_INFO_TYPE_INIT:
-		prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id());
-		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		break;
-	      case SAL_INFO_TYPE_CMC:
-		prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n");
-		ia64_log_processor_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		prfunc("+END HARDWARE ERROR STATE AT CMC\n");
-		break;
-	      case SAL_INFO_TYPE_CPE:
-		prfunc("+BEGIN HARDWARE ERROR STATE AT CPE\n");
-		ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		prfunc("+END HARDWARE ERROR STATE AT CPE\n");
-		break;
-	      default:
-		prfunc("+MCA UNKNOWN ERROR LOG (UNIMPLEMENTED)\n");
-		break;
+#ifdef CONFIG_ACPI
+	/* If platform doesn't support CPEI, get the timer going. */
+	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
+		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
+		ia64_mca_cpe_poll(0UL);
 	}
-	return platform_err;
-}
+#endif
 
-static int __init
-ia64_mca_disable_cpe_polling(char *str)
-{
-	cpe_poll_enabled = 0;
-	return 1;
+	return 0;
 }
 
-__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
+module_init(ia64_mca_late_init);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/pci.c linux-2.4.26-pre6/arch/ia64/kernel/pci.c
--- linux-2.4.25/arch/ia64/kernel/pci.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/pci.c	2004-03-25 00:19:35.000000000 +0000
@@ -386,10 +386,6 @@ pcibios_config_init (void)
 void __init
 pcibios_init (void)
 {
-#ifdef CONFIG_IA64_MCA
-	ia64_mca_check_errors();    /* For post-failure MCA error logging */
-#endif
-
 	pcibios_config_init();
 
 	platform_pci_fixup(0);	/* phase 0 fixups (before buses scanned) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/ptrace.c linux-2.4.26-pre6/arch/ia64/kernel/ptrace.c
--- linux-2.4.25/arch/ia64/kernel/ptrace.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/ptrace.c	2004-03-25 00:22:20.000000000 +0000
@@ -63,12 +63,25 @@ ia64_get_scratch_nat_bits (struct pt_reg
 	({										\
 		unsigned long bit = ia64_unat_pos(&pt->r##first);			\
 		unsigned long mask = ((1UL << (last - first + 1)) - 1) << first;	\
-		(ia64_rotl(unat, first) >> bit) & mask;					\
+		unsigned long dist;							\
+		if (bit < first)							\
+			dist = 64 + bit - first;					\
+		else									\
+			dist = bit - first;						\
+		ia64_rotr(unat, dist) & mask;						\
 	})
 	unsigned long val;
 
-	val  = GET_BITS( 1,  3, scratch_unat);
-	val |= GET_BITS(12, 15, scratch_unat);
+	/*
+	 * Registers that are stored consecutively in struct pt_regs can be handled in
+	 * parallel.  If the register order in struct_pt_regs changes, this code MUST be
+	 * updated.
+	 */
+	val  = GET_BITS( 1,  1, scratch_unat);
+	val |= GET_BITS( 2,  3, scratch_unat);
+	val |= GET_BITS(12, 13, scratch_unat);
+	val |= GET_BITS(14, 14, scratch_unat);
+	val |= GET_BITS(15, 15, scratch_unat);
 	val |= GET_BITS( 8, 11, scratch_unat);
 	val |= GET_BITS(16, 31, scratch_unat);
 	return val;
@@ -84,16 +97,29 @@ ia64_get_scratch_nat_bits (struct pt_reg
 unsigned long
 ia64_put_scratch_nat_bits (struct pt_regs *pt, unsigned long nat)
 {
+#	define PUT_BITS(first, last, nat)						\
+	({										\
+		unsigned long bit = ia64_unat_pos(&pt->r##first);			\
+		unsigned long mask = ((1UL << (last - first + 1)) - 1) << first;	\
+		long dist;								\
+		if (bit < first)							\
+			dist = 64 + bit - first;					\
+		else									\
+			dist = bit - first;						\
+		ia64_rotl(nat & mask, dist);						\
+	})
 	unsigned long scratch_unat;
 
-#	define PUT_BITS(first, last, nat)					\
-	({									\
-		unsigned long bit = ia64_unat_pos(&pt->r##first);		\
-		unsigned long mask = ((1UL << (last - first + 1)) - 1) << bit;	\
-		(ia64_rotr(nat, first) << bit) & mask;				\
-	})
-	scratch_unat  = PUT_BITS( 1,  3, nat);
-	scratch_unat |= PUT_BITS(12, 15, nat);
+	/*
+	 * Registers that are stored consecutively in struct pt_regs can be handled in
+	 * parallel.  If the register order in struct_pt_regs changes, this code MUST be
+	 * updated.
+	 */
+	scratch_unat  = PUT_BITS( 1,  1, nat);
+	scratch_unat |= PUT_BITS( 2,  3, nat);
+	scratch_unat |= PUT_BITS(12, 13, nat);
+	scratch_unat |= PUT_BITS(14, 14, nat);
+	scratch_unat |= PUT_BITS(15, 15, nat);
 	scratch_unat |= PUT_BITS( 8, 11, nat);
 	scratch_unat |= PUT_BITS(16, 31, nat);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/salinfo.c linux-2.4.26-pre6/arch/ia64/kernel/salinfo.c
--- linux-2.4.25/arch/ia64/kernel/salinfo.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/salinfo.c	2004-03-25 00:19:35.000000000 +0000
@@ -16,6 +16,13 @@
  *   Cache the record across multi-block reads from user space.
  *   Support > 64 cpus.
  *   Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
+ *
+ * Jan 28 2004	kaos@sgi.com
+ *   Periodically check for outstanding MCA or INIT records.
+ *
+ * Feb 21 2004	kaos@sgi.com
+ *   Copy record contents rather than relying on the mca.c buffers, to cope with
+ *   interrupts arriving in mca.c faster than salinfo.c can process them.
  */
 
 #include <linux/types.h>
@@ -23,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/timer.h>
 #include <linux/vmalloc.h>
 
 #include <asm/semaphore.h>
@@ -83,6 +91,7 @@ struct salinfo_data_saved {
 	u64			size;
 	u64			id;
 	int			cpu;
+	int			kmalloced :1;	/* buffer was kmalloc'ed */
 };
 
 /* State transitions.  Actions are :-
@@ -178,6 +187,8 @@ salinfo_platform_oemdata_cpu(void *conte
 static void
 shift1_data_saved (struct salinfo_data *data, int shift)
 {
+	if (data->data_saved[shift].kmalloced)
+		kfree(data->data_saved[shift].buffer);
 	memcpy(data->data_saved+shift, data->data_saved+shift+1,
 	       (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
 	memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
@@ -187,6 +198,8 @@ shift1_data_saved (struct salinfo_data *
 /* This routine is invoked in interrupt context.  Note: mca.c enables
  * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
  * not irq safe, do not call any routines that use spinlocks, they may deadlock.
+ * MCA and INIT records are recorded, a timer event will look for any
+ * outstanding events and wake up the user space code.
  *
  * The buffer passed from mca.c points to the output from ia64_log_get. This is
  * a persistent buffer but its contents can change between the interrupt and
@@ -194,12 +207,12 @@ shift1_data_saved (struct salinfo_data *
  * changes.
  */
 void
-salinfo_log_wakeup(int type, u8 *buffer, u64 size)
+salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
 {
 	struct salinfo_data *data = salinfo_data + type;
 	struct salinfo_data_saved *data_saved;
 	unsigned long flags = 0;
-	int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT;
+	int i;
 	int saved_size = ARRAY_SIZE(data->data_saved);
 
 	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
@@ -221,7 +234,13 @@ salinfo_log_wakeup(int type, u8 *buffer,
 		data_saved->cpu = smp_processor_id();
 		data_saved->id = ((sal_log_record_header_t *)buffer)->id;
 		data_saved->size = size;
-		data_saved->buffer = buffer;
+		if (irqsafe && (data_saved->buffer = kmalloc(size, GFP_ATOMIC))) {
+			memcpy(data_saved->buffer, buffer, size);
+			data_saved->kmalloced = 1;
+		} else {
+			data_saved->buffer = buffer;
+			data_saved->kmalloced = 0;
+		}
 	}
 	if (irqsafe)
 		spin_unlock_irqrestore(&data_saved_lock, flags);
@@ -232,6 +251,35 @@ salinfo_log_wakeup(int type, u8 *buffer,
 	}
 }
 
+/* Check for outstanding MCA/INIT records every 5 minutes (arbitrary) */
+#define SALINFO_TIMER_DELAY (5*60*HZ)
+static struct timer_list salinfo_timer;
+
+static void
+salinfo_timeout_check(struct salinfo_data *data)
+{
+	int i;
+	if (!data->open)
+		return;
+	for (i = 0; i < NR_CPUS; ++i) {
+		if (test_bit(i, &data->cpu_event)) {
+			/* double up() is not a problem, user space will see no
+			 * records for the additional "events".
+			 */
+			up(&data->sem);
+		}
+	}
+}
+
+static void 
+salinfo_timeout (unsigned long arg)
+{
+	salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
+	salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
+	salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
+	add_timer(&salinfo_timer);
+}
+
 static int
 salinfo_event_open(struct inode *inode, struct file *file)
 {
@@ -571,6 +619,11 @@ salinfo_init(void)
 
 	*sdir++ = salinfo_dir;
 
+	init_timer(&salinfo_timer);
+	salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
+	salinfo_timer.function = &salinfo_timeout;
+	add_timer(&salinfo_timer);
+
 	return 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/signal.c linux-2.4.26-pre6/arch/ia64/kernel/signal.c
--- linux-2.4.25/arch/ia64/kernel/signal.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/signal.c	2004-03-25 00:20:20.000000000 +0000
@@ -349,12 +349,6 @@ setup_sigcontext (struct sigcontext *sc,
 		__copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16);
 	}
 
-	/*
-	 * Note: sw->ar_unat is UNDEFINED unless the process is being
-	 * PTRACED.  However, this is OK because the NaT bits of the
-	 * preserved registers (r4-r7) are never being looked at by
-	 * the signal handler (registers r4-r7 are used instead).
-	 */
 	nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat);
 
 	err  = __put_user(flags, &sc->sc_flags);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/smpboot.c linux-2.4.26-pre6/arch/ia64/kernel/smpboot.c
--- linux-2.4.25/arch/ia64/kernel/smpboot.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/smpboot.c	2004-03-25 00:18:24.000000000 +0000
@@ -349,7 +349,6 @@ smp_callin (void)
 
 #ifdef CONFIG_IA64_MCA
 	ia64_mca_cmc_vector_setup();	/* Setup vector on AP & enable */
-	ia64_mca_check_errors();	/* For post-failure MCA error logging */
 #endif
 
 #ifdef CONFIG_PERFMON
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/unwind.c linux-2.4.26-pre6/arch/ia64/kernel/unwind.c
--- linux-2.4.25/arch/ia64/kernel/unwind.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/unwind.c	2004-03-25 00:22:36.000000000 +0000
@@ -1,9 +1,8 @@
 /*
- * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
- * 	- Change pt_regs_off() to make it less dependant on pt_regs structure.
- *
  * Copyright (C) 1999-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
+ * 	- Change pt_regs_off() to make it less dependant on pt_regs structure.
  */
 /*
  * This file implements call frame unwind support for the Linux
@@ -27,7 +26,9 @@
  *	o if both the unw.lock spinlock and a script's read-write lock must be
  *	  acquired, then the read-write lock must be acquired first.
  */
+#include <linux/module.h>
 #include <linux/bootmem.h>
+#include <linux/elf.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -58,15 +59,9 @@
 
 #ifdef UNW_DEBUG
   static unsigned int unw_debug_level = UNW_DEBUG;
-#  ifdef CONFIG_KDB
-#    include <linux/kdb.h>
-#    define UNW_DEBUG_ON(n)	(unw_debug_level >= n && !KDB_IS_RUNNING())
-#    define UNW_DPRINT(n, ...)	if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
-#  else	/* !CONFIG_KDB */
-#    define UNW_DEBUG_ON(n)	unw_debug_level >= n
-     /* Do not code a printk level, not all debug lines end in newline */
-#    define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
-#  endif /* CONFIG_KDB */
+#  define UNW_DEBUG_ON(n)	unw_debug_level >= n
+   /* Do not code a printk level, not all debug lines end in newline */
+#  define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
 #  define inline
 #else /* !UNW_DEBUG */
 #  define UNW_DEBUG_ON(n)  0
@@ -79,7 +74,7 @@
 # define STAT(x...)
 #endif
 
-#define alloc_reg_state()	kmalloc(sizeof(struct unw_state_record), GFP_ATOMIC)
+#define alloc_reg_state()	kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
 #define free_reg_state(usr)	kfree(usr)
 #define alloc_labeled_state()	kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
 #define free_labeled_state(usr)	kfree(usr)
@@ -87,8 +82,6 @@
 typedef unsigned long unw_word;
 typedef unsigned char unw_hash_index_t;
 
-#define struct_offset(str,fld)	((char *)&((str *)NULL)->fld - (char *) 0)
-
 static struct {
 	spinlock_t lock;			/* spinlock for unwind data */
 
@@ -107,6 +100,8 @@ static struct {
 	/* index into unw_frame_info for preserved register i */
 	unsigned short preg_index[UNW_NUM_REGS];
 
+	short pt_regs_offsets[32];
+
 	/* unwind table for the kernel: */
 	struct unw_table kernel_table;
 
@@ -156,47 +151,78 @@ static struct {
 		UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
 	},
 	.preg_index = {
-		struct_offset(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_GR */
-		struct_offset(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_MEM */
-		struct_offset(struct unw_frame_info, bsp_loc)/8,
-		struct_offset(struct unw_frame_info, bspstore_loc)/8,
-		struct_offset(struct unw_frame_info, pfs_loc)/8,
-		struct_offset(struct unw_frame_info, rnat_loc)/8,
-		struct_offset(struct unw_frame_info, psp)/8,
-		struct_offset(struct unw_frame_info, rp_loc)/8,
-		struct_offset(struct unw_frame_info, r4)/8,
-		struct_offset(struct unw_frame_info, r5)/8,
-		struct_offset(struct unw_frame_info, r6)/8,
-		struct_offset(struct unw_frame_info, r7)/8,
-		struct_offset(struct unw_frame_info, unat_loc)/8,
-		struct_offset(struct unw_frame_info, pr_loc)/8,
-		struct_offset(struct unw_frame_info, lc_loc)/8,
-		struct_offset(struct unw_frame_info, fpsr_loc)/8,
-		struct_offset(struct unw_frame_info, b1_loc)/8,
-		struct_offset(struct unw_frame_info, b2_loc)/8,
-		struct_offset(struct unw_frame_info, b3_loc)/8,
-		struct_offset(struct unw_frame_info, b4_loc)/8,
-		struct_offset(struct unw_frame_info, b5_loc)/8,
-		struct_offset(struct unw_frame_info, f2_loc)/8,
-		struct_offset(struct unw_frame_info, f3_loc)/8,
-		struct_offset(struct unw_frame_info, f4_loc)/8,
-		struct_offset(struct unw_frame_info, f5_loc)/8,
-		struct_offset(struct unw_frame_info, fr_loc[16 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[17 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[18 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[19 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[20 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[21 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[22 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[23 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[24 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[25 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[26 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[27 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[28 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[29 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
+		offsetof(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_GR */
+		offsetof(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_MEM */
+		offsetof(struct unw_frame_info, bsp_loc)/8,
+		offsetof(struct unw_frame_info, bspstore_loc)/8,
+		offsetof(struct unw_frame_info, pfs_loc)/8,
+		offsetof(struct unw_frame_info, rnat_loc)/8,
+		offsetof(struct unw_frame_info, psp)/8,
+		offsetof(struct unw_frame_info, rp_loc)/8,
+		offsetof(struct unw_frame_info, r4)/8,
+		offsetof(struct unw_frame_info, r5)/8,
+		offsetof(struct unw_frame_info, r6)/8,
+		offsetof(struct unw_frame_info, r7)/8,
+		offsetof(struct unw_frame_info, unat_loc)/8,
+		offsetof(struct unw_frame_info, pr_loc)/8,
+		offsetof(struct unw_frame_info, lc_loc)/8,
+		offsetof(struct unw_frame_info, fpsr_loc)/8,
+		offsetof(struct unw_frame_info, b1_loc)/8,
+		offsetof(struct unw_frame_info, b2_loc)/8,
+		offsetof(struct unw_frame_info, b3_loc)/8,
+		offsetof(struct unw_frame_info, b4_loc)/8,
+		offsetof(struct unw_frame_info, b5_loc)/8,
+		offsetof(struct unw_frame_info, f2_loc)/8,
+		offsetof(struct unw_frame_info, f3_loc)/8,
+		offsetof(struct unw_frame_info, f4_loc)/8,
+		offsetof(struct unw_frame_info, f5_loc)/8,
+		offsetof(struct unw_frame_info, fr_loc[16 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[17 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[18 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[19 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[20 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[21 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[22 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[23 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[24 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[25 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[26 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[27 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[28 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[29 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[30 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[31 - 16])/8,
+	},
+	.pt_regs_offsets = {
+		[0] = -1,
+		offsetof(struct pt_regs,  r1),
+		offsetof(struct pt_regs,  r2),
+		offsetof(struct pt_regs,  r3),
+		[4] = -1, [5] = -1, [6] = -1, [7] = -1,
+		offsetof(struct pt_regs,  r8),
+		offsetof(struct pt_regs,  r9),
+		offsetof(struct pt_regs, r10),
+		offsetof(struct pt_regs, r11),
+		offsetof(struct pt_regs, r12),
+		offsetof(struct pt_regs, r13),
+		offsetof(struct pt_regs, r14),
+		offsetof(struct pt_regs, r15),
+		offsetof(struct pt_regs, r16),
+		offsetof(struct pt_regs, r17),
+		offsetof(struct pt_regs, r18),
+		offsetof(struct pt_regs, r19),
+		offsetof(struct pt_regs, r20),
+		offsetof(struct pt_regs, r21),
+		offsetof(struct pt_regs, r22),
+		offsetof(struct pt_regs, r23),
+		offsetof(struct pt_regs, r24),
+		offsetof(struct pt_regs, r25),
+		offsetof(struct pt_regs, r26),
+		offsetof(struct pt_regs, r27),
+		offsetof(struct pt_regs, r28),
+		offsetof(struct pt_regs, r29),
+		offsetof(struct pt_regs, r30),
+		offsetof(struct pt_regs, r31),
 	},
 	.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
 #ifdef UNW_DEBUG
@@ -212,11 +238,6 @@ static struct {
 #endif
 };
 
-#define OFF_CASE(reg, reg_num) 					\
-	case reg:						\
-		off=struct_offset(struct pt_regs, reg_num);	\
-		break;
-
 /* Unwind accessors.  */
 
 /*
@@ -225,43 +246,16 @@ static struct {
 static inline unsigned long
 pt_regs_off (unsigned long reg)
 {
-	unsigned long off =0;
+	short off = -1;
 
-	switch (reg)
-	{
-		OFF_CASE(1,r1)
-		OFF_CASE(2,r2)
-		OFF_CASE(3,r3)
-		OFF_CASE(8,r8)
-		OFF_CASE(9,r9)
-		OFF_CASE(10,r10)
-		OFF_CASE(11,r11)
-		OFF_CASE(12,r12)
-		OFF_CASE(13,r13)
-		OFF_CASE(14,r14)
-		OFF_CASE(15,r15)
-		OFF_CASE(16,r16)
-		OFF_CASE(17,r17)
-		OFF_CASE(18,r18)
-		OFF_CASE(19,r19)
-		OFF_CASE(20,r20)
-		OFF_CASE(21,r21)
-		OFF_CASE(22,r22)
-		OFF_CASE(23,r23)
-		OFF_CASE(24,r24)
-		OFF_CASE(25,r25)
-		OFF_CASE(26,r26)
-		OFF_CASE(27,r27)
-		OFF_CASE(28,r28)
-		OFF_CASE(29,r29)
-		OFF_CASE(30,r30)
-		OFF_CASE(31,r31)
-		default:
-			UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
-			break;
-	}
+	if (reg < ARRAY_SIZE(unw.pt_regs_offsets))
+		off = unw.pt_regs_offsets[reg];
 
-	return off;
+	if (off < 0) {
+		UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
+		off = 0;
+	}
+	return (unsigned long) off;
 }
 
 static inline struct pt_regs *
@@ -398,6 +392,7 @@ unw_access_gr (struct unw_frame_info *in
 	}
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_gr);
 
 int
 unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
@@ -429,6 +424,7 @@ unw_access_br (struct unw_frame_info *in
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_br);
 
 int
 unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
@@ -473,6 +469,7 @@ unw_access_fr (struct unw_frame_info *in
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_fr);
 
 int
 unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
@@ -565,6 +562,7 @@ unw_access_ar (struct unw_frame_info *in
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_ar);
 
 int
 unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
@@ -581,6 +579,7 @@ unw_access_pr (struct unw_frame_info *in
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_pr);
 
 
 /* Routines to manipulate the state stack.  */
@@ -826,7 +825,7 @@ desc_prologue (int body, unw_word rlen, 
 static inline void
 desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
 {
-	if (abi == 0 && context == 'i') {
+	if (abi == 3 && context == 'i') {
 		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
 		UNW_DPRINT(3, "unwind.%s: interrupt frame\n",  __FUNCTION__);
 	}
@@ -1177,9 +1176,10 @@ desc_spill_sprel_p (unsigned char qp, un
 static inline unw_hash_index_t
 hash (unsigned long ip)
 {
-#	define magic	0x9e3779b97f4a7c16	/* based on (sqrt(5)/2-1)*2^64 */
+#	define hashmagic	0x9e3779b97f4a7c16	/* based on (sqrt(5)/2-1)*2^64 */
 
-	return (ip >> 4)*magic >> (64 - UNW_LOG_HASH_SIZE);
+	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
+#undef hashmagic
 }
 
 static inline long
@@ -1258,13 +1258,18 @@ script_new (unsigned long ip)
 	spin_unlock(&unw.lock);
 
 	/*
-	 * XXX We'll deadlock here if we interrupt a thread that is
-	 * holding a read lock on script->lock.  A try_write_lock()
-	 * might be mighty handy here...  Alternatively, we could
-	 * disable interrupts whenever we hold a read-lock, but that
-	 * seems silly.
+	 * We'd deadlock here if we interrupted a thread that is holding a read lock on
+	 * script->lock.  Thus, if the write_trylock() fails, we simply bail out.  The
+	 * alternative would be to disable interrupts whenever we hold a read-lock, but
+	 * that seems silly.
 	 */
-	write_lock(&script->lock);
+	/* Kludge: 2.4 has down_write_trylock on semaphores but not write_trylock on
+	 * spinlocks, even though they are both in 2.6 and are identical.  Pretend
+	 * that script lock is a rw_semaphore so we can use the only 2.4 code that
+	 * avoids a deadlock.  KAO.
+	 */
+	if (!down_write_trylock((struct rw_semaphore *)(&script->lock)))
+		return NULL;
 
 	spin_lock(&unw.lock);
 	{
@@ -1415,13 +1420,13 @@ compile_reg (struct unw_state_record *sr
 
 	      case UNW_WHERE_FR:
 		if (rval <= 5)
-			val = unw.preg_index[UNW_REG_F2  + (rval -  1)];
+			val = unw.preg_index[UNW_REG_F2  + (rval -  2)];
 		else if (rval >= 16 && rval <= 31)
 			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 		else {
 			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval <= 11)
-				val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
+				val = offsetof(struct pt_regs, f6) + 16*(rval - 6);
 			else
 				UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
 					   __FUNCTION__, rval);
@@ -1434,11 +1439,11 @@ compile_reg (struct unw_state_record *sr
 		else {
 			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval == 0)
-				val = struct_offset(struct pt_regs, b0);
+				val = offsetof(struct pt_regs, b0);
 			else if (rval == 6)
-				val = struct_offset(struct pt_regs, b6);
+				val = offsetof(struct pt_regs, b6);
 			else
-				val = struct_offset(struct pt_regs, b7);
+				val = offsetof(struct pt_regs, b7);
 		}
 		break;
 
@@ -1638,7 +1643,7 @@ build_script (struct unw_frame_info *inf
 	    && sr.curr.reg[UNW_REG_PSP].val != 0) {
 		/* new psp is sp plus frame size */
 		insn.opc = UNW_INSN_ADD;
-		insn.dst = struct_offset(struct unw_frame_info, psp)/8;
+		insn.dst = offsetof(struct unw_frame_info, psp)/8;
 		insn.val = sr.curr.reg[UNW_REG_PSP].val;	/* frame size */
 		script_emit(script, insn);
 	}
@@ -1772,13 +1777,13 @@ run_script (struct unw_script *script, s
   lazy_init:
 	off = unw.sw_off[val];
 	s[val] = (unsigned long) state->sw + off;
-	if (off >= struct_offset(struct switch_stack, r4) && off <= struct_offset(struct switch_stack, r7))
+	if (off >= offsetof(struct switch_stack, r4) && off <= offsetof(struct switch_stack, r7))
 		/*
 		 * We're initializing a general register: init NaT info, too.  Note that
 		 * the offset is a multiple of 8 which gives us the 3 bits needed for
 		 * the type field.
 		 */
-		s[val+1] = (struct_offset(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
+		s[val+1] = (offsetof(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
 	goto redo;
 }
 
@@ -1868,7 +1873,7 @@ unw_unwind (struct unw_frame_info *info)
 		if ((pr & (1UL << pNonSys)) != 0)
 			num_regs = *info->cfm_loc & 0x7f;		/* size of frame */
 		info->pfs_loc =
-			(unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs));
+			(unsigned long *) (info->pt + offsetof(struct pt_regs, ar_pfs));
 		UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
 	} else
 		num_regs = (*info->cfm_loc >> 7) & 0x7f;	/* size of locals */
@@ -1906,6 +1911,7 @@ unw_unwind (struct unw_frame_info *info)
 	STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 	return retval;
 }
+EXPORT_SYMBOL(unw_unwind);
 
 int
 unw_unwind_to_user (struct unw_frame_info *info)
@@ -1930,6 +1936,7 @@ unw_unwind_to_user (struct unw_frame_inf
 	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
 	return -1;
 }
+EXPORT_SYMBOL(unw_unwind_to_user);
 
 static void
 init_frame_info (struct unw_frame_info *info, struct task_struct *t,
@@ -1987,6 +1994,8 @@ unw_init_from_interruption (struct unw_f
 
 	init_frame_info(info, t, sw, pt->r12);
 	info->cfm_loc = &pt->cr_ifs;
+	info->unat_loc = &pt->ar_unat;
+	info->pfs_loc = &pt->ar_pfs;
 	sof = *info->cfm_loc & 0x7f;
 	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof);
 	info->ip = pt->cr_iip + ia64_psr(pt)->ri;
@@ -2025,6 +2034,7 @@ unw_init_from_blocked_task (struct unw_f
 	UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
 	unw_init_frame_info(info, t, sw);
 }
+EXPORT_SYMBOL(unw_init_from_blocked_task);
 
 static void
 init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/kernel/unwind_i.h linux-2.4.26-pre6/arch/ia64/kernel/unwind_i.h
--- linux-2.4.25/arch/ia64/kernel/unwind_i.h	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/kernel/unwind_i.h	2004-03-25 00:19:27.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2002 Hewlett-Packard Co
+ * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Kernel unwind support.
@@ -45,12 +45,6 @@ struct unw_info_block {
 	/* personality routine and language-specific data follow behind descriptors */
 };
 
-struct unw_table_entry {
-	u64 start_offset;
-	u64 end_offset;
-	u64 info_offset;
-};
-
 struct unw_table {
 	struct unw_table *next;		/* must be first member! */
 	const char *name;
@@ -148,7 +142,7 @@ struct unw_insn {
 };
 
 /*
- * Preserved general static registers (r2-r5) give rise to two script
+ * Preserved general static registers (r4-r7) give rise to two script
  * instructions; everything else yields at most one instruction; at
  * the end of the script, the psp gets popped, accounting for one more
  * instruction.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/sn/kernel/mca.c linux-2.4.26-pre6/arch/ia64/sn/kernel/mca.c
--- linux-2.4.25/arch/ia64/sn/kernel/mca.c	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/sn/kernel/mca.c	2004-03-25 00:21:34.000000000 +0000
@@ -36,6 +36,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <asm/machvec.h>
 #include <asm/mca.h>
 #include <asm/sal.h>
 #include <asm/sn/sn_sal.h>
@@ -53,6 +55,41 @@
 struct timer_list sn_cpei_timer;
 void sn_init_cpei_timer(void);
 
+/* Printing oemdata from mca uses data that is not passed through SAL, it is
+ * global.  Only one user at a time.
+ */
+static DECLARE_MUTEX(sn_oemdata_mutex);
+static u8 **sn_oemdata;
+static u64 *sn_oemdata_size, sn_oemdata_bufsize;
+
+/* Called as the "printk" routine via sn_platform_plat_specific_err_print,
+ * ia64_sn_plat_specific_err_print through SAL to print_hook.  It only handles
+ * a print of '"%s", buf'.  buf is appended to sn_oemdata, resizing as required.
+ */
+static int
+sn_oemdata_print(const char *fmt, ...)
+{
+	va_list args;
+	char *buf;
+	int len;
+	va_start(args, fmt);
+	buf = va_arg(args, char *);
+	va_end(args);
+	len = strlen(buf);
+	while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {
+		u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);
+		if (!newbuf) {
+			printk(KERN_ERR "%s: unable to extend sn_oemdata\n", __FUNCTION__);
+			return 0;
+		}
+		memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);
+		vfree(*sn_oemdata);
+		*sn_oemdata = newbuf;
+	}
+	memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);
+	*sn_oemdata_size += len;
+	return len;
+}
 
 /*
  * print_hook
@@ -86,25 +123,11 @@ print_hook(const char *fmt, ...)
 	newline = (p != 0);
 
 	va_end(args);
-	printk("%s", buf);
+	sn_oemdata_print("%s", buf);	/* args must be '"%s", buf' */
 	return len;
 }
 
 
-
-/*
- * ia64_sn2_platform_plat_specific_err_print
- *
- * Called by the MCA handler to log platform-specific errors.
- */
-void
-ia64_sn2_platform_plat_specific_err_print(int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
-{
-	ia64_sn_plat_specific_err_print(print_hook, p_data - sect_len);
-}
-
-
-
 static void
 sn_cpei_handler(int irq, void *devid, struct pt_regs *regs)
 {
@@ -132,3 +155,42 @@ sn_init_cpei_timer() {
         sn_cpei_timer.function = sn_cpei_timer_handler;
         add_timer(&sn_cpei_timer);
 }
+
+static int
+sn_platform_plat_specific_err_print(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
+{
+	sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header;
+	if (!psei->valid.oem_data)
+		return 0;
+	down(&sn_oemdata_mutex);
+	sn_oemdata = oemdata;
+	sn_oemdata_size = oemdata_size;
+	ia64_sn_plat_specific_err_print(print_hook, (char *)psei);
+	up(&sn_oemdata_mutex);
+	return 0;
+}
+
+/* Callback when userspace salinfo wants to decode oem data via the platform
+ * kernel and/or prom.
+ */
+int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
+{
+	efi_guid_t guid = *(efi_guid_t *)sect_header;
+	*oemdata_size = 0;
+	sn_oemdata_bufsize = 0;
+	vfree(*oemdata);
+	*oemdata = NULL;
+	if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0)
+		return sn_platform_plat_specific_err_print(sect_header, oemdata, oemdata_size);
+	return 0;
+}
+
+static int __init sn_salinfo_init(void)
+{
+	salinfo_platform_oemdata = &sn_salinfo_platform_oemdata;
+        return 0;
+}
+
+module_init(sn_salinfo_init)
+
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/tools/Makefile linux-2.4.26-pre6/arch/ia64/tools/Makefile
--- linux-2.4.25/arch/ia64/tools/Makefile	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ia64/tools/Makefile	2004-03-25 00:20:06.000000000 +0000
@@ -5,6 +5,7 @@ TARGET	= $(TOPDIR)/include/asm-ia64/offs
 all:
 
 mrproper: clean
+	rm -f $(TARGET)
 
 clean:
 	rm -f print_offsets.s print_offsets offsets.h
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/m68k/mac/baboon.c linux-2.4.26-pre6/arch/m68k/mac/baboon.c
--- linux-2.4.25/arch/m68k/mac/baboon.c	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/m68k/mac/baboon.c	2004-03-25 00:20:55.000000000 +0000
@@ -19,8 +19,8 @@
 #include <asm/macints.h> 
 #include <asm/mac_baboon.h>
 
-/* #define DEBUG_BABOON /**/
-/* #define DEBUG_IRQS /**/
+/* #define DEBUG_BABOON */
+/* #define DEBUG_IRQS */
 
 int baboon_present,baboon_active;
 volatile struct baboon *baboon;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/m68k/mac/config.c linux-2.4.26-pre6/arch/m68k/mac/config.c
--- linux-2.4.25/arch/m68k/mac/config.c	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.26-pre6/arch/m68k/mac/config.c	2004-03-25 00:19:26.000000000 +0000
@@ -33,6 +33,7 @@
 #include <asm/pgtable.h>
 #include <asm/rtc.h>
 #include <asm/machdep.h>
+#include <asm/keyboard.h>
 
 #include <asm/macintosh.h>
 #include <asm/macints.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/8260_io/Config.in linux-2.4.26-pre6/arch/ppc/8260_io/Config.in
--- linux-2.4.25/arch/ppc/8260_io/Config.in	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/8260_io/Config.in	1970-01-01 00:00:00.000000000 +0000
@@ -1,26 +0,0 @@
-#
-# MPC8260 Communication options
-#
-mainmenu_option next_comment
-comment 'MPC8260 CPM Options'
-bool 'Enable SCC Console' CONFIG_SCC_CONSOLE
-if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
-  bool 'CPM SCC Ethernet' CONFIG_SCC_ENET
-  if [ "$CONFIG_SCC_ENET" = "y" ]; then
-  bool 'Ethernet on SCC1' CONFIG_SCC1_ENET
-    if [ "$CONFIG_SCC1_ENET" != "y" ]; then
-      bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
-    fi
-  fi
-#
-#  CONFIG_FEC_ENET is only used to get netdevices to call our init
-#    function.  Any combination of FCC1,2,3 are supported.
-#
-  bool 'FCC Ethernet' CONFIG_FEC_ENET
-  if [ "$CONFIG_FEC_ENET" = "y" ]; then
-    bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
-    bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
-    bool 'Ethernet on FCC3' CONFIG_FCC3_ENET
-  fi
-fi
-endmenu
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/8260_io/Makefile linux-2.4.26-pre6/arch/ppc/8260_io/Makefile
--- linux-2.4.25/arch/ppc/8260_io/Makefile	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/8260_io/Makefile	1970-01-01 00:00:00.000000000 +0000
@@ -1,17 +0,0 @@
-#
-# Makefile for the linux MPC8xx ppc-specific parts of comm processor
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-O_TARGET		:= 8260_io.o
-
-obj-y			:= commproc.o uart.o
-
-obj-$(CONFIG_FEC_ENET)	+= fcc_enet.o
-obj-$(CONFIG_SCC_ENET)	+= enet.o
-
-include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/8260_io/commproc.c linux-2.4.26-pre6/arch/ppc/8260_io/commproc.c
--- linux-2.4.25/arch/ppc/8260_io/commproc.c	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/8260_io/commproc.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,179 +0,0 @@
-/*
- * General Purpose functions for the global management of the
- * 8260 Communication Processor Module.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
- *	2.3.99 Updates
- *
- * In addition to the individual control of the communication
- * channels, there are a few functions that globally affect the
- * communication processor.
- *
- * Buffer descriptors must be allocated from the dual ported memory
- * space.  The allocator for that is here.  When the communication
- * process is reset, we reclaim the memory available.  There is
- * currently no deallocator for this memory.
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/bootmem.h>
-#include <asm/irq.h>
-#include <asm/mpc8260.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/immap_8260.h>
-#include <asm/cpm_8260.h>
-
-static	uint	dp_alloc_base;	/* Starting offset in DP ram */
-static	uint	dp_alloc_top;	/* Max offset + 1 */
-static	uint	host_buffer;	/* One page of host buffer */
-static	uint	host_end;	/* end + 1 */
-cpm8260_t	*cpmp;		/* Pointer to comm processor space */
-
-/* We allocate this here because it is used almost exclusively for
- * the communication processor devices.
- */
-immap_t		*immr;
-
-void
-m8260_cpm_reset(void)
-{
-	volatile immap_t	 *imp;
-	volatile cpm8260_t	*commproc;
-	uint			vpgaddr;
-
-	immr = imp = (volatile immap_t *)IMAP_ADDR;
-	commproc = &imp->im_cpm;
-
-	/* Reclaim the DP memory for our use.
-	*/
-	dp_alloc_base = CPM_DATAONLY_BASE;
-	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
-
-	/* Set the host page for allocation.
-	*/
-	host_buffer =
-		(uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
-	host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
-
-	vpgaddr = host_buffer;
-
-	/* Tell everyone where the comm processor resides.
-	*/
-	cpmp = (cpm8260_t *)commproc;
-}
-
-/* Allocate some memory from the dual ported ram.
- * To help protocols with object alignment restrictions, we do that
- * if they ask.
- */
-uint
-m8260_cpm_dpalloc(uint size, uint align)
-{
-	uint	retloc;
-	uint	align_mask, off;
-	uint	savebase;
-
-	align_mask = align - 1;
-	savebase = dp_alloc_base;
-
-	if ((off = (dp_alloc_base & align_mask)) != 0)
-		dp_alloc_base += (align - off);
-
-	if ((dp_alloc_base + size) >= dp_alloc_top) {
-		dp_alloc_base = savebase;
-		return(CPM_DP_NOSPACE);
-	}
-
-	retloc = dp_alloc_base;
-	dp_alloc_base += size;
-
-	return(retloc);
-}
-
-/* We also own one page of host buffer space for the allocation of
- * UART "fifos" and the like.
- */
-uint
-m8260_cpm_hostalloc(uint size, uint align)
-{
-	uint	retloc;
-	uint	align_mask, off;
-	uint	savebase;
-
-	align_mask = align - 1;
-	savebase = host_buffer;
-
-	if ((off = (host_buffer & align_mask)) != 0)
-		host_buffer += (align - off);
-
-	if ((host_buffer + size) >= host_end) {
-		host_buffer = savebase;
-		return(0);
-	}
-
-	retloc = host_buffer;
-	host_buffer += size;
-
-	return(retloc);
-}
-
-/* Set a baud rate generator.  This needs lots of work.  There are
- * eight BRGs, which can be connected to the CPM channels or output
- * as clocks.  The BRGs are in two different block of internal
- * memory mapped space.
- * The baud rate clock is the system clock divided by something.
- * It was set up long ago during the initial boot phase and is
- * is given to us.
- * Baud rate clocks are zero-based in the driver code (as that maps
- * to port numbers).  Documentation uses 1-based numbering.
- */
-#define BRG_INT_CLK	(((bd_t *)__res)->bi_brgfreq)
-#define BRG_UART_CLK	(BRG_INT_CLK/16)
-
-/* This function is used by UARTS, or anything else that uses a 16x
- * oversampled clock.
- */
-void
-m8260_cpm_setbrg(uint brg, uint rate)
-{
-	volatile uint	*bp;
-
-	/* This is good enough to get SMCs running.....
-	*/
-	if (brg < 4) {
-		bp = (uint *)&immr->im_brgc1;
-	}
-	else {
-		bp = (uint *)&immr->im_brgc5;
-		brg -= 4;
-	}
-	bp += brg;
-	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
-}
-
-/* This function is used to set high speed synchronous baud rate
- * clocks.
- */
-void
-m8260_cpm_fastbrg(uint brg, uint rate, int div16)
-{
-	volatile uint	*bp;
-
-	if (brg < 4) {
-		bp = (uint *)&immr->im_brgc1;
-	}
-	else {
-		bp = (uint *)&immr->im_brgc5;
-		brg -= 4;
-	}
-	bp += brg;
-	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
-	if (div16)
-		*bp |= CPM_BRG_DIV16;
-}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/8260_io/enet.c linux-2.4.26-pre6/arch/ppc/8260_io/enet.c
--- linux-2.4.25/arch/ppc/8260_io/enet.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/8260_io/enet.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,857 +0,0 @@
-/*
- * Ethernet driver for Motorola MPC8260.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
- *	2.3.99 Updates
- *
- * I copied this from the 8xx CPM Ethernet driver, so follow the
- * credits back through that.
- *
- * This version of the driver is somewhat selectable for the different
- * processor/board combinations.  It works for the boards I know about
- * now, and should be easily modified to include others.  Some of the
- * configuration information is contained in <asm/commproc.h> and the
- * remainder is here.
- *
- * Buffer descriptors are kept in the CPM dual port RAM, and the frame
- * buffers are in the host memory.
- *
- * Right now, I am very watseful with the buffers.  I allocate memory
- * pages and then divide them into 2K frame buffers.  This way I know I
- * have buffers large enough to hold one frame within one buffer descriptor.
- * Once I get this working, I will use 64 or 128 byte CPM buffers, which
- * will be much more memory efficient and will easily handle lots of
- * small packets.
- *
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-
-#include <asm/immap_8260.h>
-#include <asm/pgtable.h>
-#include <asm/mpc8260.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/cpm_8260.h>
-#include <asm/irq.h>
-
-/*
- *				Theory of Operation
- *
- * The MPC8260 CPM performs the Ethernet processing on an SCC.  It can use
- * an aribtrary number of buffers on byte boundaries, but must have at
- * least two receive buffers to prevent constant overrun conditions.
- *
- * The buffer descriptors are allocated from the CPM dual port memory
- * with the data buffers allocated from host memory, just like all other
- * serial communication protocols.  The host memory buffers are allocated
- * from the free page pool, and then divided into smaller receive and
- * transmit buffers.  The size of the buffers should be a power of two,
- * since that nicely divides the page.  This creates a ring buffer
- * structure similar to the LANCE and other controllers.
- *
- * Like the LANCE driver:
- * The driver runs as two independent, single-threaded flows of control.  One
- * is the send-packet routine, which enforces single-threaded use by the
- * cep->tx_busy flag.  The other thread is the interrupt handler, which is
- * single threaded by the hardware and other software.
- */
-
-/* The transmitter timeout
- */
-#define TX_TIMEOUT	(2*HZ)
-
-/* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it is best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter.  We just use
- * the skbuffer directly.
- */
-#define CPM_ENET_RX_PAGES	4
-#define CPM_ENET_RX_FRSIZE	2048
-#define CPM_ENET_RX_FRPPG	(PAGE_SIZE / CPM_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
-#define TX_RING_SIZE		8	/* Must be power of two */
-#define TX_RING_MOD_MASK	7	/*   for this to work */
-
-/* The CPM stores dest/src/type, data, and checksum for receive packets.
- */
-#define PKT_MAXBUF_SIZE		1518
-#define PKT_MINBUF_SIZE		64
-#define PKT_MAXBLR_SIZE		1520
-
-/* The CPM buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct scc_enet_private {
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
-	ushort	skb_cur;
-	ushort	skb_dirty;
-
-	/* CPM dual port RAM relative addresses.
-	*/
-	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
-	cbd_t	*tx_bd_base;
-	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
-	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
-	scc_t	*sccp;
-	struct	net_device_stats stats;
-	uint	tx_free;
-	spinlock_t lock;
-};
-
-static int scc_enet_open(struct net_device *dev);
-static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int scc_enet_rx(struct net_device *dev);
-static void scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
-static int scc_enet_close(struct net_device *dev);
-static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-/* These will be configurable for the SCC choice.
-*/
-#define CPM_ENET_BLOCK	CPM_CR_SCC1_SBLOCK
-#define CPM_ENET_PAGE	CPM_CR_SCC1_PAGE
-#define PROFF_ENET	PROFF_SCC1
-#define SCC_ENET	0
-#define SIU_INT_ENET	SIU_INT_SCC1
-
-/* These are both board and SCC dependent....
-*/
-#define PD_ENET_RXD	((uint)0x00000001)
-#define PD_ENET_TXD	((uint)0x00000002)
-#define PD_ENET_TENA	((uint)0x00000004)
-#define PC_ENET_RENA	((uint)0x00020000)
-#define PC_ENET_CLSN	((uint)0x00000004)
-#define PC_ENET_TXCLK	((uint)0x00000800)
-#define PC_ENET_RXCLK	((uint)0x00000400)
-#define CMX_CLK_ROUTE	((uint)0x25000000)
-#define CMX_CLK_MASK	((uint)0xff000000)
-
-/* Specific to a board.
-*/
-#define PC_EST8260_ENET_LOOPBACK	((uint)0x80000000)
-#define PC_EST8260_ENET_SQE		((uint)0x40000000)
-#define PC_EST8260_ENET_NOTFD		((uint)0x20000000)
-
-static int
-scc_enet_open(struct net_device *dev)
-{
-
-	/* I should reset the ring buffers here, but I don't yet know
-	 * a simple way to do that.
-	 */
-	netif_start_queue(dev);
-	return 0;					/* Always succeed */
-}
-
-static int
-scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
-	volatile cbd_t	*bdp;
-
-
-	/* Fill in a Tx ring entry */
-	bdp = cep->cur_tx;
-
-#ifndef final_version
-	if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
-		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since the tx queue should be stopped.
-		 */
-		printk("%s: tx queue full!.\n", dev->name);
-		return 1;
-	}
-#endif
-
-	/* Clear all of the status flags.
-	 */
-	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
-
-	/* If the frame is short, tell CPM to pad it.
-	*/
-	if (skb->len <= ETH_ZLEN)
-		bdp->cbd_sc |= BD_ENET_TX_PAD;
-	else
-		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
-
-	/* Set buffer length and buffer pointer.
-	*/
-	bdp->cbd_datlen = skb->len;
-	bdp->cbd_bufaddr = __pa(skb->data);
-
-	/* Save skb pointer.
-	*/
-	cep->tx_skbuff[cep->skb_cur] = skb;
-
-	cep->stats.tx_bytes += skb->len;
-	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
-
-	spin_lock_irq(&cep->lock);
-
-	/* Send it on its way.  Tell CPM its ready, interrupt when done,
-	 * its the last BD of the frame, and to put the CRC on the end.
-	 */
-	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
-
-	dev->trans_start = jiffies;
-
-	/* If this was the last BD in the ring, start at the beginning again.
-	*/
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = cep->tx_bd_base;
-	else
-		bdp++;
-
-	if (!--cep->tx_free)
-		netif_stop_queue(dev);
-
-	cep->cur_tx = (cbd_t *)bdp;
-
-	spin_unlock_irq(&cep->lock);
-
-	return 0;
-}
-
-static void
-scc_enet_timeout(struct net_device *dev)
-{
-	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
-
-	printk("%s: transmit timed out.\n", dev->name);
-	cep->stats.tx_errors++;
-#ifndef final_version
-	{
-		int	i;
-		cbd_t	*bdp;
-		printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n",
-		       cep->cur_tx, cep->tx_free,
-		       cep->cur_rx);
-		bdp = cep->tx_bd_base;
-		printk(" Tx @base %p :\n", bdp);
-		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-		bdp = cep->rx_bd_base;
-		printk(" Rx @base %p :\n", bdp);
-		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-	}
-#endif
-	if (cep->tx_free)
-		netif_wake_queue(dev);
-}
-
-/* The interrupt handler.
- * This is called from the CPM handler, not the MPC core interrupt.
- */
-static void
-scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
-	struct	net_device *dev = dev_id;
-	volatile struct	scc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	ushort	int_events;
-	int	must_restart;
-
-	cep = (struct scc_enet_private *)dev->priv;
-
-	/* Get the interrupt events that caused us to be here.
-	*/
-	int_events = cep->sccp->scc_scce;
-	cep->sccp->scc_scce = int_events;
-	must_restart = 0;
-
-	/* Handle receive event in its own function.
-	*/
-	if (int_events & SCCE_ENET_RXF)
-		scc_enet_rx(dev_id);
-
-	/* Check for a transmit error.  The manual is a little unclear
-	 * about this, so the debug code until I get it figured out.  It
-	 * appears that if TXE is set, then TXB is not set.  However,
-	 * if carrier sense is lost during frame transmission, the TXE
-	 * bit is set, "and continues the buffer transmission normally."
-	 * I don't know if "normally" implies TXB is set when the buffer
-	 * descriptor is closed.....trial and error :-).
-	 */
-
-	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
-	*/
-	if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
-	    spin_lock(&cep->lock);
-	    bdp = cep->dirty_tx;
-	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
-		if (cep->tx_free == TX_RING_SIZE)
-		    break;
-
-		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
-			cep->stats.tx_heartbeat_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
-			cep->stats.tx_window_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
-			cep->stats.tx_aborted_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
-			cep->stats.tx_fifo_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
-			cep->stats.tx_carrier_errors++;
-
-
-		/* No heartbeat or Lost carrier are not really bad errors.
-		 * The others require a restart transmit command.
-		 */
-		if (bdp->cbd_sc &
-		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
-			must_restart = 1;
-			cep->stats.tx_errors++;
-		}
-
-		cep->stats.tx_packets++;
-
-		/* Deferred means some collisions occurred during transmit,
-		 * but we eventually sent the packet OK.
-		 */
-		if (bdp->cbd_sc & BD_ENET_TX_DEF)
-			cep->stats.collisions++;
-
-		/* Free the sk buffer associated with this last transmit.
-		*/
-		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
-		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
-
-		/* Update pointer to next buffer descriptor to be transmitted.
-		*/
-		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-			bdp = cep->tx_bd_base;
-		else
-			bdp++;
-
-		/* I don't know if we can be held off from processing these
-		 * interrupts for more than one frame time.  I really hope
-		 * not.  In such a case, we would now want to check the
-		 * currently available BD (cur_tx) and determine if any
-		 * buffers between the dirty_tx and cur_tx have also been
-		 * sent.  We would want to process anything in between that
-		 * does not have BD_ENET_TX_READY set.
-		 */
-
-		/* Since we have freed up a buffer, the ring is no longer
-		 * full.
-		 */
-		if (!cep->tx_free++) {
-			if (netif_queue_stopped(dev)) {
-				netif_wake_queue(dev);
-			}
-		}
-
-		cep->dirty_tx = (cbd_t *)bdp;
-	    }
-
-	    if (must_restart) {
-		volatile cpm8260_t *cp;
-
-		/* Some transmit errors cause the transmitter to shut
-		 * down.  We now issue a restart transmit.  Since the
-		 * errors close the BD and update the pointers, the restart
-		 * _should_ pick up without having to reset any of our
-		 * pointers either.
-		 */
-
-		cp = cpmp;
-		cp->cp_cpcr =
-		    mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
-		    			CPM_CR_RESTART_TX) | CPM_CR_FLG;
-		while (cp->cp_cpcr & CPM_CR_FLG);
-	    }
-	    spin_unlock(&cep->lock);
-	}
-
-	/* Check for receive busy, i.e. packets coming but no place to
-	 * put them.
-	 */
-	if (int_events & SCCE_ENET_BSY)
-		cep->stats.rx_dropped++;
-
-	return;
-}
-
-/* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- * not been given to the system, we just set the empty indicator,
- * effectively tossing the packet.
- */
-static int
-scc_enet_rx(struct net_device *dev)
-{
-	struct	scc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	struct	sk_buff *skb;
-	ushort	pkt_len;
-
-	cep = (struct scc_enet_private *)dev->priv;
-
-	/* First, grab all of the stats for the incoming packet.
-	 * These get messed up if we get called due to a busy condition.
-	 */
-	bdp = cep->cur_rx;
-
-for (;;) {
-	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
-		break;
-
-#ifndef final_version
-	/* Since we have allocated space to hold a complete frame, both
-	 * the first and last indicators should be set.
-	 */
-	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
-		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
-			printk("CPM ENET: rcv is not first+last\n");
-#endif
-
-	/* Frame too long or too short.
-	*/
-	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-		cep->stats.rx_length_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
-		cep->stats.rx_frame_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
-		cep->stats.rx_crc_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
-		cep->stats.rx_crc_errors++;
-
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
-	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
-		cep->stats.rx_frame_errors++;
-	}
-	else {
-
-		/* Process the incoming frame.
-		*/
-		cep->stats.rx_packets++;
-		pkt_len = bdp->cbd_datlen;
-		cep->stats.rx_bytes += pkt_len;
-
-		/* This does 16 byte alignment, much more than we need.
-		 * The packet length includes FCS, but we don't want to
-		 * include that when passing upstream as it messes up
-		 * bridging applications.
-		 */
-		skb = dev_alloc_skb(pkt_len-4);
-
-		if (skb == NULL) {
-			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-			cep->stats.rx_dropped++;
-		}
-		else {
-			skb->dev = dev;
-			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
-				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len-4, 0);
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb);
-		}
-	}
-
-	/* Clear the status flags for this buffer.
-	*/
-	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
-
-	/* Mark the buffer empty.
-	*/
-	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
-
-	/* Update BD pointer to next entry.
-	*/
-	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
-		bdp = cep->rx_bd_base;
-	else
-		bdp++;
-
-   }
-	cep->cur_rx = (cbd_t *)bdp;
-
-	return 0;
-}
-
-static int
-scc_enet_close(struct net_device *dev)
-{
-	/* Don't know what to do yet.
-	*/
-	netif_stop_queue(dev);
-
-	return 0;
-}
-
-static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
-{
-	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
-
-	return &cep->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- * Skeleton taken from sunlance driver.
- * The CPM Ethernet implementation allows Multicast as well as individual
- * MAC address filtering.  Some of the drivers check to make sure it is
- * a group multicast address, and discard those that are not.  I guess I
- * will do the same for now, but just remove the test if you want
- * individual filtering as well (do the upper net layers want or support
- * this kind of feature?).
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-	struct	scc_enet_private *cep;
-	struct	dev_mc_list *dmi;
-	u_char	*mcptr, *tdptr;
-	volatile scc_enet_t *ep;
-	int	i, j;
-	cep = (struct scc_enet_private *)dev->priv;
-
-	/* Get pointer to SCC area in parameter RAM.
-	*/
-	ep = (scc_enet_t *)dev->base_addr;
-
-	if (dev->flags&IFF_PROMISC) {
-
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
-		cep->sccp->scc_pmsr |= SCC_PSMR_PRO;
-	} else {
-
-		cep->sccp->scc_pmsr &= ~SCC_PSMR_PRO;
-
-		if (dev->flags & IFF_ALLMULTI) {
-			/* Catch all multicast addresses, so set the
-			 * filter to all 1's.
-			 */
-			ep->sen_gaddr1 = 0xffff;
-			ep->sen_gaddr2 = 0xffff;
-			ep->sen_gaddr3 = 0xffff;
-			ep->sen_gaddr4 = 0xffff;
-		}
-		else {
-			/* Clear filter and add the addresses in the list.
-			*/
-			ep->sen_gaddr1 = 0;
-			ep->sen_gaddr2 = 0;
-			ep->sen_gaddr3 = 0;
-			ep->sen_gaddr4 = 0;
-
-			dmi = dev->mc_list;
-
-			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
-
-				/* Only support group multicast for now.
-				*/
-				if (!(dmi->dmi_addr[0] & 1))
-					continue;
-
-				/* The address in dmi_addr is LSB first,
-				 * and taddr is MSB first.  We have to
-				 * copy bytes MSB first from dmi_addr.
-				 */
-				mcptr = (u_char *)dmi->dmi_addr + 5;
-				tdptr = (u_char *)&ep->sen_taddrh;
-				for (j=0; j<6; j++)
-					*tdptr++ = *mcptr--;
-
-				/* Ask CPM to run CRC and set bit in
-				 * filter mask.
-				 */
-				cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
-						CPM_ENET_BLOCK, 0,
-						CPM_CR_SET_GADDR) | CPM_CR_FLG;
-				/* this delay is necessary here -- Cort */
-				udelay(10);
-				while (cpmp->cp_cpcr & CPM_CR_FLG);
-			}
-		}
-	}
-}
-
-/* Initialize the CPM Ethernet on SCC.
- */
-int __init scc_enet_init(void)
-{
-	struct net_device *dev;
-	struct scc_enet_private *cep;
-	int i, j;
-	unsigned char	*eap;
-	unsigned long	mem_addr;
-	bd_t		*bd;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-	volatile	scc_t		*sccp;
-	volatile	scc_enet_t	*ep;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	cp = cpmp;	/* Get pointer to Communication Processor */
-
-	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
-	io = &immap->im_ioport;
-
-	bd = (bd_t *)__res;
-
-	/* Allocate some private information.
-	*/
-	cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
-	if (cep == NULL)
-		return -ENOMEM;
-
-	__clear_user(cep,sizeof(*cep));
-	spin_lock_init(&cep->lock);
-
-	/* Create an Ethernet device instance.
-	*/
-	dev = init_etherdev(0, 0);
-
-	/* Get pointer to SCC area in parameter RAM.
-	*/
-	ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
-
-	/* And another to the SCC register area.
-	*/
-	sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
-	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */
-
-	/* Disable receive and transmit in case someone left it running.
-	*/
-	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
-	/* Configure port C and D pins for SCC Ethernet.  This
-	 * won't work for all SCC possibilities....it will be
-	 * board/port specific.
-	 */
-	io->iop_pparc |=
-		(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
-	io->iop_pdirc &=
-		~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
-	io->iop_psorc &=
-		~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
-	io->iop_psorc |= PC_ENET_CLSN;
-
-	io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
-	io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
-	io->iop_pdird &= ~PD_ENET_RXD;
-	io->iop_psord |= PD_ENET_TXD;
-	io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
-
-	/* Configure Serial Interface clock routing.
-	 * First, clear all SCC bits to zero, then set the ones we want.
-	 */
-	immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
-	immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
-
-	/* Allocate space for the buffer descriptors in the DP ram.
-	 * These are relative offsets in the DP ram address space.
-	 * Initialize base addresses for the buffer descriptors.
-	 */
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
-	ep->sen_genscc.scc_rbase = i;
-	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
-	ep->sen_genscc.scc_tbase = i;
-	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-
-	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
-	cep->tx_free = TX_RING_SIZE;
-	cep->cur_rx = cep->rx_bd_base;
-
-	ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-	ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-	/* Set maximum bytes per receive buffer.
-	 * This appears to be an Ethernet frame size, not the buffer
-	 * fragment size.  It must be a multiple of four.
-	 */
-	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
-
-	/* Set CRC preset and mask.
-	*/
-	ep->sen_cpres = 0xffffffff;
-	ep->sen_cmask = 0xdebb20e3;
-
-	ep->sen_crcec = 0;	/* CRC Error counter */
-	ep->sen_alec = 0;	/* alignment error counter */
-	ep->sen_disfc = 0;	/* discard frame counter */
-
-	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
-	ep->sen_retlim = 15;	/* Retry limit threshold */
-
-	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
-	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
-
-	ep->sen_maxd1 = PKT_MAXBLR_SIZE;	/* maximum DMA1 length */
-	ep->sen_maxd2 = PKT_MAXBLR_SIZE;	/* maximum DMA2 length */
-
-	/* Clear hash tables.
-	*/
-	ep->sen_gaddr1 = 0;
-	ep->sen_gaddr2 = 0;
-	ep->sen_gaddr3 = 0;
-	ep->sen_gaddr4 = 0;
-	ep->sen_iaddr1 = 0;
-	ep->sen_iaddr2 = 0;
-	ep->sen_iaddr3 = 0;
-	ep->sen_iaddr4 = 0;
-
-	/* Set Ethernet station address.
-	 *
-	 * This is supplied in the board information structure, so we
-	 * copy that into the controller.
-	 */
-	eap = (unsigned char *)&(ep->sen_paddrh);
-	for (i=5; i>=0; i--)
-		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-
-	ep->sen_pper = 0;	/* 'cause the book says so */
-	ep->sen_taddrl = 0;	/* temp address (LSB) */
-	ep->sen_taddrm = 0;
-	ep->sen_taddrh = 0;	/* temp address (MSB) */
-
-	/* Now allocate the host memory pages and initialize the
-	 * buffer descriptors.
-	 */
-	bdp = cep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	bdp = cep->rx_bd_base;
-	for (i=0; i<CPM_ENET_RX_PAGES; i++) {
-
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += CPM_ENET_RX_FRSIZE;
-			bdp++;
-		}
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* Let's re-initialize the channel now.  We have to do it later
-	 * than the manual describes because we have just now finished
-	 * the BD initialization.
-	 */
-	cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
-			CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	cep->skb_cur = cep->skb_dirty = 0;
-
-	sccp->scc_scce = 0xffff;	/* Clear any pending events */
-
-	/* Enable interrupts for transmit error, complete frame
-	 * received, and any transmit buffer we have also set the
-	 * interrupt flag.
-	 */
-	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
-
-	/* Install our interrupt handler.
-	*/
-	request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
-
-	/* Set GSMR_H to enable all normal operating modes.
-	 * Set GSMR_L to enable Ethernet to MC68160.
-	 */
-	sccp->scc_gsmrh = 0;
-	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
-
-	/* Set sync/delimiters.
-	*/
-	sccp->scc_dsr = 0xd555;
-
-	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
-	 * start frame search 22 bit times after RENA.
-	 */
-	sccp->scc_pmsr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
-
-	/* It is now OK to enable the Ethernet transmitter.
-	 * Unfortunately, there are board implementation differences here.
-	 */
-	io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
-				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
-	io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
-				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
-	io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
-				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
-	io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
-	io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
-
-	dev->base_addr = (unsigned long)ep;
-	dev->priv = cep;
-
-	/* The CPM Ethernet specific entries in the device structure. */
-	dev->open = scc_enet_open;
-	dev->hard_start_xmit = scc_enet_start_xmit;
-	dev->tx_timeout = scc_enet_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->stop = scc_enet_close;
-	dev->get_stats = scc_enet_get_stats;
-	dev->set_multicast_list = set_multicast_list;
-
-	/* And last, enable the transmit and receive processing.
-	*/
-	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
-	printk("%s: SCC ENET Version 0.1, ", dev->name);
-	for (i=0; i<5; i++)
-		printk("%02x:", dev->dev_addr[i]);
-	printk("%02x\n", dev->dev_addr[5]);
-
-	return 0;
-}
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/8260_io/fcc_enet.c linux-2.4.26-pre6/arch/ppc/8260_io/fcc_enet.c
--- linux-2.4.25/arch/ppc/8260_io/fcc_enet.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/8260_io/fcc_enet.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,1613 +0,0 @@
-/*
- * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
- * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
- *
- * This version of the driver is a combination of the 8xx fec and
- * 8260 SCC Ethernet drivers.  People seem to be choosing common I/O
- * configurations, so this driver will work on the EST8260 boards and
- * others yet to be announced.
- *
- * Right now, I am very watseful with the buffers.  I allocate memory
- * pages and then divide them into 2K frame buffers.  This way I know I
- * have buffers large enough to hold one frame within one buffer descriptor.
- * Once I get this working, I will use 64 or 128 byte CPM buffers, which
- * will be much more memory efficient and will easily handle lots of
- * small packets.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-
-#include <asm/immap_8260.h>
-#include <asm/pgtable.h>
-#include <asm/mpc8260.h>
-#include <asm/irq.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/cpm_8260.h>
-
-/* The transmitter timeout
- */
-#define TX_TIMEOUT	(2*HZ)
-
-/* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it is best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter.  We just use
- * the skbuffer directly.
- */
-#define FCC_ENET_RX_PAGES	16
-#define FCC_ENET_RX_FRSIZE	2048
-#define FCC_ENET_RX_FRPPG	(PAGE_SIZE / FCC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
-#define TX_RING_SIZE		16	/* Must be power of two */
-#define TX_RING_MOD_MASK	15	/*   for this to work */
-
-/* The FCC stores dest/src/type, data, and checksum for receive packets.
- */
-#define PKT_MAXBUF_SIZE		1518
-#define PKT_MINBUF_SIZE		64
-
-/* Maximum input DMA size.  Must be a should(?) be a multiple of 4.
-*/
-#define PKT_MAXDMA_SIZE		1520
-
-/* Maximum input buffer size.  Must be a multiple of 32.
-*/
-#define PKT_MAXBLR_SIZE		1536
-
-static int fcc_enet_open(struct net_device *dev);
-static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int fcc_enet_rx(struct net_device *dev);
-static void fcc_enet_mii(struct net_device *dev);
-static	void fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
-static int fcc_enet_close(struct net_device *dev);
-static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void restart_fcc(struct net_device *dev);
-
-/* These will be configurable for the FCC choice.
- * Multiple ports can be configured.  There is little choice among the
- * I/O pins to the PHY, except the clocks.  We will need some board
- * dependent clock selection.
- * Why in the hell did I put these inside #ifdef's?  I dunno, maybe to
- * help show what pins are used for each device.
- */
-
-/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PA1_COL		((uint)0x00000001)
-#define PA1_CRS		((uint)0x00000002)
-#define PA1_TXER	((uint)0x00000004)
-#define PA1_TXEN	((uint)0x00000008)
-#define PA1_RXDV	((uint)0x00000010)
-#define PA1_RXER	((uint)0x00000020)
-#define PA1_TXDAT	((uint)0x00003c00)
-#define PA1_RXDAT	((uint)0x0003c000)
-#define PA1_PSORA0	(PA1_RXDAT | PA1_TXDAT)
-#define PA1_PSORA1	(PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
-				PA1_RXDV | PA1_RXER)
-#define PA1_DIRA0	(PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
-#define PA1_DIRA1	(PA1_TXDAT | PA1_TXEN | PA1_TXER)
-
-/* CLK12 is receive, CLK11 is transmit.  These are board specific.
-*/
-#define PC_F1RXCLK	((uint)0x00000800)
-#define PC_F1TXCLK	((uint)0x00000400)
-#define CMX1_CLK_ROUTE	((uint)0x3e000000)
-#define CMX1_CLK_MASK	((uint)0xff000000)
-
-/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB2_TXER	((uint)0x00000001)
-#define PB2_RXDV	((uint)0x00000002)
-#define PB2_TXEN	((uint)0x00000004)
-#define PB2_RXER	((uint)0x00000008)
-#define PB2_COL		((uint)0x00000010)
-#define PB2_CRS		((uint)0x00000020)
-#define PB2_TXDAT	((uint)0x000003c0)
-#define PB2_RXDAT	((uint)0x00003c00)
-#define PB2_PSORB0	(PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
-				PB2_RXER | PB2_RXDV | PB2_TXER)
-#define PB2_PSORB1	(PB2_TXEN)
-#define PB2_DIRB0	(PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
-#define PB2_DIRB1	(PB2_TXDAT | PB2_TXEN | PB2_TXER)
-
-/* CLK13 is receive, CLK14 is transmit.  These are board dependent.
-*/
-#define PC_F2RXCLK	((uint)0x00001000)
-#define PC_F2TXCLK	((uint)0x00002000)
-#define CMX2_CLK_ROUTE	((uint)0x00250000)
-#define CMX2_CLK_MASK	((uint)0x00ff0000)
-
-/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB3_RXDV	((uint)0x00004000)
-#define PB3_RXER	((uint)0x00008000)
-#define PB3_TXER	((uint)0x00010000)
-#define PB3_TXEN	((uint)0x00020000)
-#define PB3_COL		((uint)0x00040000)
-#define PB3_CRS		((uint)0x00080000)
-#define PB3_TXDAT	((uint)0x0f000000)
-#define PB3_RXDAT	((uint)0x00f00000)
-#define PB3_PSORB0	(PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
-				PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
-#define PB3_PSORB1	(0)
-#define PB3_DIRB0	(PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
-#define PB3_DIRB1	(PB3_TXDAT | PB3_TXEN | PB3_TXER)
-
-/* CLK15 is receive, CLK16 is transmit.  These are board dependent.
-*/
-#define PC_F3RXCLK	((uint)0x00004000)
-#define PC_F3TXCLK	((uint)0x00008000)
-#define CMX3_CLK_ROUTE	((uint)0x00003700)
-#define CMX3_CLK_MASK	((uint)0x0000ff00)
-
-/* MII status/control serial interface.
-*/
-#define PC_MDIO		((uint)0x00400000)
-#define PC_MDCK		((uint)0x00200000)
-
-/* A table of information for supporting FCCs.  This does two things.
- * First, we know how many FCCs we have and they are always externally
- * numbered from zero.  Second, it holds control register and I/O
- * information that could be different among board designs.
- */
-typedef struct fcc_info {
-	uint	fc_fccnum;
-	uint	fc_cpmblock;
-	uint	fc_cpmpage;
-	uint	fc_proff;
-	uint	fc_interrupt;
-	uint	fc_trxclocks;
-	uint	fc_clockroute;
-	uint	fc_clockmask;
-	uint	fc_mdio;
-	uint	fc_mdck;
-} fcc_info_t;
-
-static fcc_info_t fcc_ports[] = {
-#ifdef CONFIG_FCC1_ENET
-	{ 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
-		(PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
-		PC_MDIO, PC_MDCK },
-#endif
-#ifdef CONFIG_FCC2_ENET
-	{ 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
-		(PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
-		PC_MDIO, PC_MDCK },
-#endif
-#ifdef CONFIG_FCC3_ENET
-	{ 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
-		(PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
-		PC_MDIO, PC_MDCK },
-#endif
-};
-
-/* The FCC buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct fcc_enet_private {
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
-	ushort	skb_cur;
-	ushort	skb_dirty;
-
-	/* CPM dual port RAM relative addresses.
-	*/
-	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
-	cbd_t	*tx_bd_base;
-	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
-	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
-	volatile fcc_t	*fccp;
-	volatile fcc_enet_t	*ep;
-	struct	net_device_stats stats;
-	uint	tx_full;
-	spinlock_t lock;
-	uint	phy_address;
-	uint	phy_type;
-	uint	phy_duplex;
-	fcc_info_t	*fip;
-};
-
-static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
-	volatile immap_t *immap);
-static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
-static void init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
-	volatile immap_t *immap);
-static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
-	volatile immap_t *immap);
-
-/* MII processing.  We keep this as simple as possible.  Requests are
- * placed on the list (if there is room).  When the request is finished
- * by the MII, an optional function may be called.
- */
-typedef struct mii_list {
-	uint	mii_regval;
-	void	(*mii_func)(uint val, struct net_device *dev);
-	struct	mii_list *mii_next;
-} mii_list_t;
-
-#define		NMII	20
-mii_list_t	mii_cmds[NMII];
-mii_list_t	*mii_free;
-mii_list_t	*mii_head;
-mii_list_t	*mii_tail;
-
-static	int	phyaddr;
-static	uint	phytype;
-
-static int	mii_queue(int request, void (*func)(uint, struct net_device *));
-static void	mii_startup_cmds(void);
-static uint	mii_send_receive(fcc_info_t *fip, uint cmd);
-
-/* Make MII read/write commands for the FCC.
-*/
-
-#define mk_mii_phyaddr(ADDR)	(0x60020000 | ((ADDR) << 23) | (2 << 18))
-
-#define mk_mii_read(REG)	(0x60020000 | ((phyaddr << 23) | \
-						(REG & 0x1f) << 18))
-
-#define mk_mii_write(REG, VAL)	(0x50020000 | ((phyaddr << 23) | \
-						(REG & 0x1f) << 18) | \
-						(VAL & 0xffff))
-
-
-static int
-fcc_enet_open(struct net_device *dev)
-{
-	netif_start_queue(dev);
-	return 0;					/* Always succeed */
-}
-
-static int
-fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
-	volatile cbd_t	*bdp;
-
-
-	/* Fill in a Tx ring entry */
-	bdp = cep->cur_tx;
-
-#ifndef final_version
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since cep->tx_full should be set.
-		 */
-		printk("%s: tx queue full!.\n", dev->name);
-		return 1;
-	}
-#endif
-
-	/* Clear all of the status flags.
-	 */
-	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
-
-	/* If the frame is short, tell CPM to pad it.
-	*/
-	if (skb->len <= ETH_ZLEN)
-		bdp->cbd_sc |= BD_ENET_TX_PAD;
-	else
-		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
-
-	/* Set buffer length and buffer pointer.
-	*/
-	bdp->cbd_datlen = skb->len;
-	bdp->cbd_bufaddr = __pa(skb->data);
-
-	/* Save skb pointer.
-	*/
-	cep->tx_skbuff[cep->skb_cur] = skb;
-
-	cep->stats.tx_bytes += skb->len;
-	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
-
-	spin_lock_irq(&cep->lock);
-
-	/* Send it on its way.  Tell CPM its ready, interrupt when done,
-	 * its the last BD of the frame, and to put the CRC on the end.
-	 */
-	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
-
-#if 0
-	/* Errata says don't do this.
-	*/
-	cep->fccp->fcc_ftodr = 0x8000;
-#endif
-	dev->trans_start = jiffies;
-
-	/* If this was the last BD in the ring, start at the beginning again.
-	*/
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = cep->tx_bd_base;
-	else
-		bdp++;
-
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		netif_stop_queue(dev);
-		cep->tx_full = 1;
-	}
-
-	cep->cur_tx = (cbd_t *)bdp;
-
-	spin_unlock_irq(&cep->lock);
-
-	return 0;
-}
-
-
-static void
-fcc_enet_timeout(struct net_device *dev)
-{
-	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
-
-	printk("%s: transmit timed out.\n", dev->name);
-	cep->stats.tx_errors++;
-#ifndef final_version
-	{
-		int	i;
-		cbd_t	*bdp;
-		printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
-		       cep->cur_tx, cep->tx_full ? " (full)" : "",
-		       cep->cur_rx);
-		bdp = cep->tx_bd_base;
-		printk(" Tx @base %p :\n", bdp);
-		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-		bdp = cep->rx_bd_base;
-		printk(" Rx @base %p :\n", bdp);
-		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-	}
-#endif
-	if (!cep->tx_full)
-		netif_wake_queue(dev);
-}
-
-/* The interrupt handler.
- */
-static void
-fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
-	struct	net_device *dev = dev_id;
-	volatile struct	fcc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	ushort	int_events;
-	int	must_restart;
-
-	cep = (struct fcc_enet_private *)dev->priv;
-
-	/* Get the interrupt events that caused us to be here.
-	*/
-	int_events = cep->fccp->fcc_fcce;
-	cep->fccp->fcc_fcce = int_events;
-	must_restart = 0;
-
-	/* Handle receive event in its own function.
-	*/
-	if (int_events & FCC_ENET_RXF)
-		fcc_enet_rx(dev_id);
-
-	/* Check for a transmit error.  The manual is a little unclear
-	 * about this, so the debug code until I get it figured out.  It
-	 * appears that if TXE is set, then TXB is not set.  However,
-	 * if carrier sense is lost during frame transmission, the TXE
-	 * bit is set, "and continues the buffer transmission normally."
-	 * I don't know if "normally" implies TXB is set when the buffer
-	 * descriptor is closed.....trial and error :-).
-	 */
-
-	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
-	*/
-	if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) {
-	    spin_lock(&cep->lock);
-	    bdp = cep->dirty_tx;
-	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
-		if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
-		    break;
-
-		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
-			cep->stats.tx_heartbeat_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
-			cep->stats.tx_window_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
-			cep->stats.tx_aborted_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
-			cep->stats.tx_fifo_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
-			cep->stats.tx_carrier_errors++;
-
-
-		/* No heartbeat or Lost carrier are not really bad errors.
-		 * The others require a restart transmit command.
-		 */
-		if (bdp->cbd_sc &
-		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
-			must_restart = 1;
-			cep->stats.tx_errors++;
-		}
-
-		cep->stats.tx_packets++;
-
-		/* Deferred means some collisions occurred during transmit,
-		 * but we eventually sent the packet OK.
-		 */
-		if (bdp->cbd_sc & BD_ENET_TX_DEF)
-			cep->stats.collisions++;
-
-		/* Free the sk buffer associated with this last transmit.
-		*/
-		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
-		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
-
-		/* Update pointer to next buffer descriptor to be transmitted.
-		*/
-		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-			bdp = cep->tx_bd_base;
-		else
-			bdp++;
-
-		/* I don't know if we can be held off from processing these
-		 * interrupts for more than one frame time.  I really hope
-		 * not.  In such a case, we would now want to check the
-		 * currently available BD (cur_tx) and determine if any
-		 * buffers between the dirty_tx and cur_tx have also been
-		 * sent.  We would want to process anything in between that
-		 * does not have BD_ENET_TX_READY set.
-		 */
-
-		/* Since we have freed up a buffer, the ring is no longer
-		 * full.
-		 */
-		if (cep->tx_full) {
-			cep->tx_full = 0;
-			if (netif_queue_stopped(dev)) {
-				netif_wake_queue(dev);
-			}
-		}
-
-		cep->dirty_tx = (cbd_t *)bdp;
-	    }
-
-	    if (must_restart) {
-		volatile cpm8260_t *cp;
-
-		/* Some transmit errors cause the transmitter to shut
-		 * down.  We now issue a restart transmit.  Since the
-		 * errors close the BD and update the pointers, the restart
-		 * _should_ pick up without having to reset any of our
-		 * pointers either.
-		 */
-
-		cp = cpmp;
-		cp->cp_cpcr =
-		    mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
-		    		0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
-		while (cp->cp_cpcr & CPM_CR_FLG);
-	    }
-	    spin_unlock(&cep->lock);
-	}
-
-	/* Check for receive busy, i.e. packets coming but no place to
-	 * put them.
-	 */
-	if (int_events & FCC_ENET_BSY) {
-		cep->stats.rx_dropped++;
-	}
-	return;
-}
-
-/* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- * not been given to the system, we just set the empty indicator,
- * effectively tossing the packet.
- */
-static int
-fcc_enet_rx(struct net_device *dev)
-{
-	struct	fcc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	struct	sk_buff *skb;
-	ushort	pkt_len;
-
-	cep = (struct fcc_enet_private *)dev->priv;
-
-	/* First, grab all of the stats for the incoming packet.
-	 * These get messed up if we get called due to a busy condition.
-	 */
-	bdp = cep->cur_rx;
-
-for (;;) {
-	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
-		break;
-
-#ifndef final_version
-	/* Since we have allocated space to hold a complete frame, both
-	 * the first and last indicators should be set.
-	 */
-	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
-		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
-			printk("CPM ENET: rcv is not first+last\n");
-#endif
-
-	/* Frame too long or too short.
-	*/
-	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-		cep->stats.rx_length_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
-		cep->stats.rx_frame_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
-		cep->stats.rx_crc_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
-		cep->stats.rx_crc_errors++;
-
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
-	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
-		cep->stats.rx_frame_errors++;
-	}
-	else {
-
-		/* Process the incoming frame.
-		*/
-		cep->stats.rx_packets++;
-		pkt_len = bdp->cbd_datlen;
-		cep->stats.rx_bytes += pkt_len;
-
-		/* This does 16 byte alignment, much more than we need.
-		 * The packet length includes FCS, but we don't want to
-		 * include that when passing upstream as it messes up
-		 * bridging applications.
-		 */
-		skb = dev_alloc_skb(pkt_len-4);
-
-		if (skb == NULL) {
-			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-			cep->stats.rx_dropped++;
-		}
-		else {
-			skb->dev = dev;
-			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
-				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len-4, 0);
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb);
-		}
-	}
-
-	/* Clear the status flags for this buffer.
-	*/
-	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
-
-	/* Mark the buffer empty.
-	*/
-	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
-
-	/* Update BD pointer to next entry.
-	*/
-	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
-		bdp = cep->rx_bd_base;
-	else
-		bdp++;
-
-   }
-	cep->cur_rx = (cbd_t *)bdp;
-
-	return 0;
-}
-
-static int
-fcc_enet_close(struct net_device *dev)
-{
-	/* Don't know what to do yet.
-	*/
-	netif_stop_queue(dev);
-
-	return 0;
-}
-
-static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
-{
-	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
-
-	return &cep->stats;
-}
-
-/* The MII is simulated from the 8xx FEC implementation.  The FCC
- * is not responsible for the MII control/status interface.
- */
-static void
-fcc_enet_mii(struct net_device *dev)
-{
-	struct	fcc_enet_private *fep;
-	mii_list_t	*mip;
-	uint		mii_reg;
-
-	fep = (struct fcc_enet_private *)dev->priv;
-#if 0
-	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
-	mii_reg = ep->fec_mii_data;
-#endif
-
-	if ((mip = mii_head) == NULL) {
-		printk("MII and no head!\n");
-		return;
-	}
-
-	if (mip->mii_func != NULL)
-		(*(mip->mii_func))(mii_reg, dev);
-
-	mii_head = mip->mii_next;
-	mip->mii_next = mii_free;
-	mii_free = mip;
-
-#if 0
-	if ((mip = mii_head) != NULL)
-		ep->fec_mii_data = mip->mii_regval;
-#endif
-}
-
-static int
-mii_queue(int regval, void (*func)(uint, struct net_device *))
-{
-	unsigned long	flags;
-	mii_list_t	*mip;
-	int		retval;
-
-	retval = 0;
-
-	save_flags(flags);
-	cli();
-
-	if ((mip = mii_free) != NULL) {
-		mii_free = mip->mii_next;
-		mip->mii_regval = regval;
-		mip->mii_func = func;
-		mip->mii_next = NULL;
-		if (mii_head) {
-			mii_tail->mii_next = mip;
-			mii_tail = mip;
-		}
-		else {
-			mii_head = mii_tail = mip;
-#if 0
-			(&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
-#endif
-		}
-	}
-	else {
-		retval = 1;
-	}
-
-	restore_flags(flags);
-
-	return(retval);
-}
-
-static	volatile uint	full_duplex;
-
-static void
-mii_status(uint mii_reg, struct net_device *dev)
-{
-	volatile uint	prev_duplex;
-
-	if (((mii_reg >> 18) & 0x1f) == 1) {
-		/* status register.
-		*/
-		printk("fec: ");
-		if (mii_reg & 0x0004)
-			printk("link up");
-		else
-			printk("link down");
-
-		if (mii_reg & 0x0010)
-			printk(",remote fault");
-		if (mii_reg & 0x0020)
-			printk(",auto complete");
-		printk("\n");
-	}
-	if (((mii_reg >> 18) & 0x1f) == 0x14) {
-		/* Extended chip status register.
-		*/
-		prev_duplex = full_duplex;
-		printk("fec: ");
-		if (mii_reg & 0x0800)
-			printk("100 Mbps");
-		else
-			printk("10 Mbps");
-
-		if (mii_reg & 0x1000) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-#if 0
-		if (prev_duplex != full_duplex)
-			restart_fec(dev);
-#endif
-	}
-	if (((mii_reg >> 18) & 0x1f) == 31) {
-		/* QS6612 PHY Control/Status.
-		 * OK, now we have it all, so figure out what is going on.
-		 */
-		prev_duplex = full_duplex;
-		printk("fec: ");
-
-		mii_reg = (mii_reg >> 2) & 7;
-
-		if (mii_reg & 1)
-			printk("10 Mbps");
-		else
-			printk("100 Mbps");
-
-		if (mii_reg > 4) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-
-#if 0
-		if (prev_duplex != full_duplex)
-			restart_fec(dev);
-#endif
-	}
-}
-
-static	uint	phyno;
-
-static void
-mii_discover_phy3(uint mii_reg, struct net_device *dev)
-{
-	phytype <<= 16;
-	phytype |= (mii_reg & 0xffff);
-	printk("fec: Phy @ 0x%x, type 0x%08x\n", phyno, phytype);
-	mii_startup_cmds();
-}
-
-static void
-mii_discover_phy(uint mii_reg, struct net_device *dev)
-{
-	if (phyno < 32) {
-		if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
-			phyaddr = phyno;
-			mii_queue(mk_mii_read(3), mii_discover_phy3);
-		}
-		else {
-			phyno++;
-			mii_queue(mk_mii_phyaddr(phyno), mii_discover_phy);
-		}
-	}
-	else {
-		printk("FEC: No PHY device found.\n");
-	}
-}
-
-static void
-mii_discover_phy_poll(fcc_info_t *fip)
-{
-	uint	rv;
-	int	i;
-
-	for (i=0; i<32; i++) {
-		rv = mii_send_receive(fip, mk_mii_phyaddr(i));
-		if ((phytype = (rv & 0xffff)) != 0xffff) {
-			phyaddr = i;
-			rv = mii_send_receive(fip, mk_mii_read(3));
-			phytype <<= 16;
-			phytype |= (rv & 0xffff);
-			printk("fec: Phy @ 0x%x, type 0x%08x\n", phyaddr, phytype);
-		}
-	}
-}
-
-static	void
-mii_startup_cmds(void)
-{
-
-#if 1
-	/* Level One PHY.
-	*/
-
-	/* Read status registers to clear any pending interrupt.
-	*/
-	mii_queue(mk_mii_read(1), mii_status);
-	mii_queue(mk_mii_read(18), mii_status);
-
-	/* Read extended chip status register.
-	*/
-	mii_queue(mk_mii_read(0x14), mii_status);
-
-	/* Set default operation of 100-TX....for some reason
-	 * some of these bits are set on power up, which is wrong.
-	 */
-	mii_queue(mk_mii_write(0x13, 0), NULL);
-
-	/* Enable Link status change interrupts.
-	*/
-	mii_queue(mk_mii_write(0x11, 0x0002), NULL);
-
-	/* Don't advertize Full duplex.
-	mii_queue(mk_mii_write(0x04, 0x0021), NULL);
-	*/
-#endif
-
-}
-
-/* This supports the mii_link interrupt below.
- * We should get called three times.  Once for register 1, once for
- * register 18, and once for register 20.
- */
-static	uint mii_saved_reg1;
-
-static void
-mii_relink(uint mii_reg, struct net_device *dev)
-{
-	volatile uint	prev_duplex;
-	unsigned long	flags;
-
-	if (((mii_reg >> 18) & 0x1f) == 1) {
-		/* Just save the status register and get out.
-		*/
-		mii_saved_reg1 = mii_reg;
-		return;
-	}
-	if (((mii_reg >> 18) & 0x1f) == 18) {
-		/* Not much here, but has to be read to clear the
-		 * interrupt condition.
-		 */
-		if ((mii_reg & 0x8000) == 0)
-			printk("fec: re-link and no IRQ?\n");
-		if ((mii_reg & 0x4000) == 0)
-			printk("fec: no PHY power?\n");
-	}
-	if (((mii_reg >> 18) & 0x1f) == 20) {
-		/* Extended chip status register.
-		 * OK, now we have it all, so figure out what is going on.
-		 */
-		prev_duplex = full_duplex;
-		printk("fec: ");
-		if (mii_saved_reg1 & 0x0004)
-			printk("link up");
-		else
-			printk("link down");
-
-		if (mii_saved_reg1 & 0x0010)
-			printk(", remote fault");
-		if (mii_saved_reg1 & 0x0020)
-			printk(", auto complete");
-
-		if (mii_reg & 0x0800)
-			printk(", 100 Mbps");
-		else
-			printk(", 10 Mbps");
-
-		if (mii_reg & 0x1000) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-		if (prev_duplex != full_duplex) {
-			save_flags(flags);
-			cli();
-#if 0
-			restart_fec(dev);
-#endif
-			restore_flags(flags);
-		}
-	}
-	if (((mii_reg >> 18) & 0x1f) == 31) {
-		/* QS6612 PHY Control/Status.
-		 * OK, now we have it all, so figure out what is going on.
-		 */
-		prev_duplex = full_duplex;
-		printk("fec: ");
-		if (mii_saved_reg1 & 0x0004)
-			printk("link up");
-		else
-			printk("link down");
-
-		if (mii_saved_reg1 & 0x0010)
-			printk(", remote fault");
-		if (mii_saved_reg1 & 0x0020)
-			printk(", auto complete");
-
-		mii_reg = (mii_reg >> 2) & 7;
-
-		if (mii_reg & 1)
-			printk(", 10 Mbps");
-		else
-			printk(", 100 Mbps");
-
-		if (mii_reg > 4) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-
-#if 0
-		if (prev_duplex != full_duplex) {
-			save_flags(flags);
-			cli();
-			restart_fec(dev);
-			restore_flags(flags);
-		}
-#endif
-	}
-}
-
-/* Set or clear the multicast filter for this adaptor.
- * Skeleton taken from sunlance driver.
- * The CPM Ethernet implementation allows Multicast as well as individual
- * MAC address filtering.  Some of the drivers check to make sure it is
- * a group multicast address, and discard those that are not.  I guess I
- * will do the same for now, but just remove the test if you want
- * individual filtering as well (do the upper net layers want or support
- * this kind of feature?).
- */
-static void
-set_multicast_list(struct net_device *dev)
-{
-	struct	fcc_enet_private *cep;
-	struct	dev_mc_list *dmi;
-	u_char	*mcptr, *tdptr;
-	volatile fcc_enet_t *ep;
-	int	i, j;
-
-	cep = (struct fcc_enet_private *)dev->priv;
-
-return;
-	/* Get pointer to FCC area in parameter RAM.
-	*/
-	ep = (fcc_enet_t *)dev->base_addr;
-
-	if (dev->flags&IFF_PROMISC) {
-
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
-		cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
-	} else {
-
-		cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
-
-		if (dev->flags & IFF_ALLMULTI) {
-			/* Catch all multicast addresses, so set the
-			 * filter to all 1's.
-			 */
-			ep->fen_gaddrh = 0xffffffff;
-			ep->fen_gaddrl = 0xffffffff;
-		}
-		else {
-			/* Clear filter and add the addresses in the list.
-			*/
-			ep->fen_gaddrh = 0;
-			ep->fen_gaddrl = 0;
-
-			dmi = dev->mc_list;
-
-			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
-
-				/* Only support group multicast for now.
-				*/
-				if (!(dmi->dmi_addr[0] & 1))
-					continue;
-
-				/* The address in dmi_addr is LSB first,
-				 * and taddr is MSB first.  We have to
-				 * copy bytes MSB first from dmi_addr.
-				 */
-				mcptr = (u_char *)dmi->dmi_addr + 5;
-				tdptr = (u_char *)&ep->fen_taddrh;
-				for (j=0; j<6; j++)
-					*tdptr++ = *mcptr--;
-
-				/* Ask CPM to run CRC and set bit in
-				 * filter mask.
-				 */
-				cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage,
-						cep->fip->fc_cpmblock, 0x0c,
-						CPM_CR_SET_GADDR) | CPM_CR_FLG;
-				udelay(10);
-				while (cpmp->cp_cpcr & CPM_CR_FLG);
-			}
-		}
-	}
-}
-
-/* Initialize the CPM Ethernet on FCC.
- */
-int __init fec_enet_init(void)
-{
-	struct net_device *dev;
-	struct fcc_enet_private *cep;
-	fcc_info_t	*fip;
-	int	i, np;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
-	io = &immap->im_ioport;
-
-	np = sizeof(fcc_ports) / sizeof(fcc_info_t);
-	fip = fcc_ports;
-
-	while (np-- > 0) {
-
-		/* Allocate some private information.
-		*/
-		cep = (struct fcc_enet_private *)
-					kmalloc(sizeof(*cep), GFP_KERNEL);
-		if (cep == NULL)
-			return -ENOMEM;
-
-		__clear_user(cep,sizeof(*cep));
-		spin_lock_init(&cep->lock);
-		cep->fip = fip;
-
-		/* Create an Ethernet device instance.
-		*/
-		dev = init_etherdev(0, 0);
-		dev->priv = cep;
-
-		init_fcc_shutdown(fip, cep, immap);
-		init_fcc_ioports(fip, io, immap);
-		init_fcc_param(fip, dev, immap);
-
-		dev->base_addr = (unsigned long)(cep->ep);
-
-		/* The CPM Ethernet specific entries in the device
-		 * structure.
-		 */
-		dev->open = fcc_enet_open;
-		dev->hard_start_xmit = fcc_enet_start_xmit;
-		dev->tx_timeout = fcc_enet_timeout;
-		dev->watchdog_timeo = TX_TIMEOUT;
-		dev->stop = fcc_enet_close;
-		dev->get_stats = fcc_enet_get_stats;
-		dev->set_multicast_list = set_multicast_list;
-
-		init_fcc_startup(fip, dev);
-
-		printk("%s: FCC ENET Version 0.2, ", dev->name);
-		for (i=0; i<5; i++)
-			printk("%02x:", dev->dev_addr[i]);
-		printk("%02x\n", dev->dev_addr[5]);
-
-		/* This is just a hack for now that works only on the EST
-		 * board, or anything else that has MDIO/CK configured.
-		 * It is mainly to test the MII software clocking.
-		 */
-		mii_discover_phy_poll(fip);
-
-		fip++;
-	}
-
-	return 0;
-}
-
-/* Make sure the device is shut down during initialization.
-*/
-static void __init
-init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
-						volatile immap_t *immap)
-{
-	volatile	fcc_enet_t	*ep;
-	volatile	fcc_t		*fccp;
-
-	/* Get pointer to FCC area in parameter RAM.
-	*/
-	ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
-
-	/* And another to the FCC register area.
-	*/
-	fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
-	cep->fccp = fccp;		/* Keep the pointers handy */
-	cep->ep = ep;
-
-	/* Disable receive and transmit in case someone left it running.
-	*/
-	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
-}
-
-/* Initialize the I/O pins for the FCC Ethernet.
-*/
-static void __init
-init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
-						volatile immap_t *immap)
-{
-
-	/* FCC1 pins are on port A/C.  FCC2/3 are port B/C.
-	*/
-	if (fip->fc_proff == PROFF_FCC1) {
-		/* Configure port A and C pins for FCC1 Ethernet.
-		 */
-		io->iop_pdira &= ~PA1_DIRA0;
-		io->iop_pdira |= PA1_DIRA1;
-		io->iop_psora &= ~PA1_PSORA0;
-		io->iop_psora |= PA1_PSORA1;
-		io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
-	}
-	if (fip->fc_proff == PROFF_FCC2) {
-		/* Configure port B and C pins for FCC Ethernet.
-		 */
-		io->iop_pdirb &= ~PB2_DIRB0;
-		io->iop_pdirb |= PB2_DIRB1;
-		io->iop_psorb &= ~PB2_PSORB0;
-		io->iop_psorb |= PB2_PSORB1;
-		io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
-	}
-	if (fip->fc_proff == PROFF_FCC3) {
-		/* Configure port B and C pins for FCC Ethernet.
-		 */
-		io->iop_pdirb &= ~PB3_DIRB0;
-		io->iop_pdirb |= PB3_DIRB1;
-		io->iop_psorb &= ~PB3_PSORB0;
-		io->iop_psorb |= PB3_PSORB1;
-		io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
-	}
-
-	/* Port C has clocks......
-	*/
-	io->iop_psorc &= ~(fip->fc_trxclocks);
-	io->iop_pdirc &= ~(fip->fc_trxclocks);
-	io->iop_pparc |= fip->fc_trxclocks;
-
-	/* ....and the MII serial clock/data.
-	*/
-	io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
-	io->iop_podrc |= fip->fc_mdio;
-	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
-	io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
-
-	/* Configure Serial Interface clock routing.
-	 * First, clear all FCC bits to zero,
-	 * then set the ones we want.
-	 */
-	immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
-	immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
-}
-
-static void __init
-init_fcc_param(fcc_info_t *fip, struct net_device *dev,
-						volatile immap_t *immap)
-{
-	unsigned char	*eap;
-	unsigned long	mem_addr;
-	bd_t		*bd;
-	int		i, j;
-	struct		fcc_enet_private *cep;
-	volatile	fcc_enet_t	*ep;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-
-	cep = (struct fcc_enet_private *)(dev->priv);
-	ep = cep->ep;
-	cp = cpmp;
-
-	bd = (bd_t *)__res;
-
-	/* Zero the whole thing.....I must have missed some individually.
-	 * It works when I do this.
-	 */
-	memset((char *)ep, 0, sizeof(fcc_enet_t));
-
-	/* Allocate space for the buffer descriptors in the DP ram.
-	 * These are relative offsets in the DP ram address space.
-	 * Initialize base addresses for the buffer descriptors.
-	 */
-#if 0
-	/* I really want to do this, but for some reason it doesn't
-	 * work with the data cache enabled, so I allocate from the
-	 * main memory instead.
-	 */
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_rbase = (uint)&immap->im_dprambase[i];
-	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_tbase = (uint)&immap->im_dprambase[i];
-	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-#else
-	cep->rx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
-	cep->tx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
-#endif
-
-	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
-	cep->cur_rx = cep->rx_bd_base;
-
-	ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
-	ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
-
-	/* Set maximum bytes per receive buffer.
-	 * It must be a multiple of 32.
-	 */
-	ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
-
-	/* Allocate space in the reserved FCC area of DPRAM for the
-	 * internal buffers.  No one uses this space (yet), so we
-	 * can do this.  Later, we will add resource management for
-	 * this area.
-	 */
-	mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
-	ep->fen_genfcc.fcc_riptr = mem_addr;
-	ep->fen_genfcc.fcc_tiptr = mem_addr+32;
-	ep->fen_padptr = mem_addr+64;
-	memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
-
-	ep->fen_genfcc.fcc_rbptr = 0;
-	ep->fen_genfcc.fcc_tbptr = 0;
-	ep->fen_genfcc.fcc_rcrc = 0;
-	ep->fen_genfcc.fcc_tcrc = 0;
-	ep->fen_genfcc.fcc_res1 = 0;
-	ep->fen_genfcc.fcc_res2 = 0;
-
-	ep->fen_camptr = 0;	/* CAM isn't used in this driver */
-
-	/* Set CRC preset and mask.
-	*/
-	ep->fen_cmask = 0xdebb20e3;
-	ep->fen_cpres = 0xffffffff;
-
-	ep->fen_crcec = 0;	/* CRC Error counter */
-	ep->fen_alec = 0;	/* alignment error counter */
-	ep->fen_disfc = 0;	/* discard frame counter */
-	ep->fen_retlim = 15;	/* Retry limit threshold */
-	ep->fen_pper = 0;	/* Normal persistence */
-
-	/* Clear hash filter tables.
-	*/
-	ep->fen_gaddrh = 0;
-	ep->fen_gaddrl = 0;
-	ep->fen_iaddrh = 0;
-	ep->fen_iaddrl = 0;
-
-	/* Clear the Out-of-sequence TxBD.
-	*/
-	ep->fen_tfcstat = 0;
-	ep->fen_tfclen = 0;
-	ep->fen_tfcptr = 0;
-
-	ep->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
-	ep->fen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
-
-	/* Set Ethernet station address.
-	 *
-	 * This is supplied in the board information structure, so we
-	 * copy that into the controller.
-	 * So, far we have only been given one Ethernet address. We make
-	 * it unique by setting a few bits in the upper byte of the
-	 * non-static part of the address.
-	 */
-	eap = (unsigned char *)&(ep->fen_paddrh);
-	for (i=5; i>=0; i--) {
-
-/* 
- * The EP8260 only uses FCC3, so we can safely give it the real
- * MAC address.
- */
-#ifndef CONFIG_RPX6
-		if (i == 3) {
-			dev->dev_addr[i] = bd->bi_enetaddr[i];
-			dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
-			*eap++ = dev->dev_addr[i];
-		}
-		else {
-			*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-		}
-#else
-		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-#endif
-	}
-
-	ep->fen_taddrh = 0;
-	ep->fen_taddrm = 0;
-	ep->fen_taddrl = 0;
-
-	ep->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length */
-	ep->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length */
-
-	/* Clear stat counters, in case we ever enable RMON.
-	*/
-	ep->fen_octc = 0;
-	ep->fen_colc = 0;
-	ep->fen_broc = 0;
-	ep->fen_mulc = 0;
-	ep->fen_uspc = 0;
-	ep->fen_frgc = 0;
-	ep->fen_ospc = 0;
-	ep->fen_jbrc = 0;
-	ep->fen_p64c = 0;
-	ep->fen_p65c = 0;
-	ep->fen_p128c = 0;
-	ep->fen_p256c = 0;
-	ep->fen_p512c = 0;
-	ep->fen_p1024c = 0;
-
-	ep->fen_rfthr = 0;	/* Suggested by manual */
-	ep->fen_rfcnt = 0;
-	ep->fen_cftype = 0;
-
-	/* Now allocate the host memory pages and initialize the
-	 * buffer descriptors.
-	 */
-	bdp = cep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_datlen = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	bdp = cep->rx_bd_base;
-	for (i=0; i<FCC_ENET_RX_PAGES; i++) {
-
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		for (j=0; j<FCC_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
-			bdp->cbd_datlen = 0;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += FCC_ENET_RX_FRSIZE;
-			bdp++;
-		}
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* Let's re-initialize the channel now.  We have to do it later
-	 * than the manual describes because we have just now finished
-	 * the BD initialization.
-	 */
-	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
-			CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	cep->skb_cur = cep->skb_dirty = 0;
-}
-
-/* Let 'er rip.
-*/
-static void __init
-init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
-{
-	volatile fcc_t	*fccp;
-	struct fcc_enet_private *cep;
-
-	cep = (struct fcc_enet_private *)(dev->priv);
-	fccp = cep->fccp;
-
-	fccp->fcc_fcce = 0xffff;	/* Clear any pending events */
-
-	/* Enable interrupts for transmit error, complete frame
-	 * received, and any transmit buffer we have also set the
-	 * interrupt flag.
-	 */
-	fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
-
-	/* Install our interrupt handler.
-	*/
-	if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",
-				dev) < 0)
-		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
-
-	/* Set GFMR to enable Ethernet operating mode.
-	 */
-	fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
-
-	/* Set sync/delimiters.
-	*/
-	fccp->fcc_fdsr = 0xd555;
-
-	/* Set protocol specific processing mode for Ethernet.
-	 * This has to be adjusted for Full Duplex operation after we can
-	 * determine how to detect that.
-	 */
-	fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
-
-	/* And last, enable the transmit and receive processing.
-	*/
-	fccp->fcc_gfmr |= (FCC_GFMR_ENR | FCC_GFMR_ENT);
-}
-
-/* MII command/status interface.
- * I'm not going to describe all of the details.  You can find the
- * protocol definition in many other places, including the data sheet
- * of most PHY parts.
- * I wonder what "they" were thinking (maybe weren't) when they leave
- * the I2C in the CPM but I have to toggle these bits......
- */
-static uint
-mii_send_receive(fcc_info_t *fip, uint cmd)
-{
-	unsigned long	flags;
-	uint		retval;
-	int		read_op, i;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	immap = (immap_t *)IMAP_ADDR;
-	io = &immap->im_ioport;
-
-	/* When we get here, both clock and data are high, outputs.
-	 * Output is open drain.
-	 * Data transitions on high->low clock, is valid on low->high clock.
-	 * Spec says edge transitions no closer than 160 nSec, minimum clock
-	 * cycle 400 nSec.  I could only manage about 500 nSec edges with
-	 * an XOR loop, so I won't worry about delays yet.
-	 * I disable interrupts during bit flipping to ensure atomic
-	 * updates of the registers.  I do lots of interrupt disable/enable
-	 * to ensure we don't hang out too long with interrupts disabled.
-	 */
-
-	/* First, crank out 32 1-bits as preamble.
-	 * This is 64 transitions to clock the bits, with clock/data
-	 * left high.
-	 */
-	save_flags(flags);
-	cli();
-	for (i=0; i<64; i++) {
-		io->iop_pdatc ^= fip->fc_mdck;
-		udelay(0);
-	}
-	restore_flags(flags);
-
-	read_op = ((cmd & 0xf0000000) == 0x60000000);
-
-	/* We return the command word on a write op, or the command portion
-	 * plus the new data on a read op.  This is what the 8xx FEC does,
-	 * and it allows the functions to simply look at the returned value
-	 * and know the PHY/register as well.
-	 */
-	if (read_op)
-		retval = cmd;
-	else
-		retval = (cmd >> 16);
-
-	/* Clock out the first 16 MS bits of the command.
-	*/
-	save_flags(flags);
-	cli();
-	for (i=0; i<16; i++) {
-		io->iop_pdatc &= ~(fip->fc_mdck);
-		if (cmd & 0x80000000)
-			io->iop_pdatc |= fip->fc_mdio;
-		else
-			io->iop_pdatc &= ~(fip->fc_mdio);
-		cmd <<= 1;
-		io->iop_pdatc |= fip->fc_mdck;
-		udelay(0);
-	}
-
-	/* Do the turn-around.  If read op, we make the IO and input.
-	 * If write op, do the 1/0 thing.
-	 */
-	io->iop_pdatc &= ~(fip->fc_mdck);
-	if (read_op)
-		io->iop_pdirc &= ~(fip->fc_mdio);
-	else
-		io->iop_pdatc |= fip->fc_mdio;
-	io->iop_pdatc |= fip->fc_mdck;
-
-	/* I do this mainly to get just a little delay.
-	*/
-	restore_flags(flags);
-	save_flags(flags);
-	cli();
-	io->iop_pdatc &= ~(fip->fc_mdck);
-	io->iop_pdirc &= ~(fip->fc_mdio);
-	io->iop_pdatc |= fip->fc_mdck;
-
-	restore_flags(flags);
-	save_flags(flags);
-	cli();
-
-	/* For read, clock in 16 bits.  For write, clock out
-	 * rest of command.
-	 */
-	if (read_op) {
-		io->iop_pdatc &= ~(fip->fc_mdck);
-		udelay(0);
-		for (i=0; i<16; i++) {
-			io->iop_pdatc |= fip->fc_mdck;
-			udelay(0);
-			retval <<= 1;
-			if (io->iop_pdatc & fip->fc_mdio)
-				retval |= 1;
-			io->iop_pdatc &= ~(fip->fc_mdck);
-			udelay(0);
-		}
-	}
-	else {
-		for (i=0; i<16; i++) {
-			io->iop_pdatc &= ~(fip->fc_mdck);
-			if (cmd & 0x80000000)
-				io->iop_pdatc |= fip->fc_mdio;
-			else
-				io->iop_pdatc &= ~(fip->fc_mdio);
-			cmd <<= 1;
-			io->iop_pdatc |= fip->fc_mdck;
-			udelay(0);
-		}
-		io->iop_pdatc &= ~(fip->fc_mdck);
-	}
-	restore_flags(flags);
-
-	/* Some diagrams show two 1 bits for "idle".  I don't know if
-	 * this is really necessary or if it was just to indicate nothing
-	 * is going to happen for a while.
-	 * Make the data pin an output, set the data high, and clock it.
-	 */
-	save_flags(flags);
-	cli();
-	io->iop_pdatc |= fip->fc_mdio;
-	io->iop_pdirc |= fip->fc_mdio;
-	for (i=0; i<3; i++)
-		io->iop_pdatc ^= fip->fc_mdck;
-	restore_flags(flags);
-
-	/* We exit with the same conditions as entry.
-	*/
-	return(retval);
-}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/8260_io/uart.c linux-2.4.26-pre6/arch/ppc/8260_io/uart.c
--- linux-2.4.25/arch/ppc/8260_io/uart.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/8260_io/uart.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,2787 +0,0 @@
-/*
- *  UART driver for MPC8260 CPM SCC or SMC
- *  Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- *  Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
- *	2.3.99 updates
- *
- * I used the 8xx uart.c driver as the framework for this driver.
- * The original code was written for the EST8260 board.  I tried to make
- * it generic, but there may be some assumptions in the structures that
- * have to be fixed later.
- *
- * The 8xx and 8260 are similar, but not identical.  Over time we
- * could probably merge these two drivers.
- * To save porting time, I did not bother to change any object names
- * that are not accessed outside of this file.
- * It still needs lots of work........When it was easy, I included code
- * to support the SCCs.
- * Only the SCCs support modem control, so that is not complete either.
- *
- * This module exports the following rs232 io functions:
- *
- *	int rs_8xx_init(void);
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <asm/immap_8260.h>
-#include <asm/mpc8260.h>
-#include <asm/cpm_8260.h>
-#include <asm/irq.h>
-
-#ifdef CONFIG_MAGIC_SYSRQ
-#include <linux/sysrq.h>
-#endif
-
-#ifdef CONFIG_SERIAL_CONSOLE
-#include <linux/console.h>
-
-/* this defines the index into rs_table for the port to use
-*/
-#ifndef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT	0
-#endif
-#endif
-
-#define TX_WAKEUP	ASYNC_SHARE_IRQ
-
-static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.01";
-
-static DECLARE_TASK_QUEUE(tq_serial);
-
-static struct tty_driver serial_driver, callout_driver;
-static int serial_refcount;
-static int serial_console_setup(struct console *co, char *options);
-
-static void serial_console_write(struct console *c, const char *s,
-		                                unsigned count);
-static kdev_t serial_console_device(struct console *c);
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-static unsigned long break_pressed; /* break, really ... */
-#endif
-
-/*
- * Serial driver configuration section.  Here are the various options:
- */
-#define SERIAL_PARANOIA_CHECK
-#define CONFIG_SERIAL_NOPAUSE_IO
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
-#define _INLINE_ inline
-
-#define DBG_CNT(s)
-
-/* We overload some of the items in the data structure to meet our
- * needs.  For example, the port address is the CPM parameter ram
- * offset for the SCC or SMC.  The maximum number of ports is 4 SCCs and
- * 2 SMCs.  The "hub6" field is used to indicate the channel number, with
- * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs.
- * Since these ports are so versatile, I don't yet have a strategy for
- * their management.  For example, SCC1 is used for Ethernet.  Right
- * now, just don't put them in the table.  Of course, right now I just
- * want the SMC to work as a uart :-)..
- * The "type" field is currently set to 0, for PORT_UNKNOWN.  It is
- * not currently used.  I should probably use it to indicate the port
- * type of CMS or SCC.
- * The SMCs do not support any modem control signals.
- */
-#define smc_scc_num	hub6
-
-/* SMC2 is sometimes used for low performance TDM interfaces.  Define
- * this as 1 if you want SMC2 as a serial port UART managed by this driver.
- * Define this as 0 if you wish to use SMC2 for something else.
- */
-#define USE_SMC2 1
-
-/* Define SCC to ttySx mapping.
-*/
-#define SCC_NUM_BASE	(USE_SMC2 + 1)	/* SCC base tty "number" */
-
-/* Define which SCC is the first one to use for a serial port.  These
- * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
- * for Ethernet, and the first available SCC for serial UART is SCC2.
- * NOTE:  IF YOU CHANGE THIS, you have to change the PROFF_xxx and
- * interrupt vectors in the table below to match.
- */
-#define SCC_IDX_BASE	1	/* table index */
-
-static struct serial_state rs_table[] = {
-	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
-	{ 0,     0, PROFF_SMC1, SIU_INT_SMC1,   0,    0 },    /* SMC1 ttyS0 */
-#if USE_SMC2
-	{ 0,     0, PROFF_SMC2, SIU_INT_SMC2,   0,    1 },    /* SMC2 ttyS1 */
-#endif
-	{ 0,     0, PROFF_SCC2, SIU_INT_SCC2,   0, SCC_NUM_BASE},    /* SCC2 ttyS2 */
-	{ 0,     0, PROFF_SCC3, SIU_INT_SCC3,   0, SCC_NUM_BASE + 1},    /* SCC3 ttyS3 */
-};
-
-#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
-
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
-/* The number of buffer descriptors and their sizes.
-*/
-#define RX_NUM_FIFO	4
-#define RX_BUF_SIZE	32
-#define TX_NUM_FIFO	4
-#define TX_BUF_SIZE	32
-
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
-/* The async_struct in serial.h does not really give us what we
- * need, so define our own here.
- */
-typedef struct serial_info {
-	int			magic;
-	int			flags;
-	struct serial_state	*state;
-	struct tty_struct 	*tty;
-	int			read_status_mask;
-	int			ignore_status_mask;
-	int			timeout;
-	int			line;
-	int			x_char;	/* xon/xoff character */
-	int			close_delay;
-	unsigned short		closing_wait;
-	unsigned short		closing_wait2;
-	unsigned long		event;
-	unsigned long		last_active;
-	int			blocked_open; /* # of blocked opens */
-	long			session; /* Session of opening process */
-	long			pgrp; /* pgrp of opening process */
-	struct tq_struct	tqueue;
-	struct tq_struct	tqueue_hangup;
-	wait_queue_head_t	open_wait;
-	wait_queue_head_t	close_wait;
-
-	/* CPM Buffer Descriptor pointers.
-	*/
-	cbd_t			*rx_bd_base;
-	cbd_t			*rx_cur;
-	cbd_t			*tx_bd_base;
-	cbd_t			*tx_cur;
-} ser_info_t;
-
-static struct console sercons = {
-        name:           "ttyS",
-        write:          serial_console_write,
-        device:         serial_console_device,
-        setup:          serial_console_setup,
-        flags:          CON_PRINTBUFFER,
-        index:          CONFIG_SERIAL_CONSOLE_PORT,
-};
-
-
-static void change_speed(ser_info_t *info);
-static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
-
-static inline int serial_paranoia_check(ser_info_t *info,
-					kdev_t device, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for serial struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null async_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, kdevname(device), routine);
-		return 1;
-	}
-	if (info->magic != SERIAL_MAGIC) {
-		printk(badmagic, kdevname(device), routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/*
- * This is used to figure out the divisor speeds and the timeouts,
- * indexed by the termio value.  The generic CPM functions are responsible
- * for setting and assigning baud rate generators for us.
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
-
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_8xx_stop(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int	idx;
-	unsigned long flags;
-	volatile scc_t	*sccp;
-	volatile smc_t	*smcp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_stop"))
-		return;
-
-	save_flags(flags); cli();
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-		smcp->smc_smcm &= ~SMCM_TX;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_sccm &= ~UART_SCCM_TX;
-	}
-	restore_flags(flags);
-}
-
-static void rs_8xx_start(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int	idx;
-	unsigned long flags;
-	volatile scc_t	*sccp;
-	volatile smc_t	*smcp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_stop"))
-		return;
-
-	save_flags(flags); cli();
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-		smcp->smc_smcm |= SMCM_TX;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_sccm |= UART_SCCM_TX;
-	}
-	restore_flags(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt().  They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off.  People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible.  After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static _INLINE_ void rs_sched_event(ser_info_t *info,
-				  int event)
-{
-	info->event |= 1 << event;
-	queue_task(&info->tqueue, &tq_serial);
-	mark_bh(SERIAL_BH);
-}
-
-static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
-{
-	struct tty_struct *tty = info->tty;
-	unsigned char ch, *cp;
-	/*int	ignored = 0;*/
-	int	i;
-	ushort	status;
-	struct	async_icount *icount;
-	volatile cbd_t	*bdp;
-
-	icount = &info->state->icount;
-
-	/* Just loop through the closed BDs and copy the characters into
-	 * the buffer.
-	 */
-	bdp = info->rx_cur;
-	for (;;) {
-		if (bdp->cbd_sc & BD_SC_EMPTY)	/* If this one is empty */
-			break;			/*   we are all done */
-
-		/* The read status mask tell us what we should do with
-		 * incoming characters, especially if errors occur.
-		 * One special case is the use of BD_SC_EMPTY.  If
-		 * this is not set, we are supposed to be ignoring
-		 * inputs.  In this case, just mark the buffer empty and
-		 * continue.
-		if (!(info->read_status_mask & BD_SC_EMPTY)) {
-			bdp->cbd_sc |= BD_SC_EMPTY;
-			bdp->cbd_sc &=
-				~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
-			if (bdp->cbd_sc & BD_SC_WRAP)
-				bdp = info->rx_bd_base;
-			else
-				bdp++;
-			continue;
-		}
-		 */
-
-		/* Get the number of characters and the buffer pointer.
-		*/
-		i = bdp->cbd_datlen;
-		cp = (unsigned char *)__va(bdp->cbd_bufaddr);
-		status = bdp->cbd_sc;
-
-		/* Check to see if there is room in the tty buffer for
-		 * the characters in our BD buffer.  If not, we exit
-		 * now, leaving the BD with the characters.  We'll pick
-		 * them up again on the next receive interrupt (which could
-		 * be a timeout).
-		 */
-		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
-			break;
-
-		while (i-- > 0) {
-			ch = *cp++;
-			*tty->flip.char_buf_ptr = ch;
-			icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
-			printk("DR%02x:%02x...", ch, *status);
-#endif
-			*tty->flip.flag_buf_ptr = 0;
-			if (status & (BD_SC_BR | BD_SC_FR |
-				       BD_SC_PR | BD_SC_OV)) {
-				/*
-				 * For statistics only
-				 */
-				if (status & BD_SC_BR)
-					icount->brk++;
-				else if (status & BD_SC_PR)
-					icount->parity++;
-				else if (status & BD_SC_FR)
-					icount->frame++;
-				if (status & BD_SC_OV)
-					icount->overrun++;
-
-				/*
-				 * Now check to see if character should be
-				 * ignored, and mask off conditions which
-				 * should be ignored.
-				if (status & info->ignore_status_mask) {
-					if (++ignored > 100)
-						break;
-					continue;
-				}
-				 */
-				status &= info->read_status_mask;
-
-				if (status & (BD_SC_BR)) {
-#ifdef SERIAL_DEBUG_INTR
-					printk("handling break....");
-#endif
-					*tty->flip.flag_buf_ptr = TTY_BREAK;
-					if (info->flags & ASYNC_SAK)
-						do_SAK(tty);
-				} else if (status & BD_SC_PR)
-					*tty->flip.flag_buf_ptr = TTY_PARITY;
-				else if (status & BD_SC_FR)
-					*tty->flip.flag_buf_ptr = TTY_FRAME;
-				if (status & BD_SC_OV) {
-					/*
-					 * Overrun is special, since it's
-					 * reported immediately, and doesn't
-					 * affect the current character
-					 */
-					if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-						tty->flip.count++;
-						tty->flip.flag_buf_ptr++;
-						tty->flip.char_buf_ptr++;
-						*tty->flip.flag_buf_ptr =
-								TTY_OVERRUN;
-					}
-				}
-			}
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-			if (break_pressed && info->line == sercons.index) {
-				if (ch != 0 && time_before(jiffies,
-							break_pressed + HZ*5)) {
-					handle_sysrq(ch, regs, NULL, NULL);
-					break_pressed = 0;
-					goto ignore_char;
-				} else
-					break_pressed = 0;
-			}
-#endif
-			
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				break;
-
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-	ignore_char:
-#endif
-
-		/* This BD is ready to be used again.  Clear status.
-		 * Get next BD.
-		 */
-		bdp->cbd_sc |= BD_SC_EMPTY;
-		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = info->rx_bd_base;
-		else
-			bdp++;
-	}
-
-	info->rx_cur = (cbd_t *)bdp;
-
-	queue_task(&tty->flip.tqueue, &tq_timer);
-}
-
-static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
-{
-	struct tty_struct *tty = info->tty;
-
-	info->state->icount.brk++;
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-	if (info->line == sercons.index) {
-		if (!break_pressed) {
-			break_pressed = jiffies;
-			return;
-		} else
-			break_pressed = 0;
-	}
-#endif
-
-	/* Check to see if there is room in the tty buffer for
-	 * the break.  If not, we exit now, losing the break.  FIXME
-	 */
-	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
-		return;
-	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
-	*(tty->flip.char_buf_ptr++) = 0;
-	tty->flip.count++;
-
-	queue_task(&tty->flip.tqueue, &tq_timer);
-}
-
-
-static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
-{
-
-	if (info->flags & TX_WAKEUP) {
-		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-	}
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("THRE...");
-#endif
-}
-
-#ifdef notdef
-	/* I need to do this for the SCCs, so it is left as a reminder.
-	*/
-static _INLINE_ void check_modem_status(struct async_struct *info)
-{
-	int	status;
-	struct	async_icount *icount;
-
-	status = serial_in(info, UART_MSR);
-
-	if (status & UART_MSR_ANY_DELTA) {
-		icount = &info->state->icount;
-		/* update input line counters */
-		if (status & UART_MSR_TERI)
-			icount->rng++;
-		if (status & UART_MSR_DDSR)
-			icount->dsr++;
-		if (status & UART_MSR_DDCD) {
-			icount->dcd++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    (status & UART_MSR_DCD))
-				hardpps();
-#endif
-		}
-		if (status & UART_MSR_DCTS)
-			icount->cts++;
-		wake_up_interruptible(&info->delta_msr_wait);
-	}
-
-	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttys%d CD now %s...", info->line,
-		       (status & UART_MSR_DCD) ? "on" : "off");
-#endif
-		if (status & UART_MSR_DCD)
-			wake_up_interruptible(&info->open_wait);
-		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
-#ifdef SERIAL_DEBUG_OPEN
-			printk("scheduling hangup...");
-#endif
-			MOD_INC_USE_COUNT;
-			if (schedule_task(&info->tqueue_hangup) == 0)
-				MOD_DEC_USE_COUNT;
-		}
-	}
-	if (info->flags & ASYNC_CTS_FLOW) {
-		if (info->tty->hw_stopped) {
-			if (status & UART_MSR_CTS) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx start...");
-#endif
-				info->tty->hw_stopped = 0;
-				info->IER |= UART_IER_THRI;
-				serial_out(info, UART_IER, info->IER);
-				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-				return;
-			}
-		} else {
-			if (!(status & UART_MSR_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx stop...");
-#endif
-				info->tty->hw_stopped = 1;
-				info->IER &= ~UART_IER_THRI;
-				serial_out(info, UART_IER, info->IER);
-			}
-		}
-	}
-}
-#endif
-
-/*
- * This is the serial driver's interrupt routine for a single port
- */
-static void rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
-	u_char	events;
-	int	idx;
-	ser_info_t *info;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	info = (ser_info_t *)dev_id;
-
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-		events = smcp->smc_smce;
-		if (events & SMCM_BRKE)
-			receive_break(info, regs);
-		if (events & SMCM_RX)
-			receive_chars(info, regs);
-		if (events & SMCM_TX)
-			transmit_chars(info, regs);
-		smcp->smc_smce = events;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		events = sccp->scc_scce;
-		if (events & SMCM_BRKE)
-			receive_break(info, regs);
-		if (events & SCCM_RX)
-			receive_chars(info, regs);
-		if (events & SCCM_TX)
-			transmit_chars(info, regs);
-		sccp->scc_scce = events;
-	}
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("rs_interrupt_single(%d, %x)...",
-					info->state->smc_scc_num, events);
-#endif
-#ifdef modem_control
-	check_modem_status(info);
-#endif
-	info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
-	printk("end.\n");
-#endif
-}
-
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-static void do_serial_bh(void)
-{
-	run_task_queue(&tq_serial);
-}
-
-static void do_softint(void *private_)
-{
-	ser_info_t	*info = (ser_info_t *) private_;
-	struct tty_struct	*tty;
-
-	tty = info->tty;
-	if (!tty)
-		return;
-
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
-}
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred.  The path of
- * hangup processing is:
- *
- * 	serial interrupt routine -> (scheduler tqueue) ->
- * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
- *
- */
-static void do_serial_hangup(void *private_)
-{
-	struct async_struct	*info = (struct async_struct *) private_;
-	struct tty_struct	*tty;
-
-	tty = info->tty;
-	if (tty)
-		tty_hangup(tty);
-	MOD_DEC_USE_COUNT;
-}
-
-/*static void rs_8xx_timer(void)
-{
-	printk("rs_8xx_timer\n");
-}*/
-
-
-static int startup(ser_info_t *info)
-{
-	unsigned long flags;
-	int	retval=0;
-	int	idx;
-	struct serial_state *state= info->state;
-	volatile smc_t		*smcp;
-	volatile scc_t		*sccp;
-	volatile smc_uart_t	*up;
-	volatile scc_uart_t	*scup;
-
-
-	save_flags(flags); cli();
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		goto errout;
-	}
-
-#ifdef maybe
-	if (!state->port || !state->type) {
-		if (info->tty)
-			set_bit(TTY_IO_ERROR, &info->tty->flags);
-		goto errout;
-	}
-#endif
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttys%d (irq %d)...", info->line, state->irq);
-#endif
-
-
-#ifdef modem_control
-	info->MCR = 0;
-	if (info->tty->termios->c_cflag & CBAUD)
-		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
-#endif
-
-	if (info->tty)
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	/*
-	 * and set the speed of the serial port
-	 */
-	change_speed(info);
-
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-
-		/* Enable interrupts and I/O.
-		*/
-		smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
-		smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
-
-		/* We can tune the buffer length and idle characters
-		 * to take advantage of the entire incoming buffer size.
-		 * If mrblr is something other than 1, maxidl has to be
-		 * non-zero or we never get an interrupt.  The maxidl
-		 * is the number of character times we wait after reception
-		 * of the last character before we decide no more characters
-		 * are coming.
-		 */
-		up = (smc_uart_t *)&immr->im_dprambase[state->port];
-#if 0
-		up->smc_mrblr = 1;	/* receive buffer length */
-		up->smc_maxidl = 0;	/* wait forever for next char */
-#else
-		up->smc_mrblr = RX_BUF_SIZE;
-		up->smc_maxidl = RX_BUF_SIZE;
-#endif
-		up->smc_brkcr = 1;	/* number of break chars */
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		scup = (scc_uart_t *)&immr->im_dprambase[state->port];
-#if 0
-		scup->scc_genscc.scc_mrblr = 1;	/* receive buffer length */
-		scup->scc_maxidl = 0;	/* wait forever for next char */
-#else
-		scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
-		scup->scc_maxidl = RX_BUF_SIZE;
-#endif
-
-		sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
-		sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	}
-
-	info->flags |= ASYNC_INITIALIZED;
-	restore_flags(flags);
-	return 0;
-
-errout:
-	restore_flags(flags);
-	return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(ser_info_t * info)
-{
-	unsigned long	flags;
-	struct serial_state *state;
-	int		idx;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	if (!(info->flags & ASYNC_INITIALIZED))
-		return;
-
-	state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d (irq %d)....", info->line,
-	       state->irq);
-#endif
-
-	save_flags(flags); cli(); /* Disable interrupts */
-
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-
-		/* Disable interrupts and I/O.
-		*/
-		smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-#ifdef CONFIG_SERIAL_CONSOLE
-		/* We can't disable the transmitter if this is the
-		 * system console.
-		 */
-		if (idx != CONFIG_SERIAL_CONSOLE_PORT)
-#endif
-			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
-		sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	}
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	info->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(ser_info_t *info)
-{
-	int	baud_rate;
-	unsigned cflag, cval, scval, prev_mode;
-	int	i, bits, sbits, idx;
-	unsigned long	flags;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	if (!info->tty || !info->tty->termios)
-		return;
-	cflag = info->tty->termios->c_cflag;
-
-	/* Character length programmed into the mode register is the
-	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
-	 * 1 or 2 stop bits, minus 1.
-	 * The value 'bits' counts this for us.
-	 */
-	cval = 0;
-	scval = 0;
-
-	/* byte size and parity */
-	switch (cflag & CSIZE) {
-	      case CS5: bits = 5; break;
-	      case CS6: bits = 6; break;
-	      case CS7: bits = 7; break;
-	      case CS8: bits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  bits = 8; break;
-	}
-	sbits = bits - 5;
-
-	if (cflag & CSTOPB) {
-		cval |= SMCMR_SL;	/* Two stops */
-		scval |= SCU_PMSR_SL;
-		bits++;
-	}
-	if (cflag & PARENB) {
-		cval |= SMCMR_PEN;
-		scval |= SCU_PMSR_PEN;
-		bits++;
-	}
-	if (!(cflag & PARODD)) {
-		cval |= SMCMR_PM_EVEN;
-		scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
-	}
-
-	/* Determine divisor based on baud rate */
-	i = cflag & CBAUD;
-	if (i >= (sizeof(baud_table)/sizeof(int)))
-		baud_rate = 9600;
-	else
-		baud_rate = baud_table[i];
-
-	info->timeout = (TX_BUF_SIZE*HZ*bits);
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-#ifdef modem_control
-	/* CTS flow control flag and modem status interrupts */
-	info->IER &= ~UART_IER_MSI;
-	if (info->flags & ASYNC_HARDPPS_CD)
-		info->IER |= UART_IER_MSI;
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->IER |= UART_IER_MSI;
-	} else
-		info->flags &= ~ASYNC_CTS_FLOW;
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else {
-		info->flags |= ASYNC_CHECK_CD;
-		info->IER |= UART_IER_MSI;
-	}
-	serial_out(info, UART_IER, info->IER);
-#endif
-
-	/*
-	 * Set up parity check flag
-	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-	info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
-	if (I_INPCK(info->tty))
-		info->read_status_mask |= BD_SC_FR | BD_SC_PR;
-	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
-		info->read_status_mask |= BD_SC_BR;
-
-	/*
-	 * Characters to ignore
-	 */
-	info->ignore_status_mask = 0;
-	if (I_IGNPAR(info->tty))
-		info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
-	if (I_IGNBRK(info->tty)) {
-		info->ignore_status_mask |= BD_SC_BR;
-		/*
-		 * If we're ignore parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->tty))
-			info->ignore_status_mask |= BD_SC_OV;
-	}
-	/*
-	 * !!! ignore all characters if CREAD is not set
-	 */
-	if ((cflag & CREAD) == 0)
-		info->read_status_mask &= ~BD_SC_EMPTY;
-	save_flags(flags); cli();
-
-	/* Start bit has not been added (so don't, because we would just
-	 * subtract it later), and we need to add one for the number of
-	 * stops bits (there is always at least one).
-	 */
-	bits++;
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-
-		/* Set the mode register.  We want to keep a copy of the
-		 * enables, because we want to put them back if they were
-		 * present.
-		 */
-		prev_mode = smcp->smc_smcmr & (SMCMR_REN | SMCMR_TEN);
-		smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART
-			| prev_mode;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_pmsr = (sbits << 12) | scval;
-	}
-
-	m8260_cpm_setbrg(info->state->smc_scc_num, baud_rate);
-
-	restore_flags(flags);
-}
-
-static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	volatile cbd_t	*bdp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
-		return;
-
-	if (!tty)
-		return;
-
-	bdp = info->tx_cur;
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	*((char *)__va(bdp->cbd_bufaddr)) = ch;
-	bdp->cbd_datlen = 1;
-	bdp->cbd_sc |= BD_SC_READY;
-
-	/* Get next BD.
-	*/
-	if (bdp->cbd_sc & BD_SC_WRAP)
-		bdp = info->tx_bd_base;
-	else
-		bdp++;
-
-	info->tx_cur = (cbd_t *)bdp;
-
-}
-
-static int rs_8xx_write(struct tty_struct * tty, int from_user,
-		    const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	volatile cbd_t *bdp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_write"))
-		return 0;
-
-	if (!tty)
-		return 0;
-
-	bdp = info->tx_cur;
-
-	while (1) {
-		c = MIN(count, TX_BUF_SIZE);
-
-		if (c <= 0)
-			break;
-
-		if (bdp->cbd_sc & BD_SC_READY) {
-			info->flags |= TX_WAKEUP;
-			break;
-		}
-
-		if (from_user) {
-			if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
-				if (!ret)
-					ret = -EFAULT;
-				break;
-			}
-		} else {
-			memcpy(__va(bdp->cbd_bufaddr), buf, c);
-		}
-
-		bdp->cbd_datlen = c;
-		bdp->cbd_sc |= BD_SC_READY;
-
-		buf += c;
-		count -= c;
-		ret += c;
-
-		/* Get next BD.
-		*/
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = info->tx_bd_base;
-		else
-			bdp++;
-		info->tx_cur = (cbd_t *)bdp;
-	}
-	return ret;
-}
-
-static int rs_8xx_write_room(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int	ret;
-
-	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
-		return 0;
-
-	if ((info->tx_cur->cbd_sc & BD_SC_READY) == 0) {
-		info->flags &= ~TX_WAKEUP;
-		ret = TX_BUF_SIZE;
-	}
-	else {
-		info->flags |= TX_WAKEUP;
-		ret = 0;
-	}
-	return ret;
-}
-
-/* I could track this with transmit counters....maybe later.
-*/
-static int rs_8xx_chars_in_buffer(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
-		return 0;
-	return 0;
-}
-
-static void rs_8xx_flush_buffer(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
-		return;
-
-	/* There is nothing to "flush", whatever we gave the CPM
-	 * is on its way out.
-	 */
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-	info->flags &= ~TX_WAKEUP;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
-{
-	volatile cbd_t	*bdp;
-
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
-		return;
-
-	bdp = info->tx_cur;
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	*((char *)__va(bdp->cbd_bufaddr)) = ch;
-	bdp->cbd_datlen = 1;
-	bdp->cbd_sc |= BD_SC_READY;
-
-	/* Get next BD.
-	*/
-	if (bdp->cbd_sc & BD_SC_WRAP)
-		bdp = info->tx_bd_base;
-	else
-		bdp++;
-
-	info->tx_cur = (cbd_t *)bdp;
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_8xx_throttle(struct tty_struct * tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %d....\n", _tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
-		return;
-
-	if (I_IXOFF(tty))
-		rs_8xx_send_xchar(tty, STOP_CHAR(tty));
-
-#ifdef modem_control
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR &= ~UART_MCR_RTS;
-
-	cli();
-	serial_out(info, UART_MCR, info->MCR);
-	sti();
-#endif
-}
-
-static void rs_8xx_unthrottle(struct tty_struct * tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			rs_8xx_send_xchar(tty, START_CHAR(tty));
-	}
-#ifdef modem_control
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR |= UART_MCR_RTS;
-	cli();
-	serial_out(info, UART_MCR, info->MCR);
-	sti();
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-#ifdef maybe
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * 	    is emptied.  On bus types like RS485, the transmitter must
- * 	    release the bus after transmitting. This must be done when
- * 	    the transmit shift register is empty, not be done when the
- * 	    transmit holding register is empty.  This functionality
- * 	    allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
-{
-	unsigned char status;
-	unsigned int result;
-
-	cli();
-	status = serial_in(info, UART_LSR);
-	sti();
-	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	return put_user(result,value);
-}
-#endif
-
-static int get_modem_info(ser_info_t *info, unsigned int *value)
-{
-	unsigned int result = 0;
-#ifdef modem_control
-	unsigned char control, status;
-
-	control = info->MCR;
-	cli();
-	status = serial_in(info, UART_MSR);
-	sti();
-	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
-		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-#ifdef TIOCM_OUT1
-		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
-		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
-#endif
-		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
-		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
-		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
-		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
-#endif
-	return put_user(result,value);
-}
-
-static int set_modem_info(ser_info_t *info, unsigned int cmd,
-			  unsigned int *value)
-{
-	int error;
-	unsigned int arg;
-
-	error = get_user(arg, value);
-	if (error)
-		return error;
-#ifdef modem_control
-	switch (cmd) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS)
-			info->MCR |= UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR |= UART_MCR_DTR;
-#ifdef TIOCM_OUT1
-		if (arg & TIOCM_OUT1)
-			info->MCR |= UART_MCR_OUT1;
-		if (arg & TIOCM_OUT2)
-			info->MCR |= UART_MCR_OUT2;
-#endif
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			info->MCR &= ~UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR &= ~UART_MCR_DTR;
-#ifdef TIOCM_OUT1
-		if (arg & TIOCM_OUT1)
-			info->MCR &= ~UART_MCR_OUT1;
-		if (arg & TIOCM_OUT2)
-			info->MCR &= ~UART_MCR_OUT2;
-#endif
-		break;
-	case TIOCMSET:
-		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
-#ifdef TIOCM_OUT1
-					    UART_MCR_OUT1 |
-					    UART_MCR_OUT2 |
-#endif
-					    UART_MCR_DTR))
-			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
-#ifdef TIOCM_OUT1
-			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
-			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
-#endif
-			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-		break;
-	default:
-		return -EINVAL;
-	}
-	cli();
-	serial_out(info, UART_MCR, info->MCR);
-	sti();
-#endif
-	return 0;
-}
-
-/* Sending a break is a two step process on the SMC/SCC.  It is accomplished
- * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
- * command.  We take advantage of the begin/end functions to make this
- * happen.
- */
-static void begin_break(ser_info_t *info)
-{
-	volatile cpm8260_t *cp;
-	uint	page, sblock;
-	ushort	num;
-
-	cp = cpmp;
-
-	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		if (num == 0) {
-			page = CPM_CR_SMC1_PAGE;
-			sblock = CPM_CR_SMC1_SBLOCK;
-		}
-		else {
-			page = CPM_CR_SMC2_PAGE;
-			sblock = CPM_CR_SMC2_SBLOCK;
-		}
-	}
-	else {
-		num -= SCC_NUM_BASE;
-		switch (num) {
-		case 0:
-			page = CPM_CR_SCC1_PAGE;
-			sblock = CPM_CR_SCC1_SBLOCK;
-			break;
-		case 1:
-			page = CPM_CR_SCC2_PAGE;
-			sblock = CPM_CR_SCC2_SBLOCK;
-			break;
-		case 2:
-			page = CPM_CR_SCC3_PAGE;
-			sblock = CPM_CR_SCC3_SBLOCK;
-			break;
-		case 3:
-			page = CPM_CR_SCC4_PAGE;
-			sblock = CPM_CR_SCC4_SBLOCK;
-			break;
-		default: return;
-		}
-	}
-	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_STOP_TX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-}
-
-static void end_break(ser_info_t *info)
-{
-	volatile cpm8260_t *cp;
-	uint	page, sblock;
-	ushort	num;
-
-	cp = cpmp;
-
-	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		if (num == 0) {
-			page = CPM_CR_SMC1_PAGE;
-			sblock = CPM_CR_SMC1_SBLOCK;
-		}
-		else {
-			page = CPM_CR_SMC2_PAGE;
-			sblock = CPM_CR_SMC2_SBLOCK;
-		}
-	}
-	else {
-		num -= SCC_NUM_BASE;
-		switch (num) {
-		case 0:
-			page = CPM_CR_SCC1_PAGE;
-			sblock = CPM_CR_SCC1_SBLOCK;
-			break;
-		case 1:
-			page = CPM_CR_SCC2_PAGE;
-			sblock = CPM_CR_SCC2_SBLOCK;
-			break;
-		case 2:
-			page = CPM_CR_SCC3_PAGE;
-			sblock = CPM_CR_SCC3_SBLOCK;
-			break;
-		case 3:
-			page = CPM_CR_SCC4_PAGE;
-			sblock = CPM_CR_SCC4_SBLOCK;
-			break;
-		default: return;
-		}
-	}
-	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_RESTART_TX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break(ser_info_t *info, int duration)
-{
-	current->state = TASK_INTERRUPTIBLE;
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
-#endif
-	begin_break(info);
-	schedule_timeout(duration);
-	end_break(info);
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("done jiffies=%lu\n", jiffies);
-#endif
-}
-
-
-static int rs_8xx_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	int error;
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int retval;
-	struct async_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct *p_cuser;	/* user space */
-
-	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-		case TCSBRK:	/* SVID version: non-zero arg --> no break */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			if (!arg) {
-				send_break(info, HZ/4);	/* 1/4 second */
-				if (signal_pending(current))
-					return -EINTR;
-			}
-			return 0;
-		case TCSBRKP:	/* support for POSIX tcsendbreak() */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
-			if (signal_pending(current))
-				return -EINTR;
-			return 0;
-		case TIOCSBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			begin_break(info);
-			return 0;
-		case TIOCCBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			end_break(info);
-			return 0;
-		case TIOCGSOFTCAR:
-			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
-		case TIOCSSOFTCAR:
-			error = get_user(arg, (unsigned int *) arg);
-			if (error)
-				return error;
-			tty->termios->c_cflag =
-				((tty->termios->c_cflag & ~CLOCAL) |
-				 (arg ? CLOCAL : 0));
-			return 0;
-		case TIOCMGET:
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
-#ifdef maybe
-		case TIOCSERGETLSR: /* Get line status register */
-			return get_lsr_info(info, (unsigned int *) arg);
-#endif
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
- 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-		 case TIOCMIWAIT:
-#ifdef modem_control
-			cli();
-			/* note the counters on entry */
-			cprev = info->state->icount;
-			sti();
-			while (1) {
-				interruptible_sleep_on(&info->delta_msr_wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				cli();
-				cnow = info->state->icount; /* atomic copy */
-				sti();
-				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-					return -EIO; /* no change => error */
-				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-					return 0;
-				}
-				cprev = cnow;
-			}
-			/* NOTREACHED */
-#else
-			return 0;
-#endif
-
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-		case TIOCGICOUNT:
-			cli();
-			cnow = info->state->icount;
-			sti();
-			p_cuser = (struct serial_icounter_struct *) arg;
-			error = put_user(cnow.cts, &p_cuser->cts);
-			if (error) return error;
-			error = put_user(cnow.dsr, &p_cuser->dsr);
-			if (error) return error;
-			error = put_user(cnow.rng, &p_cuser->rng);
-			if (error) return error;
-			error = put_user(cnow.dcd, &p_cuser->dcd);
-			if (error) return error;
-			return 0;
-
-		default:
-			return -ENOIOCTLCMD;
-		}
-	return 0;
-}
-
-/* FIX UP modem control here someday......
-*/
-static void rs_8xx_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (   (tty->termios->c_cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag)
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
-	change_speed(info);
-
-#ifdef modem_control
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-		cli();
-		serial_out(info, UART_MCR, info->MCR);
-		sti();
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    (tty->termios->c_cflag & CBAUD)) {
-		info->MCR |= UART_MCR_DTR;
-		if (!tty->hw_stopped ||
-		    !(tty->termios->c_cflag & CRTSCTS)) {
-			info->MCR |= UART_MCR_RTS;
-		}
-		cli();
-		serial_out(info, UART_MCR, info->MCR);
-		sti();
-	}
-
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rs_8xx_start(tty);
-	}
-#endif
-
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	struct serial_state *state;
-	unsigned long	flags;
-	int		idx;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
-		return;
-
-	state = info->state;
-
-	save_flags(flags); cli();
-
-	if (tty_hung_up_p(filp)) {
-		DBG_CNT("before DEC-hung");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
-	if ((tty->count == 1) && (state->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  state->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("rs_close: bad serial port count; tty->count is 1, "
-		       "state->count is %d\n", state->count);
-		state->count = 1;
-	}
-	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for ttys%d: %d\n",
-		       info->line, state->count);
-		state->count = 0;
-	}
-	if (state->count) {
-		DBG_CNT("before DEC-2");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
-	}
-	info->flags |= ASYNC_CLOSING;
-	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	if (info->flags & ASYNC_CALLOUT_ACTIVE)
-		info->state->callout_termios = *tty->termios;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	info->read_status_mask &= ~BD_SC_EMPTY;
-	if (info->flags & ASYNC_INITIALIZED) {
-		if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-			smcp = &immr->im_smc[idx];
-			smcp->smc_smcm &= ~SMCM_RX;
-			smcp->smc_smcmr &= ~SMCMR_REN;
-		}
-		else {
-			sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-			sccp->scc_sccm &= ~UART_SCCM_RX;
-			sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
-		}
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		rs_8xx_wait_until_sent(tty, info->timeout);
-	}
-	shutdown(info);
-	if (tty->driver.flush_buffer)
-		tty->driver.flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-	tty->closing = 0;
-	info->event = 0;
-	info->tty = 0;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(info->close_delay);
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
-			 ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-	MOD_DEC_USE_COUNT;
-	restore_flags(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	/*int lsr;*/
-	volatile cbd_t *bdp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
-		return;
-
-#ifdef maybe
-	if (info->state->type == PORT_UNKNOWN)
-		return;
-#endif
-
-	orig_jiffies = jiffies;
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 *
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = 1;
-	if (timeout)
-		char_time = MIN(char_time, timeout);
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
-	printk("jiff=%lu...", jiffies);
-#endif
-
-	/* We go through the loop at least once because we can't tell
-	 * exactly when the last character exits the shifter.  There can
-	 * be at least two characters waiting to be sent after the buffers
-	 * are empty.
-	 */
-	do {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-		current->state = TASK_INTERRUPTIBLE;
-/*		current->counter = 0;	 make us low-priority */
-		schedule_timeout(char_time);
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-		bdp = info->tx_cur;
-	} while (bdp->cbd_sc & BD_SC_READY);
-	current->state = TASK_RUNNING;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_8xx_hangup(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	struct serial_state *state = info->state;
-
-	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
-		return;
-
-	state = info->state;
-
-	rs_8xx_flush_buffer(tty);
-	shutdown(info);
-	info->event = 0;
-	state->count = 0;
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
-	info->tty = 0;
-	wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-			   ser_info_t *info)
-{
-#ifdef DO_THIS_LATER
-	DECLARE_WAITQUEUE(wait, current);
-#endif
-	struct serial_state *state = info->state;
-	int		retval;
-	int		do_clocal = 0;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		if (info->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		if (info->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * If this is a callout device, then just make sure the normal
-	 * device isn't being used.
-	 */
-	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
-		if (info->flags & ASYNC_NORMAL_ACTIVE)
-			return -EBUSY;
-		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
-		    (info->session != current->session))
-		    return -EBUSY;
-		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
-		    (info->pgrp != current->pgrp))
-		    return -EBUSY;
-		info->flags |= ASYNC_CALLOUT_ACTIVE;
-		return 0;
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 * If this is an SMC port, we don't have modem control to wait
-	 * for, so just get out here.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR)) ||
-	    (info->state->smc_scc_num < SCC_NUM_BASE)) {
-		if (info->flags & ASYNC_CALLOUT_ACTIVE)
-			return -EBUSY;
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
-		if (state->normal_termios.c_cflag & CLOCAL)
-			do_clocal = 1;
-	} else {
-		if (tty->termios->c_cflag & CLOCAL)
-			do_clocal = 1;
-	}
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, state->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-#ifdef DO_THIS_LATER
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttys%d, count = %d\n",
-	       state->line, state->count);
-#endif
-	cli();
-	if (!tty_hung_up_p(filp))
-		state->count--;
-	sti();
-	info->blocked_open++;
-	while (1) {
-		cli();
-		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    (tty->termios->c_cflag & CBAUD))
-			serial_out(info, UART_MCR,
-				   serial_inp(info, UART_MCR) |
-				   (UART_MCR_DTR | UART_MCR_RTS));
-		sti();
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-			if (info->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    !(info->flags & ASYNC_CLOSING) &&
-		    (do_clocal || (serial_in(info, UART_MSR) &
-				   UART_MSR_DCD)))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttys%d, count = %d\n",
-		       info->line, state->count);
-#endif
-		schedule();
-	}
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&info->open_wait, &wait);
-	if (!tty_hung_up_p(filp))
-		state->count++;
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttys%d, count = %d\n",
-	       info->line, state->count);
-#endif
-#endif /* DO_THIS_LATER */
-	if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}
-
-static int get_async_struct(int line, ser_info_t **ret_info)
-{
-	struct serial_state *sstate;
-
-	sstate = rs_table + line;
-	if (sstate->info) {
-		sstate->count++;
-		*ret_info = (ser_info_t *)sstate->info;
-		return 0;
-	}
-	else {
-		return -ENOMEM;
-	}
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
-{
-	ser_info_t	*info;
-	int 		retval, line;
-
-	line = MINOR(tty->device) - tty->driver.minor_start;
-	if ((line < 0) || (line >= NR_PORTS))
-		return -ENODEV;
-	retval = get_async_struct(line, &info);
-	if (retval)
-		return retval;
-	if (serial_paranoia_check(info, tty->device, "rs_open"))
-		return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
-	       info->state->count);
-#endif
-	tty->driver_data = info;
-	info->tty = tty;
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval)
-		return retval;
-
-	MOD_INC_USE_COUNT;
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("rs_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-			*tty->termios = info->state->normal_termios;
-		else
-			*tty->termios = info->state->callout_termios;
-		change_speed(info);
-	}
-
-	info->session = current->session;
-	info->pgrp = current->pgrp;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open ttys%d successful...", info->line);
-#endif
-	return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static int inline line_info(char *buf, struct serial_state *state)
-{
-#ifdef notdef
-	struct async_struct *info = state->info, scr_info;
-	char	stat_buf[30], control, status;
-#endif
-	int	ret;
-
-	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
-		      state->line,
-		      (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
-		      state->port, state->irq);
-
-	if (!state->port || (state->type == PORT_UNKNOWN)) {
-		ret += sprintf(buf+ret, "\n");
-		return ret;
-	}
-
-#ifdef notdef
-	/*
-	 * Figure out the current RS-232 lines
-	 */
-	if (!info) {
-		info = &scr_info;	/* This is just for serial_{in,out} */
-
-		info->magic = SERIAL_MAGIC;
-		info->port = state->port;
-		info->flags = state->flags;
-		info->quot = 0;
-		info->tty = 0;
-	}
-	cli();
-	status = serial_in(info, UART_MSR);
-	control = info ? info->MCR : serial_in(info, UART_MCR);
-	sti();
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (control & UART_MCR_RTS)
-		strcat(stat_buf, "|RTS");
-	if (status & UART_MSR_CTS)
-		strcat(stat_buf, "|CTS");
-	if (control & UART_MCR_DTR)
-		strcat(stat_buf, "|DTR");
-	if (status & UART_MSR_DSR)
-		strcat(stat_buf, "|DSR");
-	if (status & UART_MSR_DCD)
-		strcat(stat_buf, "|CD");
-	if (status & UART_MSR_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->quot) {
-		ret += sprintf(buf+ret, " baud:%d",
-			       state->baud_base / info->quot);
-	}
-
-	ret += sprintf(buf+ret, " tx:%d rx:%d",
-		      state->icount.tx, state->icount.rx);
-
-	if (state->icount.frame)
-		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
-
-	if (state->icount.parity)
-		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
-
-	if (state->icount.brk)
-		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
-
-	if (state->icount.overrun)
-		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
-
-	/*
-	 * Last thing is the RS-232 status lines
-	 */
-	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
-#endif
-	return ret;
-}
-
-int rs_8xx_read_proc(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	int i, len = 0;
-	off_t	begin = 0;
-
-	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
-	for (i = 0; i < NR_PORTS && len < 4000; i++) {
-		len += line_info(page + len, &rs_table[i]);
-		if (len+begin > off+count)
-			goto done;
-		if (len+begin < off) {
-			begin += len;
-			len = 0;
-		}
-	}
-	*eof = 1;
-done:
-	if (off >= len+begin)
-		return 0;
-	*start = page + (begin-off);
-	return ((count < begin+len-off) ? count : begin+len-off);
-}
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static _INLINE_ void show_serial_version(void)
-{
- 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
-/*
- * The serial console driver used during boot.  Note that these names
- * clash with those found in "serial.c", so we currently can't support
- * the 16xxx uarts and these at the same time.  I will fix this to become
- * an indirect function call from tty_io.c (or something).
- */
-
-#ifdef CONFIG_SERIAL_CONSOLE
-
-/*
- * Print a string to the serial port trying not to disturb any possible
- * real use of the port...
- */
-static void serial_console_write(struct console *c, const char *s,
-				unsigned count)
-{
-	struct		serial_state	*ser;
-	ser_info_t			*info;
-	unsigned			i;
-	volatile	cbd_t		*bdp, *bdbase;
-	volatile	smc_uart_t	*up;
-	volatile	u_char		*cp;
-
-	ser = rs_table + c->index;
-
-	/* If the port has been initialized for general use, we have
-	 * to use the buffer descriptors allocated there.  Otherwise,
-	 * we simply use the single buffer allocated.
-	 */
-	if ((info = (ser_info_t *)ser->info) != NULL) {
-		bdp = info->tx_cur;
-		bdbase = info->tx_bd_base;
-	}
-	else {
-		/* Pointer to UART in parameter ram.
-		*/
-		up = (smc_uart_t *)&immr->im_dprambase[ser->port];
-
-		/* Get the address of the host memory buffer.
-		 */
-		bdp = bdbase = (cbd_t *)&immr->im_dprambase[up->smc_tbase];
-	}
-
-	/*
-	 * We need to gracefully shut down the transmitter, disable
-	 * interrupts, then send our bytes out.
-	 */
-
-	/*
-	 * Now, do each character.  This is not as bad as it looks
-	 * since this is a holding FIFO and not a transmitting FIFO.
-	 * We could add the complexity of filling the entire transmit
-	 * buffer, but we would just wait longer between accesses......
-	 */
-	for (i = 0; i < count; i++, s++) {
-		/* Wait for transmitter fifo to empty.
-		 * Ready indicates output is ready, and xmt is doing
-		 * that, not that it is ready for us to send.
-		 */
-		while (bdp->cbd_sc & BD_SC_READY);
-		/* Send the character out. */
-		cp = __va(bdp->cbd_bufaddr);
-		*cp = *s;
-
-		bdp->cbd_datlen = 1;
-		bdp->cbd_sc |= BD_SC_READY;
-
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = bdbase;
-		else
-			bdp++;
-
-		/* if a LF, also do CR... */
-		if (*s == 10) {
-			while (bdp->cbd_sc & BD_SC_READY);
-			cp = __va(bdp->cbd_bufaddr);
-			*cp = 13;
-			bdp->cbd_datlen = 1;
-			bdp->cbd_sc |= BD_SC_READY;
-
-			if (bdp->cbd_sc & BD_SC_WRAP) {
-				bdp = bdbase;
-			}
-			else {
-				bdp++;
-			}
-		}
-	}
-
-	/*
-	 * Finally, Wait for transmitter & holding register to empty
-	 *  and restore the IER
-	 */
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	if (info)
-		info->tx_cur = (cbd_t *)bdp;
-}
-
-static kdev_t serial_console_device(struct console *c)
-{
-	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
-}
-
-/*
- *	Register console.
- */
-long __init console_8xx_init(long kmem_start, long kmem_end)
-{
-	register_console(&sercons);
-	return kmem_start;
-}
-
-#endif
-
-/* Default console baud rate as determined by the board information
- * structure.
- */
-static	int	baud_idx;
-
-/*
- * The serial driver boot-time initialization code!
- */
-int __init rs_8xx_init(void)
-{
-	struct serial_state * state;
-	ser_info_t	*info;
-	uint		mem_addr, dp_addr;
-	int		i, j, idx;
-	uint		page, sblock;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-	volatile	smc_t		*sp;
-	volatile	smc_uart_t	*up;
-	volatile	scc_t		*scp;
-	volatile	scc_uart_t	*sup;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	init_bh(SERIAL_BH, do_serial_bh);
-
-	show_serial_version();
-
-	/* Initialize the tty_driver structure */
-
-	/*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
-	__clear_user(&serial_driver,sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.driver_name = "serial";
-#ifdef CONFIG_DEVFS_FS
-	serial_driver.name = "tts/%d";
-#else
-	serial_driver.name = "ttyS";
-#endif
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
-		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_8xx_open;
-	serial_driver.close = rs_8xx_close;
-	serial_driver.write = rs_8xx_write;
-	serial_driver.put_char = rs_8xx_put_char;
-	serial_driver.write_room = rs_8xx_write_room;
-	serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
-	serial_driver.flush_buffer = rs_8xx_flush_buffer;
-	serial_driver.ioctl = rs_8xx_ioctl;
-	serial_driver.throttle = rs_8xx_throttle;
-	serial_driver.unthrottle = rs_8xx_unthrottle;
-	serial_driver.send_xchar = rs_8xx_send_xchar;
-	serial_driver.set_termios = rs_8xx_set_termios;
-	serial_driver.stop = rs_8xx_stop;
-	serial_driver.start = rs_8xx_start;
-	serial_driver.hangup = rs_8xx_hangup;
-	serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
-	serial_driver.read_proc = rs_8xx_read_proc;
-
-	/*
-	 * The callout device is just like normal device except for
-	 * major number and the subtype code.
-	 */
-	callout_driver = serial_driver;
-#ifdef CONFIG_DEVFS_FS
-	callout_driver.name = "cua/%d";
-#else
-	callout_driver.name = "cua";
-#endif
-	callout_driver.major = TTYAUX_MAJOR;
-	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-	callout_driver.read_proc = 0;
-	callout_driver.proc_entry = 0;
-
-	if (tty_register_driver(&serial_driver))
-		panic("Couldn't register serial driver\n");
-	if (tty_register_driver(&callout_driver))
-		panic("Couldn't register callout driver\n");
-
-	immap = immr;
-	cp = &immap->im_cpm;
-	io = &immap->im_ioport;
-
-	/* This should have been done long ago by the early boot code,
-	 * but do it again to make sure.
-	 */
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
-
-	/* Geeze, here we go....Picking I/O port bits....Lots of
-	 * choices.  If you don't like mine, pick your own.
-	 * Configure SMCs Tx/Rx.  SMC1 is only on Port D, SMC2 is
-	 * only on Port A.  You either pick 'em, or not.
-	 */
-	io->iop_ppard |= 0x00c00000;
-	io->iop_pdird |= 0x00400000;
-	io->iop_pdird &= ~0x00800000;
-	io->iop_psord &= ~0x00c00000;
-#if USE_SMC2
-	io->iop_ppara |= 0x00c00000;
-	io->iop_pdira |= 0x00400000;
-	io->iop_pdira &= ~0x00800000;
-	io->iop_psora &= ~0x00c00000;
-#endif
-
-	/* Configure SCC2 and SCC3.  Be careful about the fine print.
-	 * Secondary options are only available when you take away
-	 * the primary option.  Unless the pins are used for something
-	 * else, SCC2 and SCC3 are on Port B.
-	 *	Port B,  8 - SCC3 TxD
-	 *	Port B, 12 - SCC2 TxD
-	 *	Port B, 14 - SCC3 RxD
-	 *	Port B, 15 - SCC2 RxD
-	 */
-	io->iop_pparb |= 0x008b0000;
-	io->iop_pdirb |= 0x00880000;
-	io->iop_psorb |= 0x00880000;
-	io->iop_pdirb &= ~0x00030000;
-	io->iop_psorb &= ~0x00030000;
-
-	/* Wire BRG1 to SMC1 and BRG2 to SMC2.
-	*/
-	immap->im_cpmux.cmx_smr = 0;
-
-	/* Connect SCC2 and SCC3 to NMSI.  Connect BRG3 to SCC2 and
-	 * BRG4 to SCC3.
-	 */
-	immap->im_cpmux.cmx_scr &= ~0x00ffff00;
-	immap->im_cpmux.cmx_scr |= 0x00121b00;
-
-	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
-		state->magic = SSTATE_MAGIC;
-		state->line = i;
-		state->type = PORT_UNKNOWN;
-		state->custom_divisor = 0;
-		state->close_delay = 5*HZ/10;
-		state->closing_wait = 30*HZ;
-		state->callout_termios = callout_driver.init_termios;
-		state->normal_termios = serial_driver.init_termios;
-		state->icount.cts = state->icount.dsr =
-			state->icount.rng = state->icount.dcd = 0;
-		state->icount.rx = state->icount.tx = 0;
-		state->icount.frame = state->icount.parity = 0;
-		state->icount.overrun = state->icount.brk = 0;
-		printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
-		       i, state->port,
-		       (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC");
-#ifdef CONFIG_SERIAL_CONSOLE
-		/* If we just printed the message on the console port, and
-		 * we are about to initialize it for general use, we have
-		 * to wait a couple of character times for the CR/NL to
-		 * make it out of the transmit buffer.
-		 */
-		if (i == CONFIG_SERIAL_CONSOLE_PORT)
-			mdelay(2);
-#endif
-		info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
-		if (info) {
-			/*memset(info, 0, sizeof(ser_info_t));*/
-			__clear_user(info,sizeof(ser_info_t));
-			init_waitqueue_head(&info->open_wait);
-			init_waitqueue_head(&info->close_wait);
-			info->magic = SERIAL_MAGIC;
-			info->flags = state->flags;
-			info->tqueue.routine = do_softint;
-			info->tqueue.data = info;
-			info->tqueue_hangup.routine = do_serial_hangup;
-			info->tqueue_hangup.data = info;
-			info->line = i;
-			info->state = state;
-			state->info = (struct async_struct *)info;
-
-			/* We need to allocate a transmit and receive buffer
-			 * descriptors from dual port ram, and a character
-			 * buffer area from host mem.
-			 */
-			dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO, 8);
-
-			/* Allocate space for FIFOs in the host memory.
-			*/
-			mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE, 1);
-
-			/* Set the physical address of the host memory
-			 * buffers in the buffer descriptors, and the
-			 * virtual address for us to work with.
-			 */
-			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
-			info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
-
-			for (j=0; j<(RX_NUM_FIFO-1); j++) {
-				bdp->cbd_bufaddr = __pa(mem_addr);
-				bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
-				mem_addr += RX_BUF_SIZE;
-				bdp++;
-			}
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
-
-			if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
-				sp = &immap->im_smc[idx];
-				up = (smc_uart_t *)&immap->im_dprambase[state->port];
-				up->smc_rbase = dp_addr;
-			}
-			else {
-				scp = &immap->im_scc[idx - SCC_IDX_BASE];
-				sup = (scc_uart_t *)&immap->im_dprambase[state->port];
-				sup->scc_genscc.scc_rbase = dp_addr;
-			}
-
-			dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO, 8);
-
-			/* Allocate space for FIFOs in the host memory.
-			*/
-			mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE, 1);
-
-			/* Set the physical address of the host memory
-			 * buffers in the buffer descriptors, and the
-			 * virtual address for us to work with.
-			 */
-			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
-			info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
-
-			for (j=0; j<(TX_NUM_FIFO-1); j++) {
-				bdp->cbd_bufaddr = __pa(mem_addr);
-				bdp->cbd_sc = BD_SC_INTRPT;
-				mem_addr += TX_BUF_SIZE;
-				bdp++;
-			}
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
-
-			if (idx < SCC_NUM_BASE) {
-				up->smc_tbase = dp_addr;
-
-				/* Set up the uart parameters in the
-				 * parameter ram.
-				 */
-				up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-				up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-				/* Set this to 1 for now, so we get single
-				 * character interrupts.  Using idle charater
-				 * time requires some additional tuning.
-				 */
-				up->smc_mrblr = 1;
-				up->smc_maxidl = 0;
-				up->smc_brkcr = 1;
-
-				/* Send the CPM an initialize command.
-				*/
-				if (state->smc_scc_num == 0) {
-					page = CPM_CR_SMC1_PAGE;
-					sblock = CPM_CR_SMC1_SBLOCK;
-				}
-				else {
-					page = CPM_CR_SMC2_PAGE;
-					sblock = CPM_CR_SMC2_SBLOCK;
-				}
-
-				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
-						CPM_CR_INIT_TRX) | CPM_CR_FLG;
-				while (cp->cp_cpcr & CPM_CR_FLG);
-
-				/* Set UART mode, 8 bit, no parity, one stop.
-				 * Enable receive and transmit.
-				 */
-				sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
-
-				/* Disable all interrupts and clear all pending
-				 * events.
-				 */
-				sp->smc_smcm = 0;
-				sp->smc_smce = 0xff;
-			}
-			else {
-				sup->scc_genscc.scc_tbase = dp_addr;
-
-				/* Set up the uart parameters in the
-				 * parameter ram.
-				 */
-				sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-				sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-				/* Set this to 1 for now, so we get single
-				 * character interrupts.  Using idle charater
-				 * time requires some additional tuning.
-				 */
-				sup->scc_genscc.scc_mrblr = 1;
-				sup->scc_maxidl = 0;
-				sup->scc_brkcr = 1;
-				sup->scc_parec = 0;
-				sup->scc_frmec = 0;
-				sup->scc_nosec = 0;
-				sup->scc_brkec = 0;
-				sup->scc_uaddr1 = 0;
-				sup->scc_uaddr2 = 0;
-				sup->scc_toseq = 0;
-				sup->scc_char1 = 0x8000;
-				sup->scc_char2 = 0x8000;
-				sup->scc_char3 = 0x8000;
-				sup->scc_char4 = 0x8000;
-				sup->scc_char5 = 0x8000;
-				sup->scc_char6 = 0x8000;
-				sup->scc_char7 = 0x8000;
-				sup->scc_char8 = 0x8000;
-				sup->scc_rccm = 0xc0ff;
-
-				/* Send the CPM an initialize command.
-				*/
-				if (state->smc_scc_num == 2) {
-					page = CPM_CR_SCC2_PAGE;
-					sblock = CPM_CR_SCC2_SBLOCK;
-				}
-				else {
-					page = CPM_CR_SCC3_PAGE;
-					sblock = CPM_CR_SCC3_SBLOCK;
-				}
-
-				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
-						CPM_CR_INIT_TRX) | CPM_CR_FLG;
-				while (cp->cp_cpcr & CPM_CR_FLG);
-
-				/* Set UART mode, 8 bit, no parity, one stop.
-				 * Enable receive and transmit.
-				 */
-				scp->scc_gsmrh = 0;
-				scp->scc_gsmrl =
-					(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
-				/* Disable all interrupts and clear all pending
-				 * events.
-				 */
-				scp->scc_sccm = 0;
-				scp->scc_scce = 0xffff;
-				scp->scc_dsr = 0x7e7e;
-				scp->scc_pmsr = 0x3000;
-			}
-
-			/* Install interrupt handler.
-			*/
-			request_irq(state->irq, rs_8xx_interrupt, 0, "uart",
-					info);
-
-			/* Set up the baud rate generator.
-			*/
-			m8260_cpm_setbrg(state->smc_scc_num,
-							baud_table[baud_idx]);
-
-			/* If the port is the console, enable Rx and Tx.
-			*/
-#ifdef CONFIG_SERIAL_CONSOLE
-			if (i == CONFIG_SERIAL_CONSOLE_PORT)
-				sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-#endif
-		}
-	}
-	return 0;
-}
-
-/* This must always be called before the rs_8xx_init() function, otherwise
- * it blows away the port control information.
-*/
-static int __init serial_console_setup(struct console *co, char *options)
-{
-	struct		serial_state *ser;
-	uint		mem_addr, dp_addr, bidx;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-	volatile	immap_t		*immap;
-	volatile	smc_t		*sp;
-	volatile	smc_uart_t	*up;
-	volatile	iop8260_t	*io;
-	bd_t				*bd;
-
-	bd = (bd_t *)__res;
-
-	for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
-		if (bd->bi_baudrate == baud_table[bidx])
-			break;
-
-	co->cflag = CREAD|CLOCAL|bidx|CS8;
-	baud_idx = bidx;
-
-	ser = rs_table + co->index;
-
-
-	immap = immr;
-	cp = &immap->im_cpm;
-	io = &immap->im_ioport;
-
-	/* This should have been done long ago by the early boot code,
-	 * but do it again to make sure.
-	 */
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
-
-	/* Right now, assume we are using SMCs.
-	*/
-	sp = &immap->im_smc[ser->smc_scc_num];
-
-	/* When we get here, the CPM has been reset, so we need
-	 * to configure the port.
-	 * We need to allocate a transmit and receive buffer descriptor
-	 * from dual port ram, and a character buffer area from host mem.
-	 */
-	up = (smc_uart_t *)&immap->im_dprambase[ser->port];
-
-	/* Disable transmitter/receiver.
-	*/
-	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-
-	/* Use Port D for SMC1 instead of other functions.
-	*/
-	io->iop_ppard |= 0x00c00000;
-	io->iop_pdird |= 0x00400000;
-	io->iop_pdird &= ~0x00800000;
-	io->iop_psord &= ~0x00c00000;
-
-	/* Allocate space for two buffer descriptors in the DP ram.
-	*/
-	dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2, 8);
-
-	/* Allocate space for two 2 byte FIFOs in the host memory.
-	*/
-	mem_addr = m8260_cpm_hostalloc(4, 1);
-
-	/* Set the physical address of the host memory buffers in
-	 * the buffer descriptors.
-	 */
-	bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
-	bdp->cbd_bufaddr = __pa(mem_addr);
-	(bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
-
-	/* For the receive, set empty and wrap.
-	 * For transmit, set wrap.
-	 */
-	bdp->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
-	(bdp+1)->cbd_sc = BD_SC_WRAP;
-
-	/* Set up the uart parameters in the parameter ram.
-	*/
-	up->smc_rbase = dp_addr;	/* Base of receive buffer desc. */
-	up->smc_tbase = dp_addr+sizeof(cbd_t);	/* Base of xmt buffer desc. */
-	up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-	/* Set this to 1 for now, so we get single character interrupts.
-	*/
-	up->smc_mrblr = 1;		/* receive buffer length */
-	up->smc_maxidl = 0;		/* wait forever for next char */
-
-	/* Send the CPM an initialize command.
-	*/
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
-			CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	/* Set UART mode, 8 bit, no parity, one stop.
-	 * Enable receive and transmit.
-	 */
-	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
-
-	/* Set up the baud rate generator.
-	*/
-	m8260_cpm_setbrg(ser->smc_scc_num, bd->bi_baudrate);
-
-	/* And finally, enable Rx and Tx.
-	*/
-	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-
-	return 0;
-}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/Makefile linux-2.4.26-pre6/arch/ppc/Makefile
--- linux-2.4.25/arch/ppc/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/Makefile	2004-03-25 00:17:20.000000000 +0000
@@ -72,9 +72,9 @@ SUBDIRS += arch/ppc/8xx_io
 DRIVERS += arch/ppc/8xx_io/8xx_io.o
 endif
 
-ifdef CONFIG_8260
-SUBDIRS += arch/ppc/8260_io
-DRIVERS += arch/ppc/8260_io/8260_io.o
+ifdef CONFIG_CPM2
+SUBDIRS += arch/ppc/cpm2_io
+DRIVERS += arch/ppc/cpm2_io/cpm2_io.o
 endif
 
 ifdef CONFIG_APUS
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/boot/simple/embed_config.c linux-2.4.26-pre6/arch/ppc/boot/simple/embed_config.c
--- linux-2.4.25/arch/ppc/boot/simple/embed_config.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/boot/simple/embed_config.c	2004-03-25 00:21:27.000000000 +0000
@@ -14,7 +14,7 @@
 #endif
 #ifdef CONFIG_8260
 #include <asm/mpc8260.h>
-#include <asm/immap_8260.h>
+#include <asm/immap_cpm2.h>
 #endif
 #ifdef CONFIG_4xx
 #include <asm/io.h>
@@ -394,10 +394,10 @@ static void
 clk_8260(bd_t *bd)
 {
 	uint	scmr, vco_out, clkin;
-	uint	plldf, pllmf, busdf, brgdf, cpmdf;
-	volatile immap_t	*ip;
+	uint	plldf, pllmf, busdf, cpmdf;
+	volatile cpm2_map_t	*ip;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 	scmr = ip->im_clkrst.car_scmr;
 
 	/* The clkin is always bus frequency.
@@ -502,7 +502,6 @@ void
 embed_config(bd_t **bdp)
 {
 	u_char	*cp, *keyvals;
-	int	i;
 	bd_t	*bd;
 
 	keyvals = (u_char *)*bdp;
@@ -582,7 +581,7 @@ embed_config(bd_t **bdp)
 	*/
 	bd->bi_intfreq = 200000000;
 }
-#endif /* RPX6 for testing */
+#endif /* RPX6 */
 
 #ifdef CONFIG_ADS8260
 void
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/boot/simple/m8260_tty.c linux-2.4.26-pre6/arch/ppc/boot/simple/m8260_tty.c
--- linux-2.4.25/arch/ppc/boot/simple/m8260_tty.c	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/boot/simple/m8260_tty.c	2004-03-25 00:21:08.000000000 +0000
@@ -3,7 +3,8 @@
  */
 #include <linux/types.h>
 #include <asm/mpc8260.h>
-#include <asm/cpm_8260.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
 
 uint	no_print;
 extern char	*params[];
@@ -29,12 +30,12 @@ serial_init(int ignored, bd_t *bd)
 	volatile scc_uart_t	*sup;
 #endif
 	volatile cbd_t	*tbdf, *rbdf;
-	volatile immap_t	*ip;
-	volatile iop8260_t	*io;
-	volatile cpm8260_t	*cp;
+	volatile cpm2_map_t	*ip;
+	volatile iop_cpm2_t	*io;
+	volatile cpm_cpm2_t	*cp;
 	uint	dpaddr, memaddr;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 	cp = &ip->im_cpm;
 	io = &ip->im_ioport;
 
@@ -223,10 +224,10 @@ serial_readbuf(u_char *cbuf)
 	volatile char		*buf;
 	volatile smc_uart_t	*up;
 	volatile scc_uart_t	*sup;
-	volatile immap_t	*ip;
+	volatile cpm2_map_t	*ip;
 	int	i, nc;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 
 #ifdef SCC_CONSOLE
 	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
@@ -255,10 +256,10 @@ serial_putc(void *ignored, const char c)
 	volatile char		*buf;
 	volatile smc_uart_t	*up;
 	volatile scc_uart_t	*sup;
-	volatile immap_t	*ip;
+	volatile cpm2_map_t	*ip;
 	extern bd_t		*board_info;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 #ifdef SCC_CONSOLE
 	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
 	tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
@@ -298,9 +299,9 @@ serial_tstc(void *ignored)
 	volatile cbd_t		*rbdf;
 	volatile smc_uart_t	*up;
 	volatile scc_uart_t	*sup;
-	volatile immap_t	*ip;
+	volatile cpm2_map_t	*ip;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 #ifdef SCC_CONSOLE
 	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
 	rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/config.in linux-2.4.26-pre6/arch/ppc/config.in
--- linux-2.4.25/arch/ppc/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/config.in	2004-03-25 00:20:11.000000000 +0000
@@ -57,14 +57,30 @@ fi
 
 if [ "$CONFIG_8260" = "y" ]; then
   define_bool CONFIG_SERIAL_CONSOLE y
-  bool 'Support for EST8260' CONFIG_EST8260
+  define_bool CONFIG_CPM2 y
+  bool '  MPC8272 Family Support' CONFIG_8272
+  choice 'Machine Type'	\
+	"ADS8272	CONFIG_ADS8272	\
+	 EST8260	CONFIG_EST8260 \
+	 RPX8260	CONFIG_RPX6"	RPX8260
+fi
+
+if [ "$CONFIG_ADS8272" = "y" ]; then
+  define_bool CONFIG_PQ2ADS y
 fi
 
 if [ "$CONFIG_40x" = "y" ]; then
     choice 'Machine Type'			\
 	 "CPCI405	CONFIG_CPCI405 		\
+	 EP405/EP405PC	CONFIG_EP405 		\
+	 Redwood-5	CONFIG_REDWOOD_5 	\
+	 Redwood-6	CONFIG_REDWOOD_6 	\
 	 Oak		CONFIG_OAK		\
 	 Walnut		CONFIG_WALNUT"		Walnut
+
+   if [ "$CONFIG_EP405" = "y" ]; then
+      bool 'EP405PC Support' CONFIG_EP405PC
+   fi
 fi
 
 if [ "$CONFIG_44x" = "y" ]; then
@@ -170,11 +186,6 @@ fi
 
 if [ "$CONFIG_4xx" = "y" ]; then
 
-  bool 'PPC4xx DMA controller support' CONFIG_PPC4xx_DMA
-  if [ "$CONFIG_PPC4xx_DMA" = "y" ]; then
-    define_bool CONFIG_PPC4xx_EDMA y
-  fi
-
 #
 # Set generic PPC4xx options
 #
@@ -194,10 +205,18 @@ if [ "$CONFIG_4xx" = "y" ]; then
     define_bool CONFIG_405GP y
   fi
 
+  if [ "$CONFIG_EP405" = "y" ]; then
+    define_bool CONFIG_405GP y
+  fi
+
   if [ "$CONFIG_OAK" = "y" -o "$CONFIG_TIVO" = "y" ]; then
     define_bool CONFIG_403GCX y
   fi
 
+  if [ "$CONFIG_REDWOOD_5" = "y" -o "$CONFIG_REDWOOD_6" = "y" ]; then
+    define_bool CONFIG_STB03xxx y
+  fi
+
   if [ "$CONFIG_WALNUT" = "y" ]; then
     define_bool CONFIG_405GP y
   fi
@@ -213,19 +232,22 @@ if [ "$CONFIG_4xx" = "y" ]; then
 #
 # Set options based on processor implementation
 #
-  if [ "$CONFIG_405GP" = "y" ]; then
+  if [ "$CONFIG_405GP" = "y" -o "$CONFIG_STB03xxx" = "y" ]; then
     define_bool CONFIG_IBM_OCP y
+    define_bool CONFIG_PPC_OCP y
     define_bool CONFIG_405 y
   fi
 
   if [ "$CONFIG_440GP" = "y" ]; then
     define_bool CONFIG_IBM_OCP y
+    define_bool CONFIG_PPC_OCP y
     define_bool CONFIG_GEN550 y
     define_bool CONFIG_440 y
   fi
 
   if [ "$CONFIG_440GX" = "y" ]; then
     define_bool CONFIG_IBM_OCP y
+    define_bool CONFIG_PPC_OCP y
     define_bool CONFIG_GEN550 y
     define_bool CONFIG_IBM_EMAC4 y
     define_bool CONFIG_440A y
@@ -248,15 +270,26 @@ if [ "$CONFIG_4xx" = "y" ]; then
     define_bool CONFIG_BOOKE y
   fi
 
+  bool 'PPC4xx DMA controller support' CONFIG_PPC4xx_DMA
+  if [ "$CONFIG_PPC4xx_DMA" = "y" ]; then
+    if [ "$CONFIG_405GP" = "y" ]; then
+      define_bool CONFIG_PPC4xx_EDMA y
+    fi
+    if [ "$CONFIG_STB03xxx" = "y" ]; then
+      define_bool CONFIG_STBXXX_DMA y
+    fi
+  fi
+
 #
 # Set other board specific options
 #
   if [ "$CONFIG_OAK" = "y" -o "$CONFIG_TIVO" = "y" -o \
-  "$CONFIG_WALNUT" = "y" ]; then
+       "$CONFIG_REDWOOD_5" = "y" -o "$CONFIG_REDWOOD_6" = "y" -o \
+       "$CONFIG_WALNUT" = "y" ]; then
     define_bool CONFIG_IBM_OPENBIOS y
   fi
 
-  if [ "$CONFIG_WALNUT" = "y" ]; then
+  if [ "$CONFIG_WALNUT" = "y" -o "$CONFIG_EP405" = "y" ]; then
     define_bool CONFIG_BIOS_FIXUP y
   fi
 
@@ -572,8 +605,8 @@ if [ "$CONFIG_8xx" = "y" ]; then
 source arch/ppc/8xx_io/Config.in
 fi
 
-if [ "$CONFIG_8260" = "y" ]; then
-source arch/ppc/8260_io/Config.in
+if [ "$CONFIG_CPM2" = "y" ]; then
+source arch/ppc/cpm2_io/Config.in
 fi
 
 source drivers/usb/Config.in
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/configs/ads8272_defconfig linux-2.4.26-pre6/arch/ppc/configs/ads8272_defconfig
--- linux-2.4.25/arch/ppc/configs/ads8272_defconfig	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/configs/ads8272_defconfig	2004-03-25 00:19:57.000000000 +0000
@@ -0,0 +1,629 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_ADVANCED_OPTIONS=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_8260=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_CPM2=y
+CONFIG_8272=y
+CONFIG_ADS8272=y
+# CONFIG_EST8260 is not set
+CONFIG_PQ2ADS=y
+# CONFIG_SMP is not set
+CONFIG_EMBEDDEDBOOT=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+# CONFIG_KERNEL_START_BOOL is not set
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_PPC_RTC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+#   IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+#   IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+# CONFIG_IRPORT_SIR is not set
+# CONFIG_DONGLE is not set
+# CONFIG_USB_IRDA is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_OLD is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_IRCC_FIR is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=m
+CONFIG_INPUT_KEYBDEV=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_UNIX is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_SMB_NLS=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8260 CPM Options
+#
+CONFIG_SCC_CONSOLE=y
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+CONFIG_FCC1_ENET=y
+CONFIG_FCC2_ENET=y
+# CONFIG_FCC3_ENET is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/configs/ep405_defconfig linux-2.4.26-pre6/arch/ppc/configs/ep405_defconfig
--- linux-2.4.25/arch/ppc/configs/ep405_defconfig	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/configs/ep405_defconfig	2004-03-25 00:20:46.000000000 +0000
@@ -0,0 +1,549 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+# CONFIG_CPCI405 is not set
+CONFIG_EP405=y
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_OAK is not set
+# CONFIG_WALNUT is not set
+CONFIG_EP405PC=y
+# CONFIG_SMP is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_405GP=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_405=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM405_ERR77=y
+# CONFIG_PPC4xx_DMA is not set
+CONFIG_BIOS_FIXUP=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_PCI=y
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_PCI_NAMES is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_GEN_RTC=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_STATS=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# On-chip net devices
+#
+CONFIG_IBM_OCP_ENET=y
+# CONFIG_IBM_OCP_ENET_ERROR_MSG is not set
+CONFIG_IBM_OCP_ENET_RX_BUFF=64
+CONFIG_IBM_OCP_ENET_TX_BUFF=8
+CONFIG_IBM_OCP_ENET_GAP=8
+CONFIG_IBM_OCP_ENET_SKB_RES=0
+CONFIG_OCP_NET=y
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_PPC405_ALGO=y
+CONFIG_I2C_PPC405_ADAP=y
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_PROC is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/configs/est8260_defconfig linux-2.4.26-pre6/arch/ppc/configs/est8260_defconfig
--- linux-2.4.25/arch/ppc/configs/est8260_defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/configs/est8260_defconfig	2004-03-25 00:20:07.000000000 +0000
@@ -1,5 +1,5 @@
 #
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
 #
 # CONFIG_UID16 is not set
 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
@@ -10,6 +10,7 @@ CONFIG_HAVE_DEC_LOCK=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
 
 #
 # Loadable module support
@@ -22,13 +23,17 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_PPC=y
 CONFIG_PPC32=y
 CONFIG_6xx=y
-# CONFIG_4xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
 # CONFIG_8xx is not set
 CONFIG_8260=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_SERIAL_CONSOLE=y
+CONFIG_CPM2=y
+# CONFIG_8272 is not set
+# CONFIG_ADS8272 is not set
 CONFIG_EST8260=y
 # CONFIG_SMP is not set
 CONFIG_EMBEDDEDBOOT=y
@@ -37,11 +42,16 @@ CONFIG_EMBEDDEDBOOT=y
 # General setup
 #
 # CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
 # CONFIG_MCA is not set
 # CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -81,6 +91,7 @@ CONFIG_GEN_RTC=y
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -126,12 +137,14 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
 
 #
-#  
+#    SCTP Configuration (EXPERIMENTAL)
 #
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 
@@ -280,6 +293,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Macintosh device drivers
@@ -310,14 +324,6 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Joysticks
 #
 # CONFIG_INPUT_GAMEPORT is not set
-
-#
-# Input core support is needed for gameports
-#
-
-#
-# Input core support is needed for joysticks
-#
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_IPMI_PANIC_EVENT is not set
@@ -329,6 +335,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
@@ -342,6 +349,10 @@ CONFIG_UNIX98_PTY_COUNT=256
 #
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 # CONFIG_DRM is not set
 
 #
@@ -353,6 +364,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -362,6 +374,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -403,6 +416,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -411,6 +429,7 @@ CONFIG_EXT2_FS=y
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
@@ -466,13 +485,24 @@ CONFIG_SCC1_ENET=y
 # CONFIG_USB is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Bluetooth support
 #
 # CONFIG_BLUEZ is not set
 
 #
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
 # Library routines
 #
+# CONFIG_CRC32 is not set
 # CONFIG_ZLIB_INFLATE is not set
 # CONFIG_ZLIB_DEFLATE is not set
 
@@ -480,3 +510,4 @@ CONFIG_SCC1_ENET=y
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/configs/redwood5_defconfig linux-2.4.26-pre6/arch/ppc/configs/redwood5_defconfig
--- linux-2.4.25/arch/ppc/configs/redwood5_defconfig	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/configs/redwood5_defconfig	2004-03-25 00:19:19.000000000 +0000
@@ -0,0 +1,573 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+CONFIG_REDWOOD_5=y
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_OAK is not set
+# CONFIG_WALNUT is not set
+# CONFIG_SMP is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_STB03xxx=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_405=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM405_ERR77=y
+CONFIG_PPC4xx_DMA=y
+CONFIG_STBXXX_DMA=y
+CONFIG_IBM_OPENBIOS=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_GEN_RTC=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_STATS=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_OAKNET is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# On-chip net devices
+#
+# CONFIG_IBM_OCP_ENET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_PPC405_ALGO=y
+CONFIG_I2C_PPC405_ADAP=y
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_PROC is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/configs/redwood6_defconfig linux-2.4.26-pre6/arch/ppc/configs/redwood6_defconfig
--- linux-2.4.25/arch/ppc/configs/redwood6_defconfig	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/configs/redwood6_defconfig	2004-03-25 00:22:28.000000000 +0000
@@ -0,0 +1,534 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_REDWOOD_5 is not set
+CONFIG_REDWOOD_6=y
+# CONFIG_OAK is not set
+# CONFIG_WALNUT is not set
+# CONFIG_SMP is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_STB03xxx=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_405=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM405_ERR77=y
+CONFIG_PPC4xx_DMA=y
+CONFIG_STBXXX_DMA=y
+CONFIG_IBM_OPENBIOS=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_GEN_RTC=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_STATS=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_OAKNET is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# On-chip net devices
+#
+# CONFIG_IBM_OCP_ENET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/configs/rpx8260_defconfig linux-2.4.26-pre6/arch/ppc/configs/rpx8260_defconfig
--- linux-2.4.25/arch/ppc/configs/rpx8260_defconfig	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/configs/rpx8260_defconfig	2004-03-25 00:20:02.000000000 +0000
@@ -0,0 +1,535 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E500 is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_8260=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_CPM2=y
+# CONFIG_8272 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_EST8260 is not set
+CONFIG_RPX6=y
+# CONFIG_SMP is not set
+CONFIG_EMBEDDEDBOOT=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_PPC_RTC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_GIANFAR is not set
+# CONFIG_GFAR_NAPI is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8260 CPM Options
+#
+# CONFIG_SCC_CONSOLE is not set
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_FCC1_ENET is not set
+# CONFIG_FCC2_ENET is not set
+CONFIG_FCC3_ENET=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/cpm2_io/Config.in linux-2.4.26-pre6/arch/ppc/cpm2_io/Config.in
--- linux-2.4.25/arch/ppc/cpm2_io/Config.in	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/cpm2_io/Config.in	2004-03-25 00:17:11.000000000 +0000
@@ -0,0 +1,26 @@
+#
+# MPC8260 Communication options
+#
+mainmenu_option next_comment
+comment 'MPC8260 CPM Options'
+bool 'Enable SCC Console' CONFIG_SCC_CONSOLE
+if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+  bool 'CPM SCC Ethernet' CONFIG_SCC_ENET
+  if [ "$CONFIG_SCC_ENET" = "y" ]; then
+  bool 'Ethernet on SCC1' CONFIG_SCC1_ENET
+    if [ "$CONFIG_SCC1_ENET" != "y" ]; then
+      bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
+    fi
+  fi
+#
+#  CONFIG_FEC_ENET is only used to get netdevices to call our init
+#    function.  Any combination of FCC1,2,3 are supported.
+#
+  bool 'FCC Ethernet' CONFIG_FEC_ENET
+  if [ "$CONFIG_FEC_ENET" = "y" ]; then
+    bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
+    bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
+    bool 'Ethernet on FCC3' CONFIG_FCC3_ENET
+  fi
+fi
+endmenu
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/cpm2_io/Makefile linux-2.4.26-pre6/arch/ppc/cpm2_io/Makefile
--- linux-2.4.25/arch/ppc/cpm2_io/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/cpm2_io/Makefile	2004-03-25 00:20:56.000000000 +0000
@@ -0,0 +1,17 @@
+#
+# Makefile for the linux CPM2 ppc-specific parts of comm processor
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET		:= cpm2_io.o
+
+obj-y			:= commproc.o uart.o
+
+obj-$(CONFIG_FEC_ENET)	+= fcc_enet.o
+obj-$(CONFIG_SCC_ENET)	+= enet.o
+
+include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/cpm2_io/commproc.c linux-2.4.26-pre6/arch/ppc/cpm2_io/commproc.c
--- linux-2.4.25/arch/ppc/cpm2_io/commproc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/cpm2_io/commproc.c	2004-03-25 00:16:51.000000000 +0000
@@ -0,0 +1,179 @@
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ *	2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
+
+static	uint	dp_alloc_base;	/* Starting offset in DP ram */
+static	uint	dp_alloc_top;	/* Max offset + 1 */
+static	uint	host_buffer;	/* One page of host buffer */
+static	uint	host_end;	/* end + 1 */
+cpm_cpm2_t	*cpmp;		/* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+cpm2_map_t		*cpm2_immr;
+
+void
+cpm2_reset(void)
+{
+	volatile cpm2_map_t	 *imp;
+	volatile cpm_cpm2_t	*commproc;
+	uint			vpgaddr;
+
+	cpm2_immr = imp = (volatile cpm2_map_t *)CPM_MAP_ADDR;
+	commproc = &imp->im_cpm;
+
+	/* Reclaim the DP memory for our use.
+	*/
+	dp_alloc_base = CPM_DATAONLY_BASE;
+	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+
+	/* Set the host page for allocation.
+	*/
+	host_buffer =
+		(uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
+	host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
+
+	vpgaddr = host_buffer;
+
+	/* Tell everyone where the comm processor resides.
+	*/
+	cpmp = (cpm_cpm2_t *)commproc;
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+cpm2_dpalloc(uint size, uint align)
+{
+	uint	retloc;
+	uint	align_mask, off;
+	uint	savebase;
+
+	align_mask = align - 1;
+	savebase = dp_alloc_base;
+
+	if ((off = (dp_alloc_base & align_mask)) != 0)
+		dp_alloc_base += (align - off);
+
+	if ((dp_alloc_base + size) >= dp_alloc_top) {
+		dp_alloc_base = savebase;
+		return(CPM_DP_NOSPACE);
+	}
+
+	retloc = dp_alloc_base;
+	dp_alloc_base += size;
+
+	return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+cpm2_hostalloc(uint size, uint align)
+{
+	uint	retloc;
+	uint	align_mask, off;
+	uint	savebase;
+
+	align_mask = align - 1;
+	savebase = host_buffer;
+
+	if ((off = (host_buffer & align_mask)) != 0)
+		host_buffer += (align - off);
+
+	if ((host_buffer + size) >= host_end) {
+		host_buffer = savebase;
+		return(0);
+	}
+
+	retloc = host_buffer;
+	host_buffer += size;
+
+	return(retloc);
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks.  The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers).  Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK	(((bd_t *)__res)->bi_brgfreq)
+#define BRG_UART_CLK	(BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+cpm2_setbrg(uint brg, uint rate)
+{
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	if (brg < 4) {
+		bp = (uint *)&cpm2_immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&cpm2_immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+cpm2_fastbrg(uint brg, uint rate, int div16)
+{
+	volatile uint	*bp;
+
+	if (brg < 4) {
+		bp = (uint *)&cpm2_immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&cpm2_immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+	if (div16)
+		*bp |= CPM_BRG_DIV16;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/cpm2_io/enet.c linux-2.4.26-pre6/arch/ppc/cpm2_io/enet.c
--- linux-2.4.25/arch/ppc/cpm2_io/enet.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/cpm2_io/enet.c	2004-03-25 00:16:53.000000000 +0000
@@ -0,0 +1,857 @@
+/*
+ * Ethernet driver for Motorola MPC8260.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
+ *	2.3.99 Updates
+ *
+ * I copied this from the 8xx CPM Ethernet driver, so follow the
+ * credits back through that.
+ *
+ * This version of the driver is somewhat selectable for the different
+ * processor/board combinations.  It works for the boards I know about
+ * now, and should be easily modified to include others.  Some of the
+ * configuration information is contained in <asm/commproc.h> and the
+ * remainder is here.
+ *
+ * Buffer descriptors are kept in the CPM dual port RAM, and the frame
+ * buffers are in the host memory.
+ *
+ * Right now, I am very watseful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm2.h>
+#include <asm/irq.h>
+
+/*
+ *				Theory of Operation
+ *
+ * The MPC8260 CPM performs the Ethernet processing on an SCC.  It can use
+ * an aribtrary number of buffers on byte boundaries, but must have at
+ * least two receive buffers to prevent constant overrun conditions.
+ *
+ * The buffer descriptors are allocated from the CPM dual port memory
+ * with the data buffers allocated from host memory, just like all other
+ * serial communication protocols.  The host memory buffers are allocated
+ * from the free page pool, and then divided into smaller receive and
+ * transmit buffers.  The size of the buffers should be a power of two,
+ * since that nicely divides the page.  This creates a ring buffer
+ * structure similar to the LANCE and other controllers.
+ *
+ * Like the LANCE driver:
+ * The driver runs as two independent, single-threaded flows of control.  One
+ * is the send-packet routine, which enforces single-threaded use by the
+ * cep->tx_busy flag.  The other thread is the interrupt handler, which is
+ * single threaded by the hardware and other software.
+ */
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT	(2*HZ)
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+#define CPM_ENET_RX_PAGES	4
+#define CPM_ENET_RX_FRSIZE	2048
+#define CPM_ENET_RX_FRPPG	(PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE		8	/* Must be power of two */
+#define TX_RING_MOD_MASK	7	/*   for this to work */
+
+/* The CPM stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+#define PKT_MAXBLR_SIZE		1520
+
+/* The CPM buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct scc_enet_private {
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	ushort	skb_cur;
+	ushort	skb_dirty;
+
+	/* CPM dual port RAM relative addresses.
+	*/
+	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
+	cbd_t	*tx_bd_base;
+	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
+	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	scc_t	*sccp;
+	struct	net_device_stats stats;
+	uint	tx_free;
+	spinlock_t lock;
+};
+
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/* These will be configurable for the SCC choice.
+*/
+#define CPM_ENET_BLOCK	CPM_CR_SCC1_SBLOCK
+#define CPM_ENET_PAGE	CPM_CR_SCC1_PAGE
+#define PROFF_ENET	PROFF_SCC1
+#define SCC_ENET	0
+#define SIU_INT_ENET	SIU_INT_SCC1
+
+/* These are both board and SCC dependent....
+*/
+#define PD_ENET_RXD	((uint)0x00000001)
+#define PD_ENET_TXD	((uint)0x00000002)
+#define PD_ENET_TENA	((uint)0x00000004)
+#define PC_ENET_RENA	((uint)0x00020000)
+#define PC_ENET_CLSN	((uint)0x00000004)
+#define PC_ENET_TXCLK	((uint)0x00000800)
+#define PC_ENET_RXCLK	((uint)0x00000400)
+#define CMX_CLK_ROUTE	((uint)0x25000000)
+#define CMX_CLK_MASK	((uint)0xff000000)
+
+/* Specific to a board.
+*/
+#define PC_EST8260_ENET_LOOPBACK	((uint)0x80000000)
+#define PC_EST8260_ENET_SQE		((uint)0x40000000)
+#define PC_EST8260_ENET_NOTFD		((uint)0x20000000)
+
+static int
+scc_enet_open(struct net_device *dev)
+{
+
+	/* I should reset the ring buffers here, but I don't yet know
+	 * a simple way to do that.
+	 */
+	netif_start_queue(dev);
+	return 0;					/* Always succeed */
+}
+
+static int
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+	volatile cbd_t	*bdp;
+
+
+	/* Fill in a Tx ring entry */
+	bdp = cep->cur_tx;
+
+#ifndef final_version
+	if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since the tx queue should be stopped.
+		 */
+		printk("%s: tx queue full!.\n", dev->name);
+		return 1;
+	}
+#endif
+
+	/* Clear all of the status flags.
+	 */
+	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+	/* If the frame is short, tell CPM to pad it.
+	*/
+	if (skb->len <= ETH_ZLEN)
+		bdp->cbd_sc |= BD_ENET_TX_PAD;
+	else
+		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+	/* Set buffer length and buffer pointer.
+	*/
+	bdp->cbd_datlen = skb->len;
+	bdp->cbd_bufaddr = __pa(skb->data);
+
+	/* Save skb pointer.
+	*/
+	cep->tx_skbuff[cep->skb_cur] = skb;
+
+	cep->stats.tx_bytes += skb->len;
+	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+	spin_lock_irq(&cep->lock);
+
+	/* Send it on its way.  Tell CPM its ready, interrupt when done,
+	 * its the last BD of the frame, and to put the CRC on the end.
+	 */
+	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+	dev->trans_start = jiffies;
+
+	/* If this was the last BD in the ring, start at the beginning again.
+	*/
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = cep->tx_bd_base;
+	else
+		bdp++;
+
+	if (!--cep->tx_free)
+		netif_stop_queue(dev);
+
+	cep->cur_tx = (cbd_t *)bdp;
+
+	spin_unlock_irq(&cep->lock);
+
+	return 0;
+}
+
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+	printk("%s: transmit timed out.\n", dev->name);
+	cep->stats.tx_errors++;
+#ifndef final_version
+	{
+		int	i;
+		cbd_t	*bdp;
+		printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n",
+		       cep->cur_tx, cep->tx_free,
+		       cep->cur_rx);
+		bdp = cep->tx_bd_base;
+		printk(" Tx @base %p :\n", bdp);
+		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+		bdp = cep->rx_bd_base;
+		printk(" Rx @base %p :\n", bdp);
+		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+	}
+#endif
+	if (cep->tx_free)
+		netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static void
+scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	net_device *dev = dev_id;
+	volatile struct	scc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	ushort	int_events;
+	int	must_restart;
+
+	cep = (struct scc_enet_private *)dev->priv;
+
+	/* Get the interrupt events that caused us to be here.
+	*/
+	int_events = cep->sccp->scc_scce;
+	cep->sccp->scc_scce = int_events;
+	must_restart = 0;
+
+	/* Handle receive event in its own function.
+	*/
+	if (int_events & SCCE_ENET_RXF)
+		scc_enet_rx(dev_id);
+
+	/* Check for a transmit error.  The manual is a little unclear
+	 * about this, so the debug code until I get it figured out.  It
+	 * appears that if TXE is set, then TXB is not set.  However,
+	 * if carrier sense is lost during frame transmission, the TXE
+	 * bit is set, "and continues the buffer transmission normally."
+	 * I don't know if "normally" implies TXB is set when the buffer
+	 * descriptor is closed.....trial and error :-).
+	 */
+
+	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	*/
+	if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+	    spin_lock(&cep->lock);
+	    bdp = cep->dirty_tx;
+	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+		if (cep->tx_free == TX_RING_SIZE)
+		    break;
+
+		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
+			cep->stats.tx_heartbeat_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
+			cep->stats.tx_window_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
+			cep->stats.tx_aborted_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
+			cep->stats.tx_fifo_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
+			cep->stats.tx_carrier_errors++;
+
+
+		/* No heartbeat or Lost carrier are not really bad errors.
+		 * The others require a restart transmit command.
+		 */
+		if (bdp->cbd_sc &
+		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+			must_restart = 1;
+			cep->stats.tx_errors++;
+		}
+
+		cep->stats.tx_packets++;
+
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+			cep->stats.collisions++;
+
+		/* Free the sk buffer associated with this last transmit.
+		*/
+		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+		/* Update pointer to next buffer descriptor to be transmitted.
+		*/
+		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+			bdp = cep->tx_bd_base;
+		else
+			bdp++;
+
+		/* I don't know if we can be held off from processing these
+		 * interrupts for more than one frame time.  I really hope
+		 * not.  In such a case, we would now want to check the
+		 * currently available BD (cur_tx) and determine if any
+		 * buffers between the dirty_tx and cur_tx have also been
+		 * sent.  We would want to process anything in between that
+		 * does not have BD_ENET_TX_READY set.
+		 */
+
+		/* Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (!cep->tx_free++) {
+			if (netif_queue_stopped(dev)) {
+				netif_wake_queue(dev);
+			}
+		}
+
+		cep->dirty_tx = (cbd_t *)bdp;
+	    }
+
+	    if (must_restart) {
+		volatile cpm_cpm2_t *cp;
+
+		/* Some transmit errors cause the transmitter to shut
+		 * down.  We now issue a restart transmit.  Since the
+		 * errors close the BD and update the pointers, the restart
+		 * _should_ pick up without having to reset any of our
+		 * pointers either.
+		 */
+
+		cp = cpmp;
+		cp->cp_cpcr =
+		    mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+		    			CPM_CR_RESTART_TX) | CPM_CR_FLG;
+		while (cp->cp_cpcr & CPM_CR_FLG);
+	    }
+	    spin_unlock(&cep->lock);
+	}
+
+	/* Check for receive busy, i.e. packets coming but no place to
+	 * put them.
+	 */
+	if (int_events & SCCE_ENET_BSY)
+		cep->stats.rx_dropped++;
+
+	return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+scc_enet_rx(struct net_device *dev)
+{
+	struct	scc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	struct	sk_buff *skb;
+	ushort	pkt_len;
+
+	cep = (struct scc_enet_private *)dev->priv;
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = cep->cur_rx;
+
+for (;;) {
+	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+		break;
+
+#ifndef final_version
+	/* Since we have allocated space to hold a complete frame, both
+	 * the first and last indicators should be set.
+	 */
+	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+			printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+	/* Frame too long or too short.
+	*/
+	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+		cep->stats.rx_length_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		cep->stats.rx_frame_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
+		cep->stats.rx_crc_errors++;
+
+	/* Report late collisions as a frame error.
+	 * On this error, the BD is closed, but we don't know what we
+	 * have in the buffer.  So, just drop this frame on the floor.
+	 */
+	if (bdp->cbd_sc & BD_ENET_RX_CL) {
+		cep->stats.rx_frame_errors++;
+	}
+	else {
+
+		/* Process the incoming frame.
+		*/
+		cep->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		cep->stats.rx_bytes += pkt_len;
+
+		/* This does 16 byte alignment, much more than we need.
+		 * The packet length includes FCS, but we don't want to
+		 * include that when passing upstream as it messes up
+		 * bridging applications.
+		 */
+		skb = dev_alloc_skb(pkt_len-4);
+
+		if (skb == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			cep->stats.rx_dropped++;
+		}
+		else {
+			skb->dev = dev;
+			skb_put(skb,pkt_len-4);	/* Make room */
+			eth_copy_and_sum(skb,
+				(unsigned char *)__va(bdp->cbd_bufaddr),
+				pkt_len-4, 0);
+			skb->protocol=eth_type_trans(skb,dev);
+			netif_rx(skb);
+		}
+	}
+
+	/* Clear the status flags for this buffer.
+	*/
+	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+	/* Mark the buffer empty.
+	*/
+	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+	/* Update BD pointer to next entry.
+	*/
+	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+		bdp = cep->rx_bd_base;
+	else
+		bdp++;
+
+   }
+	cep->cur_rx = (cbd_t *)bdp;
+
+	return 0;
+}
+
+static int
+scc_enet_close(struct net_device *dev)
+{
+	/* Don't know what to do yet.
+	*/
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
+{
+	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+	return &cep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct	scc_enet_private *cep;
+	struct	dev_mc_list *dmi;
+	u_char	*mcptr, *tdptr;
+	volatile scc_enet_t *ep;
+	int	i, j;
+	cep = (struct scc_enet_private *)dev->priv;
+
+	/* Get pointer to SCC area in parameter RAM.
+	*/
+	ep = (scc_enet_t *)dev->base_addr;
+
+	if (dev->flags&IFF_PROMISC) {
+
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		cep->sccp->scc_psmr |= SCC_PSMR_PRO;
+	} else {
+
+		cep->sccp->scc_psmr &= ~SCC_PSMR_PRO;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			ep->sen_gaddr1 = 0xffff;
+			ep->sen_gaddr2 = 0xffff;
+			ep->sen_gaddr3 = 0xffff;
+			ep->sen_gaddr4 = 0xffff;
+		}
+		else {
+			/* Clear filter and add the addresses in the list.
+			*/
+			ep->sen_gaddr1 = 0;
+			ep->sen_gaddr2 = 0;
+			ep->sen_gaddr3 = 0;
+			ep->sen_gaddr4 = 0;
+
+			dmi = dev->mc_list;
+
+			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
+
+				/* Only support group multicast for now.
+				*/
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
+
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u_char *)dmi->dmi_addr + 5;
+				tdptr = (u_char *)&ep->sen_taddrh;
+				for (j=0; j<6; j++)
+					*tdptr++ = *mcptr--;
+
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
+						CPM_ENET_BLOCK, 0,
+						CPM_CR_SET_GADDR) | CPM_CR_FLG;
+				/* this delay is necessary here -- Cort */
+				udelay(10);
+				while (cpmp->cp_cpcr & CPM_CR_FLG);
+			}
+		}
+	}
+}
+
+/* Initialize the CPM Ethernet on SCC.
+ */
+int __init scc_enet_init(void)
+{
+	struct net_device *dev;
+	struct scc_enet_private *cep;
+	int i, j;
+	unsigned char	*eap;
+	unsigned long	mem_addr;
+	bd_t		*bd;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+	volatile	scc_t		*sccp;
+	volatile	scc_enet_t	*ep;
+	volatile	cpm2_map_t		*immap;
+	volatile	iop_cpm2_t	*io;
+
+	cp = cpmp;	/* Get pointer to Communication Processor */
+
+	immap = (cpm2_map_t *)CPM_MAP_ADDR;	/* and to internal registers */
+	io = &immap->im_ioport;
+
+	bd = (bd_t *)__res;
+
+	/* Allocate some private information.
+	*/
+	cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+	if (cep == NULL)
+		return -ENOMEM;
+
+	__clear_user(cep,sizeof(*cep));
+	spin_lock_init(&cep->lock);
+
+	/* Create an Ethernet device instance.
+	*/
+	dev = init_etherdev(0, 0);
+
+	/* Get pointer to SCC area in parameter RAM.
+	*/
+	ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
+
+	/* And another to the SCC register area.
+	*/
+	sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
+	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */
+
+	/* Disable receive and transmit in case someone left it running.
+	*/
+	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* Configure port C and D pins for SCC Ethernet.  This
+	 * won't work for all SCC possibilities....it will be
+	 * board/port specific.
+	 */
+	io->iop_pparc |=
+		(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+	io->iop_pdirc &=
+		~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+	io->iop_psorc &=
+		~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
+	io->iop_psorc |= PC_ENET_CLSN;
+
+	io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
+	io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
+	io->iop_pdird &= ~PD_ENET_RXD;
+	io->iop_psord |= PD_ENET_TXD;
+	io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
+
+	/* Configure Serial Interface clock routing.
+	 * First, clear all SCC bits to zero, then set the ones we want.
+	 */
+	immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
+	immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
+
+	/* Allocate space for the buffer descriptors in the DP ram.
+	 * These are relative offsets in the DP ram address space.
+	 * Initialize base addresses for the buffer descriptors.
+	 */
+	i = cpm2_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+	ep->sen_genscc.scc_rbase = i;
+	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+	i = cpm2_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+	ep->sen_genscc.scc_tbase = i;
+	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+	cep->tx_free = TX_RING_SIZE;
+	cep->cur_rx = cep->rx_bd_base;
+
+	ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	/* Set maximum bytes per receive buffer.
+	 * This appears to be an Ethernet frame size, not the buffer
+	 * fragment size.  It must be a multiple of four.
+	 */
+	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+
+	/* Set CRC preset and mask.
+	*/
+	ep->sen_cpres = 0xffffffff;
+	ep->sen_cmask = 0xdebb20e3;
+
+	ep->sen_crcec = 0;	/* CRC Error counter */
+	ep->sen_alec = 0;	/* alignment error counter */
+	ep->sen_disfc = 0;	/* discard frame counter */
+
+	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
+	ep->sen_retlim = 15;	/* Retry limit threshold */
+
+	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+
+	ep->sen_maxd1 = PKT_MAXBLR_SIZE;	/* maximum DMA1 length */
+	ep->sen_maxd2 = PKT_MAXBLR_SIZE;	/* maximum DMA2 length */
+
+	/* Clear hash tables.
+	*/
+	ep->sen_gaddr1 = 0;
+	ep->sen_gaddr2 = 0;
+	ep->sen_gaddr3 = 0;
+	ep->sen_gaddr4 = 0;
+	ep->sen_iaddr1 = 0;
+	ep->sen_iaddr2 = 0;
+	ep->sen_iaddr3 = 0;
+	ep->sen_iaddr4 = 0;
+
+	/* Set Ethernet station address.
+	 *
+	 * This is supplied in the board information structure, so we
+	 * copy that into the controller.
+	 */
+	eap = (unsigned char *)&(ep->sen_paddrh);
+	for (i=5; i>=0; i--)
+		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+
+	ep->sen_pper = 0;	/* 'cause the book says so */
+	ep->sen_taddrl = 0;	/* temp address (LSB) */
+	ep->sen_taddrm = 0;
+	ep->sen_taddrh = 0;	/* temp address (MSB) */
+
+	/* Now allocate the host memory pages and initialize the
+	 * buffer descriptors.
+	 */
+	bdp = cep->tx_bd_base;
+	for (i=0; i<TX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		bdp->cbd_sc = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	bdp = cep->rx_bd_base;
+	for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+
+		/* Allocate a page.
+		*/
+		mem_addr = __get_free_page(GFP_KERNEL);
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			mem_addr += CPM_ENET_RX_FRSIZE;
+			bdp++;
+		}
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	/* Let's re-initialize the channel now.  We have to do it later
+	 * than the manual describes because we have just now finished
+	 * the BD initialization.
+	 */
+	cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	cep->skb_cur = cep->skb_dirty = 0;
+
+	sccp->scc_scce = 0xffff;	/* Clear any pending events */
+
+	/* Enable interrupts for transmit error, complete frame
+	 * received, and any transmit buffer we have also set the
+	 * interrupt flag.
+	 */
+	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+	/* Install our interrupt handler.
+	*/
+	request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
+
+	/* Set GSMR_H to enable all normal operating modes.
+	 * Set GSMR_L to enable Ethernet to MC68160.
+	 */
+	sccp->scc_gsmrh = 0;
+	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+
+	/* Set sync/delimiters.
+	*/
+	sccp->scc_dsr = 0xd555;
+
+	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
+	 * start frame search 22 bit times after RENA.
+	 */
+	sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
+
+	/* It is now OK to enable the Ethernet transmitter.
+	 * Unfortunately, there are board implementation differences here.
+	 */
+	io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
+				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+	io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
+				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+	io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
+				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+	io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
+	io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
+
+	dev->base_addr = (unsigned long)ep;
+	dev->priv = cep;
+
+	/* The CPM Ethernet specific entries in the device structure. */
+	dev->open = scc_enet_open;
+	dev->hard_start_xmit = scc_enet_start_xmit;
+	dev->tx_timeout = scc_enet_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->stop = scc_enet_close;
+	dev->get_stats = scc_enet_get_stats;
+	dev->set_multicast_list = set_multicast_list;
+
+	/* And last, enable the transmit and receive processing.
+	*/
+	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	printk("%s: SCC ENET Version 0.1, ", dev->name);
+	for (i=0; i<5; i++)
+		printk("%02x:", dev->dev_addr[i]);
+	printk("%02x\n", dev->dev_addr[5]);
+
+	return 0;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/cpm2_io/fcc_enet.c linux-2.4.26-pre6/arch/ppc/cpm2_io/fcc_enet.c
--- linux-2.4.25/arch/ppc/cpm2_io/fcc_enet.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/cpm2_io/fcc_enet.c	2004-03-25 00:19:39.000000000 +0000
@@ -0,0 +1,2007 @@
+/*
+ * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
+ * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is a combination of the 8xx fec and
+ * 8260 SCC Ethernet drivers.  This version has some additional
+ * configuration options, which should probably be moved out of
+ * here.  This driver currently works for the EST SBC8260,
+ * SBS Diablo/BCM, Embedded Planet RPX6, TQM8260, and others.
+ *
+ * Right now, I am very watseful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.  Since this is a cache coherent processor and CPM,
+ * I could also preallocate SKB's and use them directly on the interface.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm2.h>
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT	(2*HZ)
+
+#ifdef	CONFIG_USE_MDIO
+/* Forward declarations of some structures to support different PHYs */
+
+typedef struct {
+	uint mii_data;
+	void (*funct)(uint mii_reg, struct net_device *dev);
+} phy_cmd_t;
+
+typedef struct {
+	uint id;
+	char *name;
+
+	const phy_cmd_t *config;
+	const phy_cmd_t *startup;
+	const phy_cmd_t *ack_int;
+	const phy_cmd_t *shutdown;
+} phy_info_t;
+
+/* Register definitions for the PHY. */
+
+#define MII_REG_CR          0  /* Control Register                         */
+#define MII_REG_SR          1  /* Status Register                          */
+#define MII_REG_PHYIR1      2  /* PHY Identification Register 1            */
+#define MII_REG_PHYIR2      3  /* PHY Identification Register 2            */
+#define MII_REG_ANAR        4  /* A-N Advertisement Register               */
+#define MII_REG_ANLPAR      5  /* A-N Link Partner Ability Register        */
+#define MII_REG_ANER        6  /* A-N Expansion Register                   */
+#define MII_REG_ANNPTR      7  /* A-N Next Page Transmit Register          */
+#define MII_REG_ANLPRNPR    8  /* A-N Link Partner Received Next Page Reg. */
+
+/* values for phy_status */
+
+#define PHY_CONF_ANE	0x0001  /* 1 auto-negotiation enabled */
+#define PHY_CONF_LOOP	0x0002  /* 1 loopback mode enabled */
+#define PHY_CONF_SPMASK	0x00f0  /* mask for speed */
+#define PHY_CONF_10HDX	0x0010  /* 10 Mbit half duplex supported */
+#define PHY_CONF_10FDX	0x0020  /* 10 Mbit full duplex supported */
+#define PHY_CONF_100HDX	0x0040  /* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX	0x0080  /* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK	0x0100  /* 1 up - 0 down */
+#define PHY_STAT_FAULT	0x0200  /* 1 remote fault */
+#define PHY_STAT_ANC	0x0400  /* 1 auto-negotiation complete	*/
+#define PHY_STAT_SPMASK	0xf000  /* mask for speed */
+#define PHY_STAT_10HDX	0x1000  /* 10 Mbit half duplex selected	*/
+#define PHY_STAT_10FDX	0x2000  /* 10 Mbit full duplex selected	*/
+#define PHY_STAT_100HDX	0x4000  /* 100 Mbit half duplex selected */
+#define PHY_STAT_100FDX	0x8000  /* 100 Mbit full duplex selected */
+#endif	/* CONFIG_USE_MDIO */
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+#define FCC_ENET_RX_PAGES	16
+#define FCC_ENET_RX_FRSIZE	2048
+#define FCC_ENET_RX_FRPPG	(PAGE_SIZE / FCC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
+#define TX_RING_SIZE		16	/* Must be power of two */
+#define TX_RING_MOD_MASK	15	/*   for this to work */
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+
+/* Maximum input DMA size.  Must be a should(?) be a multiple of 4.
+*/
+#define PKT_MAXDMA_SIZE		1520
+
+/* Maximum input buffer size.  Must be a multiple of 32.
+*/
+#define PKT_MAXBLR_SIZE		1536
+
+static int fcc_enet_open(struct net_device *dev);
+static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int fcc_enet_rx(struct net_device *dev);
+static	void fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int fcc_enet_close(struct net_device *dev);
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void fcc_restart(struct net_device *dev, int duplex);
+static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+
+/* These will be configurable for the FCC choice.
+ * Multiple ports can be configured.  There is little choice among the
+ * I/O pins to the PHY, except the clocks.  We will need some board
+ * dependent clock selection.
+ * Why in the hell did I put these inside #ifdef's?  I dunno, maybe to
+ * help show what pins are used for each device.
+ */
+
+/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL		((uint)0x00000001)
+#define PA1_CRS		((uint)0x00000002)
+#define PA1_TXER	((uint)0x00000004)
+#define PA1_TXEN	((uint)0x00000008)
+#define PA1_RXDV	((uint)0x00000010)
+#define PA1_RXER	((uint)0x00000020)
+#define PA1_TXDAT	((uint)0x00003c00)
+#define PA1_RXDAT	((uint)0x0003c000)
+#define PA1_PSORA0	(PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1	(PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+				PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0	(PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1	(PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+/* CLK12 is receive, CLK11 is transmit.  These are board specific.
+*/
+#ifdef CONFIG_ADS8272
+#define PC_F1RXCLK	((uint)0x00000400)
+#define PC_F1TXCLK	((uint)0x00000200)
+#define CMX1_CLK_ROUTE	((uint)0x36000000)
+#define CMX1_CLK_MASK	((uint)0xff000000)
+#else
+#define PC_F1RXCLK	((uint)0x00000800)
+#define PC_F1TXCLK	((uint)0x00000400)
+#define CMX1_CLK_ROUTE	((uint)0x3e000000)
+#define CMX1_CLK_MASK	((uint)0xff000000)
+#endif
+
+/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER	((uint)0x00000001)
+#define PB2_RXDV	((uint)0x00000002)
+#define PB2_TXEN	((uint)0x00000004)
+#define PB2_RXER	((uint)0x00000008)
+#define PB2_COL		((uint)0x00000010)
+#define PB2_CRS		((uint)0x00000020)
+#define PB2_TXDAT	((uint)0x000003c0)
+#define PB2_RXDAT	((uint)0x00003c00)
+#define PB2_PSORB0	(PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+				PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1	(PB2_TXEN)
+#define PB2_DIRB0	(PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1	(PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+/* CLK13 is receive, CLK14 is transmit.  These are board dependent.
+*/
+#ifdef CONFIG_ADS8272
+#define PC_F2RXCLK	((uint)0x00004000)
+#define PC_F2TXCLK	((uint)0x00008000)
+#define CMX2_CLK_ROUTE	((uint)0x00370000)
+#define CMX2_CLK_MASK	((uint)0x00ff0000)
+#else
+#define PC_F2RXCLK	((uint)0x00001000)
+#define PC_F2TXCLK	((uint)0x00002000)
+#define CMX2_CLK_ROUTE	((uint)0x00250000)
+#define CMX2_CLK_MASK	((uint)0x00ff0000)
+#endif
+
+/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV	((uint)0x00004000)
+#define PB3_RXER	((uint)0x00008000)
+#define PB3_TXER	((uint)0x00010000)
+#define PB3_TXEN	((uint)0x00020000)
+#define PB3_COL		((uint)0x00040000)
+#define PB3_CRS		((uint)0x00080000)
+#define PB3_TXDAT	((uint)0x0f000000)
+#define PB3_RXDAT	((uint)0x00f00000)
+#define PB3_PSORB0	(PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+				PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1	(0)
+#define PB3_DIRB0	(PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1	(PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+/* CLK15 is receive, CLK16 is transmit.  These are board dependent.
+*/
+#define PC_F3RXCLK	((uint)0x00004000)
+#define PC_F3TXCLK	((uint)0x00008000)
+#define CMX3_CLK_ROUTE	((uint)0x00003700)
+#define CMX3_CLK_MASK	((uint)0x0000ff00)
+
+/* MII status/control serial interface.
+*/
+#ifdef	CONFIG_TQM8260
+/* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
+#define PC_MDIO		((uint)0x00000002)
+#define PC_MDCK		((uint)0x00000001)
+#elif defined(CONFIG_ADS8272)
+#define PC_MDIO		((uint)0x00002000)
+#define PC_MDCK		((uint)0x00001000)
+#else
+#define PC_MDIO		((uint)0x00000004)
+#define PC_MDCK		((uint)0x00000020)
+#endif
+
+/* A table of information for supporting FCCs.  This does two things.
+ * First, we know how many FCCs we have and they are always externally
+ * numbered from zero.  Second, it holds control register and I/O
+ * information that could be different among board designs.
+ */
+typedef struct fcc_info {
+	uint	fc_fccnum;
+	uint	fc_cpmblock;
+	uint	fc_cpmpage;
+	uint	fc_proff;
+	uint	fc_interrupt;
+	uint	fc_trxclocks;
+	uint	fc_clockroute;
+	uint	fc_clockmask;
+	uint	fc_mdio;
+	uint	fc_mdck;
+} fcc_info_t;
+
+static fcc_info_t fcc_ports[] = {
+#ifdef CONFIG_FCC1_ENET
+	{ 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+		(PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
+# if defined(CONFIG_TQM8260) || defined (CONFIG_ADS8272)
+		PC_MDIO, PC_MDCK },
+# else
+		0x00000004, 0x00000100 },
+# endif
+#endif
+#ifdef CONFIG_FCC2_ENET
+	{ 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+		(PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
+# if defined(CONFIG_TQM8260) || defined (CONFIG_ADS8272)
+		PC_MDIO, PC_MDCK },
+# elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260)
+		0x00400000, 0x00200000 },
+# else
+		0x00000002, 0x00000080 },
+# endif
+#endif
+#ifdef CONFIG_FCC3_ENET
+	{ 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+		(PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
+# if defined(CONFIG_TQM8260) || defined (CONFIG_ADS8272)
+		PC_MDIO, PC_MDCK },
+# else
+		0x00000001, 0x00000040 },
+# endif
+#endif
+};
+
+/* The FCC buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fcc_enet_private {
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	ushort	skb_cur;
+	ushort	skb_dirty;
+
+	/* CPM dual port RAM relative addresses.
+	*/
+	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
+	cbd_t	*tx_bd_base;
+	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
+	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	volatile fcc_t	*fccp;
+	volatile fcc_enet_t	*ep;
+	struct	net_device_stats stats;
+	uint	tx_full;
+	spinlock_t lock;
+
+#ifdef	CONFIG_USE_MDIO
+	uint	phy_id;
+	uint	phy_id_done;
+	uint	phy_status;
+	phy_info_t	*phy;
+	struct tq_struct phy_task;
+
+	uint	sequence_done;
+
+	uint	phy_addr;
+#endif	/* CONFIG_USE_MDIO */
+
+	int	link;
+	int	old_link;
+	int	full_duplex;
+
+	fcc_info_t	*fip;
+};
+
+static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+	volatile cpm2_map_t *immap);
+static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
+static void init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
+	volatile cpm2_map_t *immap);
+static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+	volatile cpm2_map_t *immap);
+
+#ifdef	CONFIG_USE_MDIO
+static int	mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *));
+static uint	mii_send_receive(fcc_info_t *fip, uint cmd);
+
+static void	fcc_stop(struct net_device *dev);
+
+/* Make MII read/write commands for the FCC.
+*/
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | \
+						(VAL & 0xffff))
+#define mk_mii_end	0
+#endif	/* CONFIG_USE_MDIO */
+
+
+static int
+fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+	volatile cbd_t	*bdp;
+
+	if (!cep->link) {
+		/* Link is down or autonegotiation is in progress. */
+		return 1;
+	}
+
+	/* Fill in a Tx ring entry */
+	bdp = cep->cur_tx;
+
+#ifndef final_version
+	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since cep->tx_full should be set.
+		 */
+		printk("%s: tx queue full!.\n", dev->name);
+		return 1;
+	}
+#endif
+
+	/* Clear all of the status flags. */
+	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+	/* If the frame is short, tell CPM to pad it. */
+	if (skb->len <= ETH_ZLEN)
+		bdp->cbd_sc |= BD_ENET_TX_PAD;
+	else
+		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+	/* Set buffer length and buffer pointer. */
+	bdp->cbd_datlen = skb->len;
+	bdp->cbd_bufaddr = __pa(skb->data);
+
+	/* Save skb pointer. */
+	cep->tx_skbuff[cep->skb_cur] = skb;
+
+	cep->stats.tx_bytes += skb->len;
+	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+	spin_lock_irq(&cep->lock);
+
+	/* Send it on its way.  Tell CPM its ready, interrupt when done,
+	 * its the last BD of the frame, and to put the CRC on the end.
+	 */
+	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+#if 0
+	/* Errata says don't do this. */
+	cep->fccp->fcc_ftodr = 0x8000;
+#endif
+	dev->trans_start = jiffies;
+
+	/* If this was the last BD in the ring, start at the beginning again. */
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = cep->tx_bd_base;
+	else
+		bdp++;
+
+	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+		netif_stop_queue(dev);
+		cep->tx_full = 1;
+	}
+
+	cep->cur_tx = (cbd_t *)bdp;
+
+	spin_unlock_irq(&cep->lock);
+
+	return 0;
+}
+
+
+static void
+fcc_enet_timeout(struct net_device *dev)
+{
+	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+	printk("%s: transmit timed out.\n", dev->name);
+	cep->stats.tx_errors++;
+#ifndef final_version
+	{
+		int	i;
+		cbd_t	*bdp;
+		printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+		       cep->cur_tx, cep->tx_full ? " (full)" : "",
+		       cep->cur_rx);
+		bdp = cep->tx_bd_base;
+		printk(" Tx @base %p :\n", bdp);
+		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+		bdp = cep->rx_bd_base;
+		printk(" Rx @base %p :\n", bdp);
+		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+	}
+#endif
+	if (!cep->tx_full)
+		netif_wake_queue(dev);
+}
+
+/* The interrupt handler. */
+static void
+fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	net_device *dev = dev_id;
+	volatile struct	fcc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	ushort	int_events;
+	int	must_restart;
+
+	cep = (struct fcc_enet_private *)dev->priv;
+
+	/* Get the interrupt events that caused us to be here.
+	*/
+	int_events = cep->fccp->fcc_fcce;
+	cep->fccp->fcc_fcce = int_events;
+	must_restart = 0;
+
+	/* Handle receive event in its own function.
+	*/
+	if (int_events & FCC_ENET_RXF)
+		fcc_enet_rx(dev_id);
+
+	/* Check for a transmit error.  The manual is a little unclear
+	 * about this, so the debug code until I get it figured out.  It
+	 * appears that if TXE is set, then TXB is not set.  However,
+	 * if carrier sense is lost during frame transmission, the TXE
+	 * bit is set, "and continues the buffer transmission normally."
+	 * I don't know if "normally" implies TXB is set when the buffer
+	 * descriptor is closed.....trial and error :-).
+	 */
+
+	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	*/
+	if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) {
+	    spin_lock(&cep->lock);
+	    bdp = cep->dirty_tx;
+	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+		if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+		    break;
+
+		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
+			cep->stats.tx_heartbeat_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
+			cep->stats.tx_window_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
+			cep->stats.tx_aborted_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
+			cep->stats.tx_fifo_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
+			cep->stats.tx_carrier_errors++;
+
+
+		/* No heartbeat or Lost carrier are not really bad errors.
+		 * The others require a restart transmit command.
+		 */
+		if (bdp->cbd_sc &
+		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+			must_restart = 1;
+			cep->stats.tx_errors++;
+		}
+
+		cep->stats.tx_packets++;
+
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+			cep->stats.collisions++;
+
+		/* Free the sk buffer associated with this last transmit. */
+		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+		/* Update pointer to next buffer descriptor to be transmitted. */
+		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+			bdp = cep->tx_bd_base;
+		else
+			bdp++;
+
+		/* I don't know if we can be held off from processing these
+		 * interrupts for more than one frame time.  I really hope
+		 * not.  In such a case, we would now want to check the
+		 * currently available BD (cur_tx) and determine if any
+		 * buffers between the dirty_tx and cur_tx have also been
+		 * sent.  We would want to process anything in between that
+		 * does not have BD_ENET_TX_READY set.
+		 */
+
+		/* Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (cep->tx_full) {
+			cep->tx_full = 0;
+			if (netif_queue_stopped(dev)) {
+				netif_wake_queue(dev);
+			}
+		}
+
+		cep->dirty_tx = (cbd_t *)bdp;
+	    }
+
+	    if (must_restart) {
+		volatile cpm_cpm2_t *cp;
+
+		/* Some transmit errors cause the transmitter to shut
+		 * down.  We now issue a restart transmit.  Since the
+		 * errors close the BD and update the pointers, the restart
+		 * _should_ pick up without having to reset any of our
+		 * pointers either.  Also, To workaround 8260 device erratum 
+		 * CPM37, we must disable and then re-enable the transmitter
+		 * following a Late Collision, Underrun, or Retry Limit error.
+		 */
+		cep->fccp->fcc_gfmr &= ~FCC_GFMR_ENT;
+		udelay(10); /* wait a few microseconds just on principle */
+		cep->fccp->fcc_gfmr |=  FCC_GFMR_ENT;
+
+		cp = cpmp;
+		cp->cp_cpcr =
+		    mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
+		    		0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+		while (cp->cp_cpcr & CPM_CR_FLG);
+	    }
+	    spin_unlock(&cep->lock);
+	}
+
+	/* Check for receive busy, i.e. packets coming but no place to
+	 * put them.
+	 */
+	if (int_events & FCC_ENET_BSY) {
+		cep->stats.rx_dropped++;
+	}
+	return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+fcc_enet_rx(struct net_device *dev)
+{
+	struct	fcc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	struct	sk_buff *skb;
+	ushort	pkt_len;
+
+	cep = (struct fcc_enet_private *)dev->priv;
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = cep->cur_rx;
+
+for (;;) {
+	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+		break;
+
+#ifndef final_version
+	/* Since we have allocated space to hold a complete frame, both
+	 * the first and last indicators should be set.
+	 */
+	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+			printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+	/* Frame too long or too short. */
+	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+		cep->stats.rx_length_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		cep->stats.rx_frame_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CL)	/* Late Collision */
+		cep->stats.rx_frame_errors++;
+
+	if (!(bdp->cbd_sc &
+	      (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR
+	       | BD_ENET_RX_OV | BD_ENET_RX_CL)))
+	{
+		/* Process the incoming frame. */
+		cep->stats.rx_packets++;
+
+		/* Remove the FCS from the packet length. */
+		pkt_len = bdp->cbd_datlen - 4;
+		cep->stats.rx_bytes += pkt_len;
+
+		/* This does 16 byte alignment, much more than we need. */
+		skb = dev_alloc_skb(pkt_len);
+
+		if (skb == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			cep->stats.rx_dropped++;
+		}
+		else {
+			skb->dev = dev;
+			skb_put(skb,pkt_len);	/* Make room */
+			eth_copy_and_sum(skb,
+				(unsigned char *)__va(bdp->cbd_bufaddr),
+				pkt_len, 0);
+			skb->protocol=eth_type_trans(skb,dev);
+			netif_rx(skb);
+		}
+	}
+
+	/* Clear the status flags for this buffer. */
+	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+	/* Mark the buffer empty. */
+	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+	/* Update BD pointer to next entry. */
+	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+		bdp = cep->rx_bd_base;
+	else
+		bdp++;
+
+   }
+	cep->cur_rx = (cbd_t *)bdp;
+
+	return 0;
+}
+
+static int
+fcc_enet_close(struct net_device *dev)
+{
+	/* Don't know what to do yet. */
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
+{
+	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+	return &cep->stats;
+}
+
+#ifdef	CONFIG_USE_MDIO
+
+/* NOTE: Most of the following comes from the FEC driver for 860. The
+ * overall structure of MII code has been retained (as it's proved stable
+ * and well-tested), but actual transfer requests are processed "at once"
+ * instead of being queued (there's no interrupt-driven MII transfer
+ * mechanism, one has to toggle the data/clock bits manually).
+ */
+static int
+mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+{
+	struct fcc_enet_private *fep;
+	int		retval, tmp;
+
+	/* Add PHY address to register command. */
+	fep = dev->priv;
+	regval |= fep->phy_addr << 23;
+
+	retval = 0;
+
+	tmp = mii_send_receive(fep->fip, regval);
+	if (func)
+		func(tmp, dev);
+
+	return retval;
+}
+
+static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
+{
+	int k;
+
+	if(!c)
+		return;
+
+	for(k = 0; (c+k)->mii_data != mk_mii_end; k++)
+		mii_queue(dev, (c+k)->mii_data, (c+k)->funct);
+}
+
+static void mii_parse_sr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+
+	if (mii_reg & 0x0004)
+		s |= PHY_STAT_LINK;
+	if (mii_reg & 0x0010)
+		s |= PHY_STAT_FAULT;
+	if (mii_reg & 0x0020)
+		s |= PHY_STAT_ANC;
+
+	fep->phy_status = s;
+	fep->link = (s & PHY_STAT_LINK) ? 1 : 0;
+}
+
+static void mii_parse_cr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+
+	if (mii_reg & 0x1000)
+		s |= PHY_CONF_ANE;
+	if (mii_reg & 0x4000)
+		s |= PHY_CONF_LOOP;
+
+	fep->phy_status = s;
+}
+
+static void mii_parse_anar(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_CONF_SPMASK);
+
+	if (mii_reg & 0x0020)
+		s |= PHY_CONF_10HDX;
+	if (mii_reg & 0x0040)
+		s |= PHY_CONF_10FDX;
+	if (mii_reg & 0x0080)
+		s |= PHY_CONF_100HDX;
+	if (mii_reg & 0x00100)
+		s |= PHY_CONF_100FDX;
+
+	fep->phy_status = s;
+}
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT970 is used by many boards				     */
+
+#ifdef CONFIG_FCC_LXT970
+
+#define MII_LXT970_MIRROR    16  /* Mirror register           */
+#define MII_LXT970_IER       17  /* Interrupt Enable Register */
+#define MII_LXT970_ISR       18  /* Interrupt Status Register */
+#define MII_LXT970_CONFIG    19  /* Configuration Register    */
+#define MII_LXT970_CSR       20  /* Chip Status Register      */
+
+static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	if (mii_reg & 0x0800) {
+		if (mii_reg & 0x1000)
+			s |= PHY_STAT_100FDX;
+		else
+			s |= PHY_STAT_100HDX;
+	} else {
+		if (mii_reg & 0x1000)
+			s |= PHY_STAT_10FDX;
+		else
+			s |= PHY_STAT_10HDX;
+	}
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_lxt970 = {
+	0x07810000,
+	"LXT970",
+
+	(const phy_cmd_t []) {  /* config */
+#if 0
+//		{ mk_mii_write(MII_REG_ANAR, 0x0021), NULL },
+
+		/* Set default operation of 100-TX....for some reason
+		 * some of these bits are set on power up, which is wrong.
+		 */
+		{ mk_mii_write(MII_LXT970_CONFIG, 0), NULL },
+#endif
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+		/* read SR and ISR to acknowledge */
+
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_LXT970_ISR), NULL },
+
+		/* find out the current status */
+
+		{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards                  */
+
+#ifdef CONFIG_FCC_LXT971
+
+/* register definitions for the 971 */
+
+#define MII_LXT971_PCR       16  /* Port Control Register     */
+#define MII_LXT971_SR2       17  /* Status Register 2         */
+#define MII_LXT971_IER       18  /* Interrupt Enable Register */
+#define MII_LXT971_ISR       19  /* Interrupt Status Register */
+#define MII_LXT971_LCR       20  /* LED Control Register      */
+#define MII_LXT971_TCR       30  /* Transmit Control Register */
+
+/*
+ * I had some nice ideas of running the MDIO faster...
+ * The 971 should support 8MHz and I tried it, but things acted really
+ * weird, so 2.5 MHz ought to be enough for anyone...
+ */
+
+static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	if (mii_reg & 0x4000) {
+		if (mii_reg & 0x0200)
+			s |= PHY_STAT_100FDX;
+		else
+			s |= PHY_STAT_100HDX;
+	} else {
+		if (mii_reg & 0x0200)
+			s |= PHY_STAT_10FDX;
+		else
+			s |= PHY_STAT_10HDX;
+	}
+	if (mii_reg & 0x0008)
+		s |= PHY_STAT_FAULT;
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_lxt971 = {
+	0x0001378e,
+	"LXT971",
+
+	(const phy_cmd_t []) {  /* config */
+//		{ mk_mii_write(MII_REG_ANAR, 0x021), NULL }, /* 10  Mbps, HD */
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+
+		/* Somehow does the 971 tell me that the link is down
+		 * the first read after power-up.
+		 * read here to get a valid value in ack_int */
+
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+		/* find out the current status */
+
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
+
+		/* we only need to read ISR to acknowledge */
+
+		{ mk_mii_read(MII_LXT971_ISR), NULL },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF                  */
+
+#ifdef CONFIG_FCC_QS6612
+
+/* register definitions */
+
+#define MII_QS6612_MCR       17  /* Mode Control Register      */
+#define MII_QS6612_FTR       27  /* Factory Test Register      */
+#define MII_QS6612_MCO       28  /* Misc. Control Register     */
+#define MII_QS6612_ISR       29  /* Interrupt Source Register  */
+#define MII_QS6612_IMR       30  /* Interrupt Mask Register    */
+#define MII_QS6612_PCR       31  /* 100BaseTx PHY Control Reg. */
+
+static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	switch((mii_reg >> 2) & 7) {
+	case 1: s |= PHY_STAT_10HDX;  break;
+	case 2: s |= PHY_STAT_100HDX; break;
+	case 5: s |= PHY_STAT_10FDX;  break;
+	case 6: s |= PHY_STAT_100FDX; break;
+	}
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_qs6612 = {
+	0x00181440,
+	"QS6612",
+
+	(const phy_cmd_t []) {  /* config */
+//	{ mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10  Mbps */
+
+		/* The PHY powers up isolated on the RPX,
+		 * so send a command to allow operation.
+		 */
+
+		{ mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL },
+
+		/* parse cr and anar to get some info */
+
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+
+		/* we need to read ISR, SR and ANER to acknowledge */
+
+		{ mk_mii_read(MII_QS6612_ISR), NULL },
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_REG_ANER), NULL },
+
+		/* read pcr to get info */
+
+		{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+
+#endif /* CONFIG_FEC_QS6612 */
+
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9131 is used on the HYMOD board			     */
+
+#ifdef CONFIG_FCC_DM9131
+
+/* register definitions */
+
+#define MII_DM9131_ACR		16	/* Aux. Config Register		*/
+#define MII_DM9131_ACSR		17	/* Aux. Config/Status Register	*/
+#define MII_DM9131_10TCSR	18	/* 10BaseT Config/Status Reg.	*/
+#define MII_DM9131_INTR		21	/* Interrupt Register		*/
+#define MII_DM9131_RECR		22	/* Receive Error Counter Reg.	*/
+#define MII_DM9131_DISCR	23	/* Disconnect Counter Register	*/
+
+static void mii_parse_dm9131_acsr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	switch ((mii_reg >> 12) & 0xf) {
+	case 1: s |= PHY_STAT_10HDX;  break;
+	case 2: s |= PHY_STAT_10FDX;  break;
+	case 4: s |= PHY_STAT_100HDX; break;
+	case 8: s |= PHY_STAT_100FDX; break;
+	}
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_dm9131 = {
+	0x00181b80,
+	"DM9131",
+
+	(const phy_cmd_t []) {  /* config */
+		/* parse cr and anar to get some info */
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_DM9131_INTR, 0x0002), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+
+		/* we need to read INTR, SR and ANER to acknowledge */
+
+		{ mk_mii_read(MII_DM9131_INTR), NULL },
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_REG_ANER), NULL },
+
+		/* read acsr to get info */
+
+		{ mk_mii_read(MII_DM9131_ACSR), mii_parse_dm9131_acsr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_DM9131_INTR, 0x0f00), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+
+#endif /* CONFIG_FEC_DM9131 */
+
+
+static phy_info_t *phy_info[] = {
+
+#ifdef CONFIG_FCC_LXT970
+	&phy_info_lxt970,
+#endif /* CONFIG_FEC_LXT970 */
+
+#ifdef CONFIG_FCC_LXT971
+	&phy_info_lxt971,
+#endif /* CONFIG_FEC_LXT971 */
+
+#ifdef CONFIG_FCC_QS6612
+	&phy_info_qs6612,
+#endif /* CONFIG_FEC_QS6612 */
+
+#ifdef CONFIG_FCC_DM9131
+	&phy_info_dm9131,
+#endif /* CONFIG_FEC_DM9131 */
+
+	NULL
+};
+
+static void mii_display_status(struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	if (!fep->link && !fep->old_link) {
+		/* Link is still down - don't print anything */
+		return;
+	}
+
+	printk("%s: status: ", dev->name);
+
+	if (!fep->link) {
+		printk("link down");
+	} else {
+		printk("link up");
+
+		switch(s & PHY_STAT_SPMASK) {
+		case PHY_STAT_100FDX: printk(", 100 Mbps Full Duplex"); break;
+		case PHY_STAT_100HDX: printk(", 100 Mbps Half Duplex"); break;
+		case PHY_STAT_10FDX:  printk(", 10 Mbps Full Duplex");  break;
+		case PHY_STAT_10HDX:  printk(", 10 Mbps Half Duplex");  break;
+		default:
+			printk(", Unknown speed/duplex");
+		}
+
+		if (s & PHY_STAT_ANC)
+			printk(", auto-negotiation complete");
+	}
+
+	if (s & PHY_STAT_FAULT)
+		printk(", remote fault");
+
+	printk(".\n");
+}
+
+static void mii_display_config(struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	printk("%s: config: auto-negotiation ", dev->name);
+
+	if (s & PHY_CONF_ANE)
+		printk("on");
+	else
+		printk("off");
+
+	if (s & PHY_CONF_100FDX)
+		printk(", 100FDX");
+	if (s & PHY_CONF_100HDX)
+		printk(", 100HDX");
+	if (s & PHY_CONF_10FDX)
+		printk(", 10FDX");
+	if (s & PHY_CONF_10HDX)
+		printk(", 10HDX");
+	if (!(s & PHY_CONF_SPMASK))
+		printk(", No speed/duplex selected?");
+
+	if (s & PHY_CONF_LOOP)
+		printk(", loopback enabled");
+
+	printk(".\n");
+
+	fep->sequence_done = 1;
+}
+
+static void mii_relink(struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+	int duplex;
+
+	fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
+	mii_display_status(dev);
+	fep->old_link = fep->link;
+
+	if (fep->link) {
+		duplex = 0;
+		if (fep->phy_status
+		    & (PHY_STAT_100FDX | PHY_STAT_10FDX))
+			duplex = 1;
+		fcc_restart(dev, duplex);
+	} else {
+		fcc_stop(dev);
+	}
+}
+
+static void mii_queue_relink(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+
+	fep->phy_task.routine = (void *)mii_relink;
+	fep->phy_task.data = dev;
+	schedule_task(&fep->phy_task);
+}
+
+static void mii_queue_config(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+
+	fep->phy_task.routine = (void *)mii_display_config;
+	fep->phy_task.data = dev;
+	schedule_task(&fep->phy_task);
+}
+
+
+
+phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
+			       { mk_mii_end, } };
+phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
+			       { mk_mii_end, } };
+
+
+/* Read remainder of PHY ID.
+*/
+static void
+mii_discover_phy3(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep;
+	int	i;
+
+	fep = dev->priv;
+	fep->phy_id |= (mii_reg & 0xffff);
+
+	for(i = 0; phy_info[i]; i++)
+		if(phy_info[i]->id == (fep->phy_id >> 4))
+			break;
+
+	if(!phy_info[i])
+		panic("%s: PHY id 0x%08x is not supported!\n",
+		      dev->name, fep->phy_id);
+
+	fep->phy = phy_info[i];
+
+	printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",
+		dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);
+}
+
+/* Scan all of the MII PHY addresses looking for someone to respond
+ * with a valid ID.  This usually happens quickly.
+ */
+static void
+mii_discover_phy(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep;
+	uint	phytype;
+
+	fep = dev->priv;
+
+	if ((phytype = (mii_reg & 0xfff)) != 0xfff) {
+
+		/* Got first part of ID, now get remainder. */
+		fep->phy_id = phytype << 16;
+		mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3);
+	} else {
+		fep->phy_addr++;
+		if (fep->phy_addr < 32) {
+			mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+							mii_discover_phy);
+		} else {
+			printk("fec: No PHY device found.\n");
+		}
+	}
+}
+
+/* This interrupt occurs when the PHY detects a link change. */
+static void
+mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	net_device *dev = dev_id;
+	struct fcc_enet_private *fep = dev->priv;
+
+	mii_do_cmd(dev, fep->phy->ack_int);
+	mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
+}
+
+#endif	/* CONFIG_USE_MDIO */
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+	struct	fcc_enet_private *cep;
+	struct	dev_mc_list *dmi;
+	u_char	*mcptr, *tdptr;
+	volatile fcc_enet_t *ep;
+	int	i, j;
+
+	cep = (struct fcc_enet_private *)dev->priv;
+
+return;
+	/* Get pointer to FCC area in parameter RAM.
+	*/
+	ep = (fcc_enet_t *)dev->base_addr;
+
+	if (dev->flags&IFF_PROMISC) {
+
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
+	} else {
+
+		cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			ep->fen_gaddrh = 0xffffffff;
+			ep->fen_gaddrl = 0xffffffff;
+		}
+		else {
+			/* Clear filter and add the addresses in the list.
+			*/
+			ep->fen_gaddrh = 0;
+			ep->fen_gaddrl = 0;
+
+			dmi = dev->mc_list;
+
+			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
+
+				/* Only support group multicast for now.
+				*/
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
+
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u_char *)dmi->dmi_addr + 5;
+				tdptr = (u_char *)&ep->fen_taddrh;
+				for (j=0; j<6; j++)
+					*tdptr++ = *mcptr--;
+
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage,
+						cep->fip->fc_cpmblock, 0x0c,
+						CPM_CR_SET_GADDR) | CPM_CR_FLG;
+				udelay(10);
+				while (cpmp->cp_cpcr & CPM_CR_FLG);
+			}
+		}
+	}
+}
+
+
+/* Set the individual MAC address.
+ */
+int fcc_enet_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr= (struct sockaddr *) p;
+	struct fcc_enet_private *cep;
+	volatile fcc_enet_t *ep;
+	unsigned char *eap;
+	int i;
+
+	cep = (struct fcc_enet_private *)(dev->priv);
+	ep = cep->ep;
+	
+        if (netif_running(dev))
+                return -EBUSY;
+
+        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	
+	eap = (unsigned char *) &(ep->fen_paddrh);
+	for (i=5; i>=0; i--)
+		*eap++ = addr->sa_data[i];
+
+        return 0;
+}
+
+
+/* Initialize the CPM Ethernet on FCC.
+ */
+int __init fec_enet_init(void)
+{
+	struct net_device *dev;
+	struct fcc_enet_private *cep;
+	fcc_info_t	*fip;
+	int	i, np;
+	volatile	cpm2_map_t		*immap;
+	volatile	iop_cpm2_t	*io;
+
+	immap = (cpm2_map_t *)CPM_MAP_ADDR;	/* and to internal registers */
+	io = &immap->im_ioport;
+
+	np = sizeof(fcc_ports) / sizeof(fcc_info_t);
+	fip = fcc_ports;
+
+	while (np-- > 0) {
+
+		/* Allocate some private information.
+		*/
+		cep = (struct fcc_enet_private *)
+					kmalloc(sizeof(*cep), GFP_KERNEL);
+		if (cep == NULL)
+			return -ENOMEM;
+
+		__clear_user(cep,sizeof(*cep));
+		spin_lock_init(&cep->lock);
+		cep->fip = fip;
+
+		/* Create an Ethernet device instance.
+		*/
+		dev = init_etherdev(0, 0);
+		dev->priv = cep;
+
+		init_fcc_shutdown(fip, cep, immap);
+		init_fcc_ioports(fip, io, immap);
+		init_fcc_param(fip, dev, immap);
+
+		dev->base_addr = (unsigned long)(cep->ep);
+
+		/* The CPM Ethernet specific entries in the device
+		 * structure.
+		 */
+		dev->open = fcc_enet_open;
+		dev->hard_start_xmit = fcc_enet_start_xmit;
+		dev->tx_timeout = fcc_enet_timeout;
+		dev->watchdog_timeo = TX_TIMEOUT;
+		dev->stop = fcc_enet_close;
+		dev->get_stats = fcc_enet_get_stats;
+		dev->set_multicast_list = set_multicast_list;
+		dev->set_mac_address = fcc_enet_set_mac_address;
+
+		init_fcc_startup(fip, dev);
+
+		printk("%s: FCC ENET Version 0.3, ", dev->name);
+		for (i=0; i<5; i++)
+			printk("%02x:", dev->dev_addr[i]);
+		printk("%02x\n", dev->dev_addr[5]);
+
+#ifdef	CONFIG_USE_MDIO
+		/* Queue up command to detect the PHY and initialize the
+	 	* remainder of the interface.
+	 	*/
+		cep->phy_addr = 0;
+		mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
+#endif	/* CONFIG_USE_MDIO */
+
+		fip++;
+	}
+
+	return 0;
+}
+
+/* Make sure the device is shut down during initialization.
+*/
+static void __init
+init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+						volatile cpm2_map_t *immap)
+{
+	volatile	fcc_enet_t	*ep;
+	volatile	fcc_t		*fccp;
+
+	/* Get pointer to FCC area in parameter RAM.
+	*/
+	ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
+
+	/* And another to the FCC register area.
+	*/
+	fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
+	cep->fccp = fccp;		/* Keep the pointers handy */
+	cep->ep = ep;
+
+	/* Disable receive and transmit in case someone left it running.
+	*/
+	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* Initialize the I/O pins for the FCC Ethernet.
+*/
+static void __init
+init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
+						volatile cpm2_map_t *immap)
+{
+
+	/* FCC1 pins are on port A/C.  FCC2/3 are port B/C.
+	*/
+	if (fip->fc_proff == PROFF_FCC1) {
+		/* Configure port A and C pins for FCC1 Ethernet.
+		 */
+		io->iop_pdira &= ~PA1_DIRA0;
+		io->iop_pdira |= PA1_DIRA1;
+		io->iop_psora &= ~PA1_PSORA0;
+		io->iop_psora |= PA1_PSORA1;
+		io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
+	}
+	if (fip->fc_proff == PROFF_FCC2) {
+		/* Configure port B and C pins for FCC Ethernet.
+		 */
+		io->iop_pdirb &= ~PB2_DIRB0;
+		io->iop_pdirb |= PB2_DIRB1;
+		io->iop_psorb &= ~PB2_PSORB0;
+		io->iop_psorb |= PB2_PSORB1;
+		io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
+	}
+	if (fip->fc_proff == PROFF_FCC3) {
+		/* Configure port B and C pins for FCC Ethernet.
+		 */
+		io->iop_pdirb &= ~PB3_DIRB0;
+		io->iop_pdirb |= PB3_DIRB1;
+		io->iop_psorb &= ~PB3_PSORB0;
+		io->iop_psorb |= PB3_PSORB1;
+		io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
+	}
+
+	/* Port C has clocks......
+	*/
+	io->iop_psorc &= ~(fip->fc_trxclocks);
+	io->iop_pdirc &= ~(fip->fc_trxclocks);
+	io->iop_pparc |= fip->fc_trxclocks;
+
+#ifdef	CONFIG_USE_MDIO
+	/* ....and the MII serial clock/data.
+	*/
+	io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
+	io->iop_podrc &= ~(fip->fc_mdio | fip->fc_mdck);
+	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+	io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
+#endif	/* CONFIG_USE_MDIO */
+
+	/* Configure Serial Interface clock routing.
+	 * First, clear all FCC bits to zero,
+	 * then set the ones we want.
+	 */
+	immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
+	immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
+}
+
+static void __init
+init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+						volatile cpm2_map_t *immap)
+{
+	unsigned char	*eap;
+	unsigned long	mem_addr;
+	bd_t		*bd;
+	int		i, j;
+	struct		fcc_enet_private *cep;
+	volatile	fcc_enet_t	*ep;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+
+	cep = (struct fcc_enet_private *)(dev->priv);
+	ep = cep->ep;
+	cp = cpmp;
+
+	bd = (bd_t *)__res;
+
+	/* Zero the whole thing.....I must have missed some individually.
+	 * It works when I do this.
+	 */
+	memset((char *)ep, 0, sizeof(fcc_enet_t));
+
+	/* Allocate space for the buffer descriptors in the DP ram.
+	 * These are relative offsets in the DP ram address space.
+	 * Initialize base addresses for the buffer descriptors.
+	 */
+#if 0
+	/* I really want to do this, but for some reason it doesn't
+	 * work with the data cache enabled, so I allocate from the
+	 * main memory instead.
+	 */
+	i = cpm2_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_rbase = (uint)&immap->im_dprambase[i];
+	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+	i = cpm2_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_tbase = (uint)&immap->im_dprambase[i];
+	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+#else
+	cep->rx_bd_base = (cbd_t *)cpm2_hostalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
+	cep->tx_bd_base = (cbd_t *)cpm2_hostalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
+#endif
+
+	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+	cep->cur_rx = cep->rx_bd_base;
+
+	ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+	ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+
+	/* Set maximum bytes per receive buffer.
+	 * It must be a multiple of 32.
+	 */
+	ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+
+	/* Allocate space in the reserved FCC area of DPRAM for the
+	 * internal buffers.  No one uses this space (yet), so we
+	 * can do this.  Later, we will add resource management for
+	 * this area.
+	 */
+	mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
+	ep->fen_genfcc.fcc_riptr = mem_addr;
+	ep->fen_genfcc.fcc_tiptr = mem_addr+32;
+	ep->fen_padptr = mem_addr+64;
+	memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
+
+	ep->fen_genfcc.fcc_rbptr = 0;
+	ep->fen_genfcc.fcc_tbptr = 0;
+	ep->fen_genfcc.fcc_rcrc = 0;
+	ep->fen_genfcc.fcc_tcrc = 0;
+	ep->fen_genfcc.fcc_res1 = 0;
+	ep->fen_genfcc.fcc_res2 = 0;
+
+	ep->fen_camptr = 0;	/* CAM isn't used in this driver */
+
+	/* Set CRC preset and mask.
+	*/
+	ep->fen_cmask = 0xdebb20e3;
+	ep->fen_cpres = 0xffffffff;
+
+	ep->fen_crcec = 0;	/* CRC Error counter */
+	ep->fen_alec = 0;	/* alignment error counter */
+	ep->fen_disfc = 0;	/* discard frame counter */
+	ep->fen_retlim = 15;	/* Retry limit threshold */
+	ep->fen_pper = 0;	/* Normal persistence */
+
+	/* Clear hash filter tables.
+	*/
+	ep->fen_gaddrh = 0;
+	ep->fen_gaddrl = 0;
+	ep->fen_iaddrh = 0;
+	ep->fen_iaddrl = 0;
+
+	/* Clear the Out-of-sequence TxBD.
+	*/
+	ep->fen_tfcstat = 0;
+	ep->fen_tfclen = 0;
+	ep->fen_tfcptr = 0;
+
+	ep->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+	ep->fen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+
+	/* Set Ethernet station address.
+	 *
+	 * This is supplied in the board information structure, so we
+	 * copy that into the controller.
+	 * So, far we have only been given one Ethernet address. We make
+	 * it unique by toggling selected bits in the upper byte of the
+	 * non-static part of the address (for the second and third ports,
+	 * the first port uses the address supplied as is).
+	 */
+	eap = (unsigned char *)&(ep->fen_paddrh);
+	for (i=5; i>=0; i--) {
+
+/* 
+ * The EP8260 only uses FCC3, so we can safely give it the real
+ * MAC address.
+ */
+#ifndef CONFIG_RPX6
+		if (i == 3 && fip->fc_fccnum != 0) {
+			dev->dev_addr[i] = bd->bi_enetaddr[i];
+			dev->dev_addr[i] ^= (1 << (7 - fip->fc_fccnum));
+			*eap++ = dev->dev_addr[i];
+		}
+		else {
+			*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+		}
+#else
+		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+#endif
+	}
+
+	ep->fen_taddrh = 0;
+	ep->fen_taddrm = 0;
+	ep->fen_taddrl = 0;
+
+	ep->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length */
+	ep->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length */
+
+	/* Clear stat counters, in case we ever enable RMON.
+	*/
+	ep->fen_octc = 0;
+	ep->fen_colc = 0;
+	ep->fen_broc = 0;
+	ep->fen_mulc = 0;
+	ep->fen_uspc = 0;
+	ep->fen_frgc = 0;
+	ep->fen_ospc = 0;
+	ep->fen_jbrc = 0;
+	ep->fen_p64c = 0;
+	ep->fen_p65c = 0;
+	ep->fen_p128c = 0;
+	ep->fen_p256c = 0;
+	ep->fen_p512c = 0;
+	ep->fen_p1024c = 0;
+
+	ep->fen_rfthr = 0;	/* Suggested by manual */
+	ep->fen_rfcnt = 0;
+	ep->fen_cftype = 0;
+
+	/* Now allocate the host memory pages and initialize the
+	 * buffer descriptors.
+	 */
+	bdp = cep->tx_bd_base;
+	for (i=0; i<TX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		bdp->cbd_sc = 0;
+		bdp->cbd_datlen = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	bdp = cep->rx_bd_base;
+	for (i=0; i<FCC_ENET_RX_PAGES; i++) {
+
+		/* Allocate a page.
+		*/
+		mem_addr = __get_free_page(GFP_KERNEL);
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		for (j=0; j<FCC_ENET_RX_FRPPG; j++) {
+			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+			bdp->cbd_datlen = 0;
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			mem_addr += FCC_ENET_RX_FRSIZE;
+			bdp++;
+		}
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	/* Let's re-initialize the channel now.  We have to do it later
+	 * than the manual describes because we have just now finished
+	 * the BD initialization.
+	 */
+	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	cep->skb_cur = cep->skb_dirty = 0;
+}
+
+/* Let 'er rip.
+*/
+static void __init
+init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+{
+	volatile fcc_t	*fccp;
+	struct fcc_enet_private *cep;
+
+	cep = (struct fcc_enet_private *)(dev->priv);
+	fccp = cep->fccp;
+
+	fccp->fcc_fcce = 0xffff;	/* Clear any pending events */
+
+	/* Enable interrupts for transmit error, complete frame
+	 * received, and any transmit buffer we have also set the
+	 * interrupt flag.
+	 */
+	fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+	/* Install our interrupt handler.
+	*/
+	if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",
+				dev) < 0)
+		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+
+#ifdef	CONFIG_USE_MDIO
+	if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0,
+							"mii", dev) < 0)
+		printk("Can't get MII IRQ %d\n", fip->fc_interrupt);
+#endif	/* CONFIG_USE_MDIO */
+
+	/* Set GFMR to enable Ethernet operating mode.
+	 */
+	fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+	/* Set sync/delimiters.
+	*/
+	fccp->fcc_fdsr = 0xd555;
+
+	/* Set protocol specific processing mode for Ethernet.
+	 * This has to be adjusted for Full Duplex operation after we can
+	 * determine how to detect that.
+	 */
+	fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
+
+#ifdef CONFIG_PQ2ADS
+	/* Enable the PHY.
+	*/
+        *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;
+        *(volatile uint *)(BCSR_ADDR + 4) |=  BCSR1_FETH_RST;
+#endif
+
+#if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260)
+	/* start in full duplex mode, and negotiate speed
+	 */
+	fcc_restart (dev, 1);
+#else
+	/* start in half duplex mode
+	 */
+	fcc_restart (dev, 0);
+#endif
+}
+
+#ifdef	CONFIG_USE_MDIO
+/* MII command/status interface.
+ * I'm not going to describe all of the details.  You can find the
+ * protocol definition in many other places, including the data sheet
+ * of most PHY parts.
+ * I wonder what "they" were thinking (maybe weren't) when they leave
+ * the I2C in the CPM but I have to toggle these bits......
+ */
+
+#define FCC_PDATC_MDIO(bit)					\
+	if (bit)						\
+		io->iop_pdatc |= fip->fc_mdio;			\
+	else							\
+		io->iop_pdatc &= ~fip->fc_mdio;
+
+#define FCC_PDATC_MDC(bit)					\
+	if (bit)						\
+		io->iop_pdatc |= fip->fc_mdck;			\
+	else							\
+		io->iop_pdatc &= ~fip->fc_mdck;
+
+static uint
+mii_send_receive(fcc_info_t *fip, uint cmd)
+{
+	uint		retval;
+	int		read_op, i, off;
+	volatile	cpm2_map_t		*immap;
+	volatile	iop_cpm2_t	*io;
+
+	immap = (cpm2_map_t *)CPM_MAP_ADDR;
+	io = &immap->im_ioport;
+
+	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+
+	read_op = ((cmd & 0xf0000000) == 0x60000000);
+
+	/* Write preamble
+	 */
+	for (i = 0; i < 32; i++)
+	{
+		FCC_PDATC_MDC(0);
+		FCC_PDATC_MDIO(1);
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+	}
+
+	/* Write data
+	 */
+	for (i = 0, off = 31; i < (read_op ? 14 : 32); i++, --off)
+	{
+		FCC_PDATC_MDC(0);
+		FCC_PDATC_MDIO((cmd >> off) & 0x00000001);
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+	}
+
+	retval = cmd;
+
+	if (read_op)
+	{
+		retval >>= 16;
+
+		FCC_PDATC_MDC(0);
+		io->iop_pdirc &= ~fip->fc_mdio;
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+		FCC_PDATC_MDC(0);
+		udelay(1);
+
+		for (i = 0, off = 15; i < 16; i++, off--)
+		{
+			FCC_PDATC_MDC(1);
+			retval <<= 1;
+			if (io->iop_pdatc & fip->fc_mdio)
+				retval++;
+			udelay(1);
+			FCC_PDATC_MDC(0);
+			udelay(1);
+		}
+	}
+
+	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+
+	for (i = 0; i < 32; i++)
+	{
+		FCC_PDATC_MDC(0);
+		FCC_PDATC_MDIO(1);
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+	}
+
+	return retval;
+}
+
+static void
+fcc_stop(struct net_device *dev)
+{
+	volatile fcc_t	*fccp;
+	struct fcc_enet_private	*fcp;
+
+	fcp = (struct fcc_enet_private *)(dev->priv);
+	fccp = fcp->fccp;
+
+	/* Disable transmit/receive */
+	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+#endif	/* CONFIG_USE_MDIO */
+	
+static void
+fcc_restart(struct net_device *dev, int duplex)
+{
+	volatile fcc_t	*fccp;
+	struct fcc_enet_private	*fcp;
+
+	fcp = (struct fcc_enet_private *)(dev->priv);
+	fccp = fcp->fccp;
+
+	if (duplex)
+		fccp->fcc_fpsmr |= FCC_PSMR_FDE;
+	else
+		fccp->fcc_fpsmr &= ~FCC_PSMR_FDE;
+
+	/* Enable transmit/receive */
+	fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;
+}
+
+static int
+fcc_enet_open(struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+
+#ifdef	CONFIG_USE_MDIO
+	fep->sequence_done = 0;
+	fep->link = 0;
+
+	if (fep->phy) {
+		mii_do_cmd(dev, fep->phy->ack_int);
+		mii_do_cmd(dev, fep->phy->config);
+		mii_do_cmd(dev, phy_cmd_config);  /* display configuration */
+		while(!fep->sequence_done)
+			schedule();
+
+		mii_do_cmd(dev, fep->phy->startup);
+		netif_start_queue(dev);
+		return 0;		/* Success */
+	}
+	return -ENODEV;		/* No PHY we understand */
+#else
+	fep->link = 1;
+	netif_start_queue(dev);
+	return 0;					/* Always succeed */
+#endif	/* CONFIG_USE_MDIO */
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/cpm2_io/uart.c linux-2.4.26-pre6/arch/ppc/cpm2_io/uart.c
--- linux-2.4.25/arch/ppc/cpm2_io/uart.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/cpm2_io/uart.c	2004-03-25 00:17:24.000000000 +0000
@@ -0,0 +1,3160 @@
+/*
+ *  UART driver for MPC8260 CPM SCC or SMC
+ *  Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *  Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
+ *	2.3.99 updates
+ *
+ * I used the 8xx uart.c driver as the framework for this driver.
+ * The original code was written for the EST8260 board.  I tried to make
+ * it generic, but there may be some assumptions in the structures that
+ * have to be fixed later.
+ *
+ * The 8xx and 8260 are similar, but not identical.  Over time we
+ * could probably merge these two drivers.
+ * To save porting time, I did not bother to change any object names
+ * that are not accessed outside of this file.
+ * It still needs lots of work........When it was easy, I included code
+ * to support the SCCs.
+ * Only the SCCs support modem control, so that is not complete either.
+ *
+ * This module exports the following rs232 io functions:
+ *
+ *	int rs_8xx_init(void);
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
+
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+
+/* SCC Console configuration.  Not quite finished.  The SCC_CONSOLE
+ * should be the number of the SCC to use, but only SCC1 will
+ * work at this time.
+ */
+#ifdef CONFIG_SCC_CONSOLE
+#define SCC_CONSOLE 1
+#endif
+
+/* this defines the index into rs_table for the port to use
+*/
+#ifndef CONFIG_SERIAL_CONSOLE_PORT
+#define CONFIG_SERIAL_CONSOLE_PORT	0
+#endif
+#endif
+#define CONFIG_SERIAL_CONSOLE_PORT	0
+
+#define TX_WAKEUP	ASYNC_SHARE_IRQ
+
+static char *serial_name = "CPM UART driver";
+static char *serial_version = "0.01";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+static int serial_console_setup(struct console *co, char *options);
+
+static void serial_console_write(struct console *c, const char *s,
+		                                unsigned count);
+static kdev_t serial_console_device(struct console *c);
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
+/*
+ * Serial driver configuration section.  Here are the various options:
+ */
+#define SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO
+#define SERIAL_DO_RESTART
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+
+#define _INLINE_ inline
+
+#define DBG_CNT(s)
+
+/* We overload some of the items in the data structure to meet our
+ * needs.  For example, the port address is the CPM parameter ram
+ * offset for the SCC or SMC.  The maximum number of ports is 4 SCCs and
+ * 2 SMCs.  The "hub6" field is used to indicate the channel number, with
+ * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs.
+ * Since these ports are so versatile, I don't yet have a strategy for
+ * their management.  For example, SCC1 is used for Ethernet.  Right
+ * now, just don't put them in the table.  Of course, right now I just
+ * want the SMC to work as a uart :-)..
+ * The "type" field is currently set to 0, for PORT_UNKNOWN.  It is
+ * not currently used.  I should probably use it to indicate the port
+ * type of CMS or SCC.
+ * The SMCs do not support any modem control signals.
+ */
+#define smc_scc_num	hub6
+
+/* The choice of serial port to use for KGDB.  If the system has
+ * two ports, you can use one for console and one for KGDB (which
+ * doesn't make sense to me, but people asked for it).
+ */
+#ifdef CONFIG_KGDB_TTYS1
+#define KGDB_SER_IDX 1		/* SCC2/SMC2 */
+#else
+#define KGDB_SER_IDX 0		/* SCC1/SMC1 */
+#endif
+
+#ifndef SCC_CONSOLE
+
+/* SMC2 is sometimes used for low performance TDM interfaces.  Define
+ * this as 1 if you want SMC2 as a serial port UART managed by this driver.
+ * Define this as 0 if you wish to use SMC2 for something else.
+ */
+#define USE_SMC2 1
+
+/* Define SCC to ttySx mapping.
+*/
+#define SCC_NUM_BASE	(USE_SMC2 + 1)	/* SCC base tty "number" */
+
+/* Define which SCC is the first one to use for a serial port.  These
+ * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
+ * for Ethernet, and the first available SCC for serial UART is SCC2.
+ * NOTE:  IF YOU CHANGE THIS, you have to change the PROFF_xxx and
+ * interrupt vectors in the table below to match.
+ */
+#define SCC_IDX_BASE	1	/* table index */
+
+static struct serial_state rs_table[] = {
+	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
+	{ 0,     0, PROFF_SMC1, SIU_INT_SMC1,   0,    0 },    /* SMC1 ttyS0 */
+#if USE_SMC2
+	{ 0,     0, PROFF_SMC2, SIU_INT_SMC2,   0,    1 },    /* SMC2 ttyS1 */
+#endif
+#ifndef CONFIG_SCC1_ENET
+	{ 0,     0, PROFF_SCC1, SIU_INT_SCC1,   0, SCC_NUM_BASE},    /* SCC1 ttyS2 */
+#endif
+#ifndef CONFIG_SCC2_ENET
+	{ 0,     0, PROFF_SCC2, SIU_INT_SCC2,   0, SCC_NUM_BASE + 1},    /* SCC2 ttyS3 */
+#endif
+};
+
+#else /* SCC_CONSOLE */
+#define SCC_NUM_BASE	0	/* SCC base tty "number" */
+#define SCC_IDX_BASE	0	/* table index */
+static struct serial_state rs_table[] = {
+	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
+	{ 0,     0, PROFF_SCC1, SIU_INT_SCC1,   0, SCC_NUM_BASE},    /* SCC1 ttyS2 */
+	{ 0,     0, PROFF_SCC2, SIU_INT_SCC2,   0, SCC_NUM_BASE + 1},    /* SCC2 ttyS3 */
+};
+#endif /* SCC_CONSOLE */
+
+#define PORT_NUM(P)	(((P) < (SCC_NUM_BASE)) ? (P) : (P)-(SCC_NUM_BASE))
+
+#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
+
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+/* The number of buffer descriptors and their sizes.
+*/
+#define RX_NUM_FIFO	4
+#define RX_BUF_SIZE	32
+#define TX_NUM_FIFO	4
+#define TX_BUF_SIZE	32
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/* The async_struct in serial.h does not really give us what we
+ * need, so define our own here.
+ */
+typedef struct serial_info {
+	int			magic;
+	int			flags;
+	struct serial_state	*state;
+	struct tty_struct 	*tty;
+	int			read_status_mask;
+	int			ignore_status_mask;
+	int			timeout;
+	int			line;
+	int			x_char;	/* xon/xoff character */
+	int			close_delay;
+	unsigned short		closing_wait;
+	unsigned short		closing_wait2;
+	unsigned long		event;
+	unsigned long		last_active;
+	int			blocked_open; /* # of blocked opens */
+	long			session; /* Session of opening process */
+	long			pgrp; /* pgrp of opening process */
+	struct tq_struct	tqueue;
+	struct tq_struct	tqueue_hangup;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+
+	/* CPM Buffer Descriptor pointers.
+	*/
+	cbd_t			*rx_bd_base;
+	cbd_t			*rx_cur;
+	cbd_t			*tx_bd_base;
+	cbd_t			*tx_cur;
+} ser_info_t;
+
+static struct console sercons = {
+        name:           "ttyS",
+        write:          serial_console_write,
+        device:         serial_console_device,
+        setup:          serial_console_setup,
+        flags:          CON_PRINTBUFFER,
+        index:          CONFIG_SERIAL_CONSOLE_PORT,
+};
+
+
+static void change_speed(ser_info_t *info);
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
+
+static inline int serial_paranoia_check(ser_info_t *info,
+					kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null async_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, kdevname(device), routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, kdevname(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts,
+ * indexed by the termio value.  The generic CPM functions are responsible
+ * for setting and assigning baud rate generators for us.
+ */
+static int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_stop(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int	idx;
+	unsigned long flags;
+	volatile scc_t	*sccp;
+	volatile smc_t	*smcp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+
+	save_flags(flags); cli();
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+		smcp->smc_smcm &= ~SMCM_TX;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm &= ~UART_SCCM_TX;
+	}
+	restore_flags(flags);
+}
+
+static void rs_8xx_start(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int	idx;
+	unsigned long flags;
+	volatile scc_t	*sccp;
+	volatile smc_t	*smcp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+
+	save_flags(flags); cli();
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+		smcp->smc_smcm |= SMCM_TX;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm |= UART_SCCM_TX;
+	}
+	restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(ser_info_t *info,
+				  int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned char ch, *cp;
+	/*int	ignored = 0;*/
+	int	i;
+	ushort	status;
+	struct	async_icount *icount;
+	volatile cbd_t	*bdp;
+
+	icount = &info->state->icount;
+
+	/* Just loop through the closed BDs and copy the characters into
+	 * the buffer.
+	 */
+	bdp = info->rx_cur;
+	for (;;) {
+		if (bdp->cbd_sc & BD_SC_EMPTY)	/* If this one is empty */
+			break;			/*   we are all done */
+
+		/* The read status mask tell us what we should do with
+		 * incoming characters, especially if errors occur.
+		 * One special case is the use of BD_SC_EMPTY.  If
+		 * this is not set, we are supposed to be ignoring
+		 * inputs.  In this case, just mark the buffer empty and
+		 * continue.
+		if (!(info->read_status_mask & BD_SC_EMPTY)) {
+			bdp->cbd_sc |= BD_SC_EMPTY;
+			bdp->cbd_sc &=
+				~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+			if (bdp->cbd_sc & BD_SC_WRAP)
+				bdp = info->rx_bd_base;
+			else
+				bdp++;
+			continue;
+		}
+		 */
+
+		/* Get the number of characters and the buffer pointer.
+		*/
+		i = bdp->cbd_datlen;
+		cp = (unsigned char *)__va(bdp->cbd_bufaddr);
+		status = bdp->cbd_sc;
+#ifdef CONFIG_KGDB
+		if (info->state->smc_scc_num == KGDB_SER_IDX &&
+				(*cp == 0x03 || *cp == '$')) {
+			breakpoint();
+			return;
+		}
+#endif
+
+		/* Check to see if there is room in the tty buffer for
+		 * the characters in our BD buffer.  If not, we exit
+		 * now, leaving the BD with the characters.  We'll pick
+		 * them up again on the next receive interrupt (which could
+		 * be a timeout).
+		 */
+		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
+			break;
+
+		while (i-- > 0) {
+			ch = *cp++;
+			*tty->flip.char_buf_ptr = ch;
+			icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+			printk("DR%02x:%02x...", ch, *status);
+#endif
+			*tty->flip.flag_buf_ptr = 0;
+			if (status & (BD_SC_BR | BD_SC_FR |
+				       BD_SC_PR | BD_SC_OV)) {
+				/*
+				 * For statistics only
+				 */
+				if (status & BD_SC_BR)
+					icount->brk++;
+				else if (status & BD_SC_PR)
+					icount->parity++;
+				else if (status & BD_SC_FR)
+					icount->frame++;
+				if (status & BD_SC_OV)
+					icount->overrun++;
+
+				/*
+				 * Now check to see if character should be
+				 * ignored, and mask off conditions which
+				 * should be ignored.
+				if (status & info->ignore_status_mask) {
+					if (++ignored > 100)
+						break;
+					continue;
+				}
+				 */
+				status &= info->read_status_mask;
+
+				if (status & (BD_SC_BR)) {
+#ifdef SERIAL_DEBUG_INTR
+					printk("handling break....");
+#endif
+					*tty->flip.flag_buf_ptr = TTY_BREAK;
+					if (info->flags & ASYNC_SAK)
+						do_SAK(tty);
+				} else if (status & BD_SC_PR)
+					*tty->flip.flag_buf_ptr = TTY_PARITY;
+				else if (status & BD_SC_FR)
+					*tty->flip.flag_buf_ptr = TTY_FRAME;
+				if (status & BD_SC_OV) {
+					/*
+					 * Overrun is special, since it's
+					 * reported immediately, and doesn't
+					 * affect the current character
+					 */
+					if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+						tty->flip.count++;
+						tty->flip.flag_buf_ptr++;
+						tty->flip.char_buf_ptr++;
+						*tty->flip.flag_buf_ptr =
+								TTY_OVERRUN;
+					}
+				}
+			}
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+			if (break_pressed && info->line == sercons.index) {
+				if (ch != 0 && time_before(jiffies,
+							break_pressed + HZ*5)) {
+					handle_sysrq(ch, regs, NULL, NULL);
+					break_pressed = 0;
+					goto ignore_char;
+				} else
+					break_pressed = 0;
+			}
+#endif
+			
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				break;
+
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	ignore_char:
+#endif
+
+		/* This BD is ready to be used again.  Clear status.
+		 * Get next BD.
+		 */
+		bdp->cbd_sc |= BD_SC_EMPTY;
+		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = info->rx_bd_base;
+		else
+			bdp++;
+	}
+
+	info->rx_cur = (cbd_t *)bdp;
+
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+
+	info->state->icount.brk++;
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	if (info->line == sercons.index) {
+		if (!break_pressed) {
+			break_pressed = jiffies;
+			return;
+		} else
+			break_pressed = 0;
+	}
+#endif
+
+	/* Check to see if there is room in the tty buffer for
+	 * the break.  If not, we exit now, losing the break.  FIXME
+	 */
+	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
+		return;
+	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
+	*(tty->flip.char_buf_ptr++) = 0;
+	tty->flip.count++;
+
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
+{
+
+	if (info->flags & TX_WAKEUP) {
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+	}
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+}
+
+#ifdef notdef
+	/* I need to do this for the SCCs, so it is left as a reminder.
+	*/
+static _INLINE_ void check_modem_status(struct async_struct *info)
+{
+	int	status;
+	struct	async_icount *icount;
+
+	status = serial_in(info, UART_MSR);
+
+	if (status & UART_MSR_ANY_DELTA) {
+		icount = &info->state->icount;
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			icount->rng++;
+		if (status & UART_MSR_DDSR)
+			icount->dsr++;
+		if (status & UART_MSR_DDCD) {
+			icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+			if ((info->flags & ASYNC_HARDPPS_CD) &&
+			    (status & UART_MSR_DCD))
+				hardpps();
+#endif
+		}
+		if (status & UART_MSR_DCTS)
+			icount->cts++;
+		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttys%d CD now %s...", info->line,
+		       (status & UART_MSR_DCD) ? "on" : "off");
+#endif
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&info->open_wait);
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("scheduling hangup...");
+#endif
+			MOD_INC_USE_COUNT;
+			if (schedule_task(&info->tqueue_hangup) == 0)
+				MOD_DEC_USE_COUNT;
+		}
+	}
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+			}
+		}
+	}
+}
+#endif
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+static void rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	u_char	events;
+	int	idx;
+	ser_info_t *info;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	info = (ser_info_t *)dev_id;
+
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+		events = smcp->smc_smce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
+		if (events & SMCM_RX)
+			receive_chars(info, regs);
+		if (events & SMCM_TX)
+			transmit_chars(info, regs);
+		smcp->smc_smce = events;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		events = sccp->scc_scce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
+		if (events & SCCM_RX)
+			receive_chars(info, regs);
+		if (events & SCCM_TX)
+			transmit_chars(info, regs);
+		sccp->scc_scce = events;
+	}
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("rs_interrupt_single(%d, %x)...",
+					info->state->smc_scc_num, events);
+#endif
+#ifdef modem_control
+	check_modem_status(info);
+#endif
+	info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+	run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+	ser_info_t	*info = (ser_info_t *) private_;
+	struct tty_struct	*tty;
+
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+}
+
+/*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred.  The path of
+ * hangup processing is:
+ *
+ * 	serial interrupt routine -> (scheduler tqueue) ->
+ * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ *
+ */
+static void do_serial_hangup(void *private_)
+{
+	struct async_struct	*info = (struct async_struct *) private_;
+	struct tty_struct	*tty;
+
+	tty = info->tty;
+	if (tty)
+		tty_hangup(tty);
+	MOD_DEC_USE_COUNT;
+}
+
+/*static void rs_8xx_timer(void)
+{
+	printk("rs_8xx_timer\n");
+}*/
+
+
+static int startup(ser_info_t *info)
+{
+	unsigned long flags;
+	int	retval=0;
+	int	idx;
+	struct serial_state *state= info->state;
+	volatile smc_t		*smcp;
+	volatile scc_t		*sccp;
+	volatile smc_uart_t	*up;
+	volatile scc_uart_t	*scup;
+
+
+	save_flags(flags); cli();
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		goto errout;
+	}
+
+#ifdef maybe
+	if (!state->port || !state->type) {
+		if (info->tty)
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		goto errout;
+	}
+#endif
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+#endif
+
+
+#ifdef modem_control
+	info->MCR = 0;
+	if (info->tty->termios->c_cflag & CBAUD)
+		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+#endif
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(info);
+
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+
+		/* Enable interrupts and I/O.
+		*/
+		smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+		smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+
+		/* We can tune the buffer length and idle characters
+		 * to take advantage of the entire incoming buffer size.
+		 * If mrblr is something other than 1, maxidl has to be
+		 * non-zero or we never get an interrupt.  The maxidl
+		 * is the number of character times we wait after reception
+		 * of the last character before we decide no more characters
+		 * are coming.
+		 */
+		up = (smc_uart_t *)&cpm2_immr->im_dprambase[state->port];
+#if 0
+		up->smc_mrblr = 1;	/* receive buffer length */
+		up->smc_maxidl = 0;	/* wait forever for next char */
+#else
+		up->smc_mrblr = RX_BUF_SIZE;
+		up->smc_maxidl = RX_BUF_SIZE;
+#endif
+		up->smc_brkcr = 1;	/* number of break chars */
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		scup = (scc_uart_t *)&cpm2_immr->im_dprambase[state->port];
+#if 0
+		scup->scc_genscc.scc_mrblr = 1;	/* receive buffer length */
+		scup->scc_maxidl = 0;	/* wait forever for next char */
+#else
+		scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+		scup->scc_maxidl = RX_BUF_SIZE;
+#endif
+
+		sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
+		sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	}
+
+	info->flags |= ASYNC_INITIALIZED;
+	restore_flags(flags);
+	return 0;
+
+errout:
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(ser_info_t * info)
+{
+	unsigned long	flags;
+	struct serial_state *state;
+	int		idx;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("Shutting down serial port %d (irq %d)....", info->line,
+	       state->irq);
+#endif
+
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+
+		/* Disable interrupts and I/O.
+		*/
+		smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+#ifdef CONFIG_SERIAL_CONSOLE
+		/* We can't disable the transmitter if this is the
+		 * system console.
+		 */
+		if (idx != CONFIG_SERIAL_CONSOLE_PORT)
+#endif
+			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+#ifdef CONFIG_SERIAL_CONSOLE
+		if (idx != CONFIG_SERIAL_CONSOLE_PORT)
+			sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+	}
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(ser_info_t *info)
+{
+	int	baud_rate;
+	unsigned cflag, cval, scval, prev_mode;
+	int	i, bits, sbits, idx;
+	unsigned long	flags;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+
+	/* Character length programmed into the mode register is the
+	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+	 * 1 or 2 stop bits, minus 1.
+	 * The value 'bits' counts this for us.
+	 */
+	cval = 0;
+	scval = 0;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	      case CS5: bits = 5; break;
+	      case CS6: bits = 6; break;
+	      case CS7: bits = 7; break;
+	      case CS8: bits = 8; break;
+	      /* Never happens, but GCC is too dumb to figure it out */
+	      default:  bits = 8; break;
+	}
+	sbits = bits - 5;
+
+	if (cflag & CSTOPB) {
+		cval |= SMCMR_SL;	/* Two stops */
+		scval |= SCU_PSMR_SL;
+		bits++;
+	}
+	if (cflag & PARENB) {
+		cval |= SMCMR_PEN;
+		scval |= SCU_PSMR_PEN;
+		bits++;
+	}
+	if (!(cflag & PARODD)) {
+		cval |= SMCMR_PM_EVEN;
+		scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);
+	}
+
+	/* Determine divisor based on baud rate */
+	i = cflag & CBAUD;
+	if (i >= (sizeof(baud_table)/sizeof(int)))
+		baud_rate = 9600;
+	else
+		baud_rate = baud_table[i];
+
+	info->timeout = (TX_BUF_SIZE*HZ*bits);
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+#ifdef modem_control
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	if (info->flags & ASYNC_HARDPPS_CD)
+		info->IER |= UART_IER_MSI;
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+	} else
+		info->flags &= ~ASYNC_CTS_FLOW;
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else {
+		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	serial_out(info, UART_IER, info->IER);
+#endif
+
+	/*
+	 * Set up parity check flag
+	 */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= BD_SC_FR | BD_SC_PR;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= BD_SC_BR;
+
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(info->tty))
+		info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= BD_SC_BR;
+		/*
+		 * If we're ignore parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty))
+			info->ignore_status_mask |= BD_SC_OV;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		info->read_status_mask &= ~BD_SC_EMPTY;
+	save_flags(flags); cli();
+
+	/* Start bit has not been added (so don't, because we would just
+	 * subtract it later), and we need to add one for the number of
+	 * stops bits (there is always at least one).
+	 */
+	bits++;
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+
+		/* Set the mode register.  We want to keep a copy of the
+		 * enables, because we want to put them back if they were
+		 * present.
+		 */
+		prev_mode = smcp->smc_smcmr & (SMCMR_REN | SMCMR_TEN);
+		smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART
+			| prev_mode;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_psmr = (sbits << 12) | scval;
+	}
+
+	cpm2_setbrg(info->state->smc_scc_num, baud_rate);
+
+	restore_flags(flags);
+}
+
+static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	volatile cbd_t	*bdp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+		return;
+
+	if (!tty)
+		return;
+
+	bdp = info->tx_cur;
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	*((char *)__va(bdp->cbd_bufaddr)) = ch;
+	bdp->cbd_datlen = 1;
+	bdp->cbd_sc |= BD_SC_READY;
+
+	/* Get next BD.
+	*/
+	if (bdp->cbd_sc & BD_SC_WRAP)
+		bdp = info->tx_bd_base;
+	else
+		bdp++;
+
+	info->tx_cur = (cbd_t *)bdp;
+
+}
+
+static int rs_8xx_write(struct tty_struct * tty, int from_user,
+		    const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	volatile cbd_t *bdp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_write"))
+		return 0;
+
+	if (!tty)
+		return 0;
+
+	bdp = info->tx_cur;
+
+	while (1) {
+		c = MIN(count, TX_BUF_SIZE);
+
+		if (c <= 0)
+			break;
+
+		if (bdp->cbd_sc & BD_SC_READY) {
+			info->flags |= TX_WAKEUP;
+			break;
+		}
+
+		if (from_user) {
+			if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+		} else {
+			memcpy(__va(bdp->cbd_bufaddr), buf, c);
+		}
+
+		bdp->cbd_datlen = c;
+		bdp->cbd_sc |= BD_SC_READY;
+
+		buf += c;
+		count -= c;
+		ret += c;
+
+		/* Get next BD.
+		*/
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = info->tx_bd_base;
+		else
+			bdp++;
+		info->tx_cur = (cbd_t *)bdp;
+	}
+	return ret;
+}
+
+static int rs_8xx_write_room(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int	ret;
+
+	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+		return 0;
+
+	if ((info->tx_cur->cbd_sc & BD_SC_READY) == 0) {
+		info->flags &= ~TX_WAKEUP;
+		ret = TX_BUF_SIZE;
+	}
+	else {
+		info->flags |= TX_WAKEUP;
+		ret = 0;
+	}
+	return ret;
+}
+
+/* I could track this with transmit counters....maybe later.
+*/
+static int rs_8xx_chars_in_buffer(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+		return 0;
+	return 0;
+}
+
+static void rs_8xx_flush_buffer(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+		return;
+
+	/* There is nothing to "flush", whatever we gave the CPM
+	 * is on its way out.
+	 */
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+	info->flags &= ~TX_WAKEUP;
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
+{
+	volatile cbd_t	*bdp;
+
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+		return;
+
+	bdp = info->tx_cur;
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	*((char *)__va(bdp->cbd_bufaddr)) = ch;
+	bdp->cbd_datlen = 1;
+	bdp->cbd_sc |= BD_SC_READY;
+
+	/* Get next BD.
+	*/
+	if (bdp->cbd_sc & BD_SC_WRAP)
+		bdp = info->tx_bd_base;
+	else
+		bdp++;
+
+	info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_throttle(struct tty_struct * tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+
+	printk("throttle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+		return;
+
+	if (I_IXOFF(tty))
+		rs_8xx_send_xchar(tty, STOP_CHAR(tty));
+
+#ifdef modem_control
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR &= ~UART_MCR_RTS;
+
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+#endif
+}
+
+static void rs_8xx_unthrottle(struct tty_struct * tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+
+	printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			rs_8xx_send_xchar(tty, START_CHAR(tty));
+	}
+#ifdef modem_control
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR |= UART_MCR_RTS;
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+#ifdef maybe
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int *value)
+{
+	unsigned char status;
+	unsigned int result;
+
+	cli();
+	status = serial_in(info, UART_LSR);
+	sti();
+	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+	return put_user(result,value);
+}
+#endif
+
+static int get_modem_info(ser_info_t *info, unsigned int *value)
+{
+	unsigned int result = 0;
+#ifdef modem_control
+	unsigned char control, status;
+
+	control = info->MCR;
+	cli();
+	status = serial_in(info, UART_MSR);
+	sti();
+	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+#ifdef TIOCM_OUT1
+		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
+		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
+#endif
+		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
+		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
+		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
+		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
+#endif
+	return put_user(result,value);
+}
+
+static int set_modem_info(ser_info_t *info, unsigned int cmd,
+			  unsigned int *value)
+{
+	int error;
+	unsigned int arg;
+
+	error = get_user(arg, value);
+	if (error)
+		return error;
+#ifdef modem_control
+	switch (cmd) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS)
+			info->MCR |= UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR |= UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR |= UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR |= UART_MCR_OUT2;
+#endif
+		break;
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			info->MCR &= ~UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR &= ~UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR &= ~UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR &= ~UART_MCR_OUT2;
+#endif
+		break;
+	case TIOCMSET:
+		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
+#ifdef TIOCM_OUT1
+					    UART_MCR_OUT1 |
+					    UART_MCR_OUT2 |
+#endif
+					    UART_MCR_DTR))
+			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+#ifdef TIOCM_OUT1
+			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
+			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+#endif
+			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+		break;
+	default:
+		return -EINVAL;
+	}
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+#endif
+	return 0;
+}
+
+/* Sending a break is a two step process on the SMC/SCC.  It is accomplished
+ * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
+ * command.  We take advantage of the begin/end functions to make this
+ * happen.
+ */
+static void begin_break(ser_info_t *info)
+{
+	volatile cpm_cpm2_t *cp;
+	uint	page, sblock;
+	ushort	num;
+
+	cp = cpmp;
+
+	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		if (num == 0) {
+			page = CPM_CR_SMC1_PAGE;
+			sblock = CPM_CR_SMC1_SBLOCK;
+		}
+		else {
+			page = CPM_CR_SMC2_PAGE;
+			sblock = CPM_CR_SMC2_SBLOCK;
+		}
+	}
+	else {
+		num -= SCC_NUM_BASE;
+		switch (num) {
+		case 0:
+			page = CPM_CR_SCC1_PAGE;
+			sblock = CPM_CR_SCC1_SBLOCK;
+			break;
+		case 1:
+			page = CPM_CR_SCC2_PAGE;
+			sblock = CPM_CR_SCC2_SBLOCK;
+			break;
+		case 2:
+			page = CPM_CR_SCC3_PAGE;
+			sblock = CPM_CR_SCC3_SBLOCK;
+			break;
+		case 3:
+			page = CPM_CR_SCC4_PAGE;
+			sblock = CPM_CR_SCC4_SBLOCK;
+			break;
+		default: return;
+		}
+	}
+	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_STOP_TX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+static void end_break(ser_info_t *info)
+{
+	volatile cpm_cpm2_t *cp;
+	uint	page, sblock;
+	ushort	num;
+
+	cp = cpmp;
+
+	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		if (num == 0) {
+			page = CPM_CR_SMC1_PAGE;
+			sblock = CPM_CR_SMC1_SBLOCK;
+		}
+		else {
+			page = CPM_CR_SMC2_PAGE;
+			sblock = CPM_CR_SMC2_SBLOCK;
+		}
+	}
+	else {
+		num -= SCC_NUM_BASE;
+		switch (num) {
+		case 0:
+			page = CPM_CR_SCC1_PAGE;
+			sblock = CPM_CR_SCC1_SBLOCK;
+			break;
+		case 1:
+			page = CPM_CR_SCC2_PAGE;
+			sblock = CPM_CR_SCC2_SBLOCK;
+			break;
+		case 2:
+			page = CPM_CR_SCC3_PAGE;
+			sblock = CPM_CR_SCC3_SBLOCK;
+			break;
+		case 3:
+			page = CPM_CR_SCC4_PAGE;
+			sblock = CPM_CR_SCC4_SBLOCK;
+			break;
+		default: return;
+		}
+	}
+	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void send_break(ser_info_t *info, int duration)
+{
+	current->state = TASK_INTERRUPTIBLE;
+#ifdef SERIAL_DEBUG_SEND_BREAK
+	printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
+#endif
+	begin_break(info);
+	schedule_timeout(duration);
+	end_break(info);
+#ifdef SERIAL_DEBUG_SEND_BREAK
+	printk("done jiffies=%lu\n", jiffies);
+#endif
+}
+
+
+static int rs_8xx_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int error;
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int retval;
+	struct async_icount cnow;	/* kernel counter temps */
+	struct serial_icounter_struct *p_cuser;	/* user space */
+
+	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+		case TCSBRK:	/* SVID version: non-zero arg --> no break */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			if (!arg) {
+				send_break(info, HZ/4);	/* 1/4 second */
+				if (signal_pending(current))
+					return -EINTR;
+			}
+			return 0;
+		case TCSBRKP:	/* support for POSIX tcsendbreak() */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+			if (signal_pending(current))
+				return -EINTR;
+			return 0;
+		case TIOCSBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			begin_break(info);
+			return 0;
+		case TIOCCBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			end_break(info);
+			return 0;
+		case TIOCGSOFTCAR:
+			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
+		case TIOCSSOFTCAR:
+			error = get_user(arg, (unsigned int *) arg);
+			if (error)
+				return error;
+			tty->termios->c_cflag =
+				((tty->termios->c_cflag & ~CLOCAL) |
+				 (arg ? CLOCAL : 0));
+			return 0;
+		case TIOCMGET:
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+#ifdef maybe
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, (unsigned int *) arg);
+#endif
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		 case TIOCMIWAIT:
+#ifdef modem_control
+			cli();
+			/* note the counters on entry */
+			cprev = info->state->icount;
+			sti();
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				cli();
+				cnow = info->state->icount; /* atomic copy */
+				sti();
+				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+					return -EIO; /* no change => error */
+				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+					return 0;
+				}
+				cprev = cnow;
+			}
+			/* NOTREACHED */
+#else
+			return 0;
+#endif
+
+		/*
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		case TIOCGICOUNT:
+			cli();
+			cnow = info->state->icount;
+			sti();
+			p_cuser = (struct serial_icounter_struct *) arg;
+			error = put_user(cnow.cts, &p_cuser->cts);
+			if (error) return error;
+			error = put_user(cnow.dsr, &p_cuser->dsr);
+			if (error) return error;
+			error = put_user(cnow.rng, &p_cuser->rng);
+			if (error) return error;
+			error = put_user(cnow.dcd, &p_cuser->dcd);
+			if (error) return error;
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+		}
+	return 0;
+}
+
+/* FIX UP modem control here someday......
+*/
+static void rs_8xx_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (   (tty->termios->c_cflag == old_termios->c_cflag)
+	    && (   RELEVANT_IFLAG(tty->termios->c_iflag)
+		== RELEVANT_IFLAG(old_termios->c_iflag)))
+	  return;
+
+	change_speed(info);
+
+#ifdef modem_control
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(tty->termios->c_cflag & CBAUD)) {
+		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+		cli();
+		serial_out(info, UART_MCR, info->MCR);
+		sti();
+	}
+
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (tty->termios->c_cflag & CBAUD)) {
+		info->MCR |= UART_MCR_DTR;
+		if (!tty->hw_stopped ||
+		    !(tty->termios->c_cflag & CRTSCTS)) {
+			info->MCR |= UART_MCR_RTS;
+		}
+		cli();
+		serial_out(info, UART_MCR, info->MCR);
+		sti();
+	}
+
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rs_8xx_start(tty);
+	}
+#endif
+
+#if 0
+	/*
+	 * No need to wake up processes in open wait, since they
+	 * sample the CLOCAL flag once, and don't recheck it.
+	 * XXX  It's not clear whether the current behavior is correct
+	 * or not.  Hence, this may change.....
+	 */
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	struct serial_state *state;
+	unsigned long	flags;
+	int		idx;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+		return;
+
+	state = info->state;
+
+	save_flags(flags); cli();
+
+	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+	if ((tty->count == 1) && (state->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("rs_close: bad serial port count; tty->count is 1, "
+		       "state->count is %d\n", state->count);
+		state->count = 1;
+	}
+	if (--state->count < 0) {
+		printk("rs_close: bad serial port count for ttys%d: %d\n",
+		       info->line, state->count);
+		state->count = 0;
+	}
+	if (state->count) {
+		DBG_CNT("before DEC-2");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->state->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->state->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->read_status_mask &= ~BD_SC_EMPTY;
+	if (info->flags & ASYNC_INITIALIZED) {
+		if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+			smcp = &cpm2_immr->im_smc[idx];
+			smcp->smc_smcm &= ~SMCM_RX;
+			smcp->smc_smcmr &= ~SMCMR_REN;
+		}
+		else {
+			sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+			sccp->scc_sccm &= ~UART_SCCM_RX;
+			sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
+		}
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		rs_8xx_wait_until_sent(tty, info->timeout);
+	}
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	MOD_DEC_USE_COUNT;
+	restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	/*int lsr;*/
+	volatile cbd_t *bdp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+		return;
+
+#ifdef maybe
+	if (info->state->type == PORT_UNKNOWN)
+		return;
+#endif
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 *
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = 1;
+	if (timeout)
+		char_time = MIN(char_time, timeout);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+	printk("jiff=%lu...", jiffies);
+#endif
+
+	/* We go through the loop at least once because we can't tell
+	 * exactly when the last character exits the shifter.  There can
+	 * be at least two characters waiting to be sent after the buffers
+	 * are empty.
+	 */
+	do {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		current->state = TASK_INTERRUPTIBLE;
+/*		current->counter = 0;	 make us low-priority */
+		schedule_timeout(char_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+		bdp = info->tx_cur;
+	} while (bdp->cbd_sc & BD_SC_READY);
+	current->state = TASK_RUNNING;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_8xx_hangup(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	struct serial_state *state = info->state;
+
+	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+		return;
+
+	state = info->state;
+
+	rs_8xx_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	state->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   ser_info_t *info)
+{
+#ifdef DO_THIS_LATER
+	DECLARE_WAITQUEUE(wait, current);
+#endif
+	struct serial_state *state = info->state;
+	int		retval;
+	int		do_clocal = 0;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		if (info->flags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+		    return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+		    return -EBUSY;
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 * If this is an SMC port, we don't have modem control to wait
+	 * for, so just get out here.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR)) ||
+	    (info->state->smc_scc_num < SCC_NUM_BASE)) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (state->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, state->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+#ifdef DO_THIS_LATER
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       state->line, state->count);
+#endif
+	cli();
+	if (!tty_hung_up_p(filp))
+		state->count--;
+	sti();
+	info->blocked_open++;
+	while (1) {
+		cli();
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (tty->termios->c_cflag & CBAUD))
+			serial_out(info, UART_MCR,
+				   serial_inp(info, UART_MCR) |
+				   (UART_MCR_DTR | UART_MCR_RTS));
+		sti();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (serial_in(info, UART_MSR) &
+				   UART_MSR_DCD)))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, state->count);
+#endif
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		state->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, state->count);
+#endif
+#endif /* DO_THIS_LATER */
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+
+static int get_async_struct(int line, ser_info_t **ret_info)
+{
+	struct serial_state *sstate;
+
+	sstate = rs_table + line;
+	if (sstate->info) {
+		sstate->count++;
+		*ret_info = (ser_info_t *)sstate->info;
+		return 0;
+	}
+	else {
+		return -ENOMEM;
+	}
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
+{
+	ser_info_t	*info;
+	int 		retval, line;
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= NR_PORTS))
+		return -ENODEV;
+	retval = get_async_struct(line, &info);
+	if (retval)
+		return retval;
+	if (serial_paranoia_check(info, tty->device, "rs_open"))
+		return -ENODEV;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+	       info->state->count);
+#endif
+	tty->driver_data = info;
+	info->tty = tty;
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval)
+		return retval;
+
+	MOD_INC_USE_COUNT;
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("rs_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+
+	if ((info->state->count == 1) &&
+	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->state->normal_termios;
+		else
+			*tty->termios = info->state->callout_termios;
+		change_speed(info);
+	}
+
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open ttys%d successful...", info->line);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static int inline line_info(char *buf, struct serial_state *state)
+{
+#ifdef notdef
+	struct async_struct *info = state->info, scr_info;
+	char	stat_buf[30], control, status;
+#endif
+	int	ret;
+
+	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
+		      state->line,
+		      (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
+		      (unsigned int)(state->port), state->irq);
+
+	if (!state->port || (state->type == PORT_UNKNOWN)) {
+		ret += sprintf(buf+ret, "\n");
+		return ret;
+	}
+
+#ifdef notdef
+	/*
+	 * Figure out the current RS-232 lines
+	 */
+	if (!info) {
+		info = &scr_info;	/* This is just for serial_{in,out} */
+
+		info->magic = SERIAL_MAGIC;
+		info->port = state->port;
+		info->flags = state->flags;
+		info->quot = 0;
+		info->tty = 0;
+	}
+	cli();
+	status = serial_in(info, UART_MSR);
+	control = info ? info->MCR : serial_in(info, UART_MCR);
+	sti();
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (control & UART_MCR_RTS)
+		strcat(stat_buf, "|RTS");
+	if (status & UART_MSR_CTS)
+		strcat(stat_buf, "|CTS");
+	if (control & UART_MCR_DTR)
+		strcat(stat_buf, "|DTR");
+	if (status & UART_MSR_DSR)
+		strcat(stat_buf, "|DSR");
+	if (status & UART_MSR_DCD)
+		strcat(stat_buf, "|CD");
+	if (status & UART_MSR_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->quot) {
+		ret += sprintf(buf+ret, " baud:%d",
+			       state->baud_base / info->quot);
+	}
+
+	ret += sprintf(buf+ret, " tx:%d rx:%d",
+		      state->icount.tx, state->icount.rx);
+
+	if (state->icount.frame)
+		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+
+	if (state->icount.parity)
+		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+
+	if (state->icount.brk)
+		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
+
+	if (state->icount.overrun)
+		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+	/*
+	 * Last thing is the RS-232 status lines
+	 */
+	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+#endif
+	return ret;
+}
+
+int rs_8xx_read_proc(char *page, char **start, off_t off, int count,
+		 int *eof, void *data)
+{
+	int i, len = 0;
+	off_t	begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+	for (i = 0; i < NR_PORTS && len < 4000; i++) {
+		len += line_info(page + len, &rs_table[i]);
+		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static _INLINE_ void show_serial_version(void)
+{
+ 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
+}
+
+
+/*
+ * The serial console driver used during boot.  Note that these names
+ * clash with those found in "serial.c", so we currently can't support
+ * the 16xxx uarts and these at the same time.  I will fix this to become
+ * an indirect function call from tty_io.c (or something).
+ */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/*
+ * Print a string to the serial port trying not to disturb any possible
+ * real use of the port...
+ * These funcitons work equally well for SCC, even though they are
+ * designed for SMC.  Our only interests are the transmit/receive
+ * buffers, which are identically mapped for either the SCC or SMC.
+ */
+static void my_console_write(int idx, const char *s,
+				unsigned count)
+{
+	struct		serial_state	*ser;
+	ser_info_t			*info;
+	unsigned			i;
+	volatile	cbd_t		*bdp, *bdbase;
+	volatile	smc_uart_t	*up;
+	volatile	u_char		*cp;
+
+	ser = rs_table + idx;
+
+	/* If the port has been initialized for general use, we have
+	 * to use the buffer descriptors allocated there.  Otherwise,
+	 * we simply use the single buffer allocated.
+	 */
+	if ((info = (ser_info_t *)ser->info) != NULL) {
+		bdp = info->tx_cur;
+		bdbase = info->tx_bd_base;
+	}
+	else {
+		/* Pointer to UART in parameter ram.
+		*/
+		up = (smc_uart_t *)&cpm2_immr->im_dprambase[ser->port];
+
+		/* Get the address of the host memory buffer.
+		 */
+		bdp = bdbase = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_tbase];
+	}
+
+	/*
+	 * We need to gracefully shut down the transmitter, disable
+	 * interrupts, then send our bytes out.
+	 */
+
+	/*
+	 * Now, do each character.  This is not as bad as it looks
+	 * since this is a holding FIFO and not a transmitting FIFO.
+	 * We could add the complexity of filling the entire transmit
+	 * buffer, but we would just wait longer between accesses......
+	 */
+	for (i = 0; i < count; i++, s++) {
+		/* Wait for transmitter fifo to empty.
+		 * Ready indicates output is ready, and xmt is doing
+		 * that, not that it is ready for us to send.
+		 */
+		while (bdp->cbd_sc & BD_SC_READY);
+
+		/* Send the character out.
+		 * If the buffer address is in the CPM DPRAM, don't
+		 * convert it.
+		 */
+		if ((uint)(bdp->cbd_bufaddr) > (uint)CPM_MAP_ADDR)
+			cp = (u_char *)(bdp->cbd_bufaddr);
+		else
+			cp = __va(bdp->cbd_bufaddr);
+		*cp = *s;
+
+		bdp->cbd_datlen = 1;
+		bdp->cbd_sc |= BD_SC_READY;
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = bdbase;
+		else
+			bdp++;
+
+		/* if a LF, also do CR... */
+		if (*s == 10) {
+			while (bdp->cbd_sc & BD_SC_READY);
+			cp = __va(bdp->cbd_bufaddr);
+			*cp = 13;
+			bdp->cbd_datlen = 1;
+			bdp->cbd_sc |= BD_SC_READY;
+
+			if (bdp->cbd_sc & BD_SC_WRAP) {
+				bdp = bdbase;
+			}
+			else {
+				bdp++;
+			}
+		}
+	}
+
+	/*
+	 * Finally, Wait for transmitter & holding register to empty
+	 *  and restore the IER
+	 */
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	if (info)
+		info->tx_cur = (cbd_t *)bdp;
+}
+
+static void serial_console_write(struct console *c, const char *s,
+				unsigned count)
+{
+#if defined(CONFIG_KGDB_CONSOLE) && !defined(CONFIG_USE_SERIAL2_KGDB)
+	/* Try to let stub handle output. Returns true if it did. */ 
+	if (kgdb_output_string(s, count))
+		return;
+#endif
+	my_console_write(c->index, s, count);
+}
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_write(const char *s, unsigned count)
+{
+	my_console_write(KGDB_SER_IDX, s, count);
+	return(count);
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void
+putDebugChar(char ch)
+{
+	my_console_write(KGDB_SER_IDX, &ch, 1);
+}
+#endif
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
+/*
+ * Receive character from the serial port.  This only works well
+ * before the port is initialize for real use.
+ */
+static int my_console_wait_key(int idx, int xmon, char *obuf)
+{
+	struct serial_state		*ser;
+	u_char				c, *cp;
+	ser_info_t			*info;
+	volatile	cbd_t		*bdp;
+	volatile	smc_uart_t	*up;
+	int				i;
+
+	ser = rs_table + idx;
+
+	/* Pointer to UART in parameter ram.
+	*/
+	up = (smc_uart_t *)&cpm2_immr->im_dprambase[ser->port];
+
+	/* Get the address of the host memory buffer.
+	 * If the port has been initialized for general use, we must
+	 * use information from the port structure.
+	 */
+	if ((info = (ser_info_t *)ser->info))
+		bdp = info->rx_cur;
+	else
+		bdp = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_rbase];
+
+	/*
+	 * We need to gracefully shut down the receiver, disable
+	 * interrupts, then read the input.
+	 * XMON just wants a poll.  If no character, return -1, else
+	 * return the character.
+	 */
+	if (!xmon) {
+		while (bdp->cbd_sc & BD_SC_EMPTY);
+	}
+	else {
+		if (bdp->cbd_sc & BD_SC_EMPTY)
+			return -1;
+	}
+
+	/* If the buffer address is in the CPM DPRAM, don't
+	 * convert it.
+	 */
+	if ((uint)(bdp->cbd_bufaddr) > (uint)CPM_MAP_ADDR)
+		cp = (u_char *)(bdp->cbd_bufaddr);
+	else
+		cp = __va(bdp->cbd_bufaddr);
+
+	if (obuf) {
+		i = c = bdp->cbd_datlen;
+		while (i-- > 0)
+			*obuf++ = *cp++;
+	}
+	else {
+		c = *cp;
+	}
+	bdp->cbd_sc |= BD_SC_EMPTY;
+
+	if (info) {
+		if (bdp->cbd_sc & BD_SC_WRAP) {
+			bdp = info->rx_bd_base;
+		}
+		else {
+			bdp++;
+		}
+		info->rx_cur = (cbd_t *)bdp;
+	}
+
+	return((int)c);
+}
+#endif
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_read_poll(void)
+{
+	return(my_console_wait_key(KGDB_SER_IDX, 1, NULL));
+}
+
+int
+xmon_8xx_read_char(void)
+{
+	return(my_console_wait_key(KGDB_SER_IDX, 0, NULL));
+}
+#endif
+
+#ifdef CONFIG_KGDB
+static char kgdb_buf[RX_BUF_SIZE], *kgdp;
+static int kgdb_chars;
+
+char
+getDebugChar(void)
+{
+	if (kgdb_chars <= 0) {
+		kgdb_chars = my_console_wait_key(KGDB_SER_IDX, 0, kgdb_buf);
+		kgdp = kgdb_buf;
+	}
+	kgdb_chars--;
+
+	return(*kgdp++);
+}
+
+void kgdb_interruptible(int yes)
+{
+	volatile smc_t	*smcp;
+
+	smcp = &cpm2_immr->im_smc[KGDB_SER_IDX];
+
+	if (yes == 1)
+		smcp->smc_smcm |= SMCM_RX;
+	else
+		smcp->smc_smcm &= ~SMCM_RX;
+}
+
+void kgdb_map_scc(void)
+{
+	ushort		serbase;
+	uint		mem_addr;
+	volatile	cbd_t		*bdp;
+	volatile	smc_uart_t	*up;
+
+	/* The serial port has already been initialized before
+	 * we get here.  We have to assign some pointers needed by
+	 * the kernel, and grab a memory location in the CPM that will
+	 * work until the driver is really initialized.
+	 */
+	cpm2_immr = (cpm2_map_t *)CPM_MAP_ADDR;
+
+	/* Right now, assume we are using SMCs.
+	*/
+#ifdef USE_KGDB_SMC2
+	*(ushort *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = serbase = PROFF_SMC2;
+#else
+	*(ushort *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = serbase = PROFF_SMC1;
+#endif
+	up = (smc_uart_t *)&cpm2_immr->im_dprambase[serbase];
+
+	/* Allocate space for an input FIFO, plus a few bytes for output.
+	 * Allocate bytes to maintain word alignment.
+	 */
+	mem_addr = (uint)(&cpm2_immr->im_dprambase[0x1000]);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	bdp = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_rbase];
+	bdp->cbd_bufaddr = mem_addr;
+
+	bdp = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_tbase];
+	bdp->cbd_bufaddr = mem_addr+RX_BUF_SIZE;
+
+	up->smc_mrblr = RX_BUF_SIZE;		/* receive buffer length */
+	up->smc_maxidl = RX_BUF_SIZE;
+}
+#endif
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ *	Register console.
+ */
+long __init console_8xx_init(long kmem_start, long kmem_end)
+{
+	register_console(&sercons);
+	return kmem_start;
+}
+
+#endif
+
+/* Default console baud rate as determined by the board information
+ * structure.
+ */
+static	int	baud_idx;
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+int __init rs_8xx_init(void)
+{
+	struct serial_state * state;
+	ser_info_t	*info;
+	uint		mem_addr, dp_addr;
+	int		i, j, idx;
+	uint		page, sblock;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+	volatile	smc_t		*sp;
+	volatile	smc_uart_t	*up;
+	volatile	scc_t		*scp;
+	volatile	scc_uart_t	*sup;
+	volatile	cpm2_map_t	*immap;
+	volatile	iop_cpm2_t	*io;
+
+	init_bh(SERIAL_BH, do_serial_bh);
+
+	show_serial_version();
+
+	/* Initialize the tty_driver structure */
+
+	/*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
+	__clear_user(&serial_driver,sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.driver_name = "serial";
+#ifdef CONFIG_DEVFS_FS
+	serial_driver.name = "tts/%d";
+#else
+	serial_driver.name = "ttyS";
+#endif
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64;
+	serial_driver.num = NR_PORTS;
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+	serial_driver.init_termios.c_cflag =
+		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver.flags = TTY_DRIVER_REAL_RAW;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+
+	serial_driver.open = rs_8xx_open;
+	serial_driver.close = rs_8xx_close;
+	serial_driver.write = rs_8xx_write;
+	serial_driver.put_char = rs_8xx_put_char;
+	serial_driver.write_room = rs_8xx_write_room;
+	serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
+	serial_driver.flush_buffer = rs_8xx_flush_buffer;
+	serial_driver.ioctl = rs_8xx_ioctl;
+	serial_driver.throttle = rs_8xx_throttle;
+	serial_driver.unthrottle = rs_8xx_unthrottle;
+	serial_driver.send_xchar = rs_8xx_send_xchar;
+	serial_driver.set_termios = rs_8xx_set_termios;
+	serial_driver.stop = rs_8xx_stop;
+	serial_driver.start = rs_8xx_start;
+	serial_driver.hangup = rs_8xx_hangup;
+	serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
+	serial_driver.read_proc = rs_8xx_read_proc;
+
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+#ifdef CONFIG_DEVFS_FS
+	callout_driver.name = "cua/%d";
+#else
+	callout_driver.name = "cua";
+#endif
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
+
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout driver\n");
+
+	immap = cpm2_immr;
+	cp = &immap->im_cpm;
+	io = &immap->im_ioport;
+
+	/* This should have been done long ago by the early boot code,
+	 * but do it again to make sure.
+	 */
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+	/* Geeze, here we go....Picking I/O port bits....Lots of
+	 * choices.  If you don't like mine, pick your own.
+	 * Configure SMCs Tx/Rx.  SMC1 is only on Port D, SMC2 is
+	 * only on Port A.  You either pick 'em, or not.
+	 */
+#ifndef SCC_CONSOLE
+	io->iop_ppard |= 0x00c00000;
+	io->iop_pdird |= 0x00400000;
+	io->iop_pdird &= ~0x00800000;
+	io->iop_psord &= ~0x00c00000;
+#if USE_SMC2
+	io->iop_ppara |= 0x00c00000;
+	io->iop_pdira |= 0x00400000;
+	io->iop_pdira &= ~0x00800000;
+	io->iop_psora &= ~0x00c00000;
+#endif
+
+	/* Configure SCC2 and SCC3.  Be careful about the fine print.
+	 * Secondary options are only available when you take away
+	 * the primary option.  Unless the pins are used for something
+	 * else, SCC2 and SCC3 are on Port B.
+	 *	Port B,  8 - SCC3 TxD
+	 *	Port B, 12 - SCC2 TxD
+	 *	Port B, 14 - SCC3 RxD
+	 *	Port B, 15 - SCC2 RxD
+	 */
+	io->iop_pparb |= 0x008b0000;
+	io->iop_pdirb |= 0x00880000;
+	io->iop_psorb |= 0x00880000;
+	io->iop_pdirb &= ~0x00030000;
+	io->iop_psorb &= ~0x00030000;
+
+	/* Wire BRG1 to SMC1 and BRG2 to SMC2.
+	*/
+	immap->im_cpmux.cmx_smr = 0;
+
+	/* Connect SCC2 and SCC3 to NMSI.  Connect BRG3 to SCC2 and
+	 * BRG4 to SCC3.
+	 */
+	immap->im_cpmux.cmx_scr &= ~0x00ffff00;
+	immap->im_cpmux.cmx_scr |= 0x00121b00;
+#else
+	io->iop_pparb |= 0x008b0000;
+	io->iop_pdirb |= 0x00880000;
+	io->iop_psorb |= 0x00880000;
+	io->iop_pdirb &= ~0x00030000;
+	io->iop_psorb &= ~0x00030000;
+
+	/* Use Port D for SCC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00000003;
+	io->iop_psord &= ~0x00000001;	/* Rx */
+	io->iop_psord |= 0x00000002;	/* Tx */
+	io->iop_pdird &= ~0x00000001;	/* Rx */
+	io->iop_pdird |= 0x00000002;	/* Tx */
+
+	/* Connect SCC1, SCC2, SCC3 to NMSI.  Connect BRG1 to SCC1,
+	 * BRG2 to SCC2, BRG3 to SCC3.
+	 */
+	immap->im_cpmux.cmx_scr &= ~0xffffff00;
+	immap->im_cpmux.cmx_scr |= 0x00091200;
+#endif
+
+	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+		state->magic = SSTATE_MAGIC;
+		state->line = i;
+		state->type = PORT_UNKNOWN;
+		state->custom_divisor = 0;
+		state->close_delay = 5*HZ/10;
+		state->closing_wait = 30*HZ;
+		state->callout_termios = callout_driver.init_termios;
+		state->normal_termios = serial_driver.init_termios;
+		state->icount.cts = state->icount.dsr =
+			state->icount.rng = state->icount.dcd = 0;
+		state->icount.rx = state->icount.tx = 0;
+		state->icount.frame = state->icount.parity = 0;
+		state->icount.overrun = state->icount.brk = 0;
+ 		printk (KERN_INFO "ttyS%d on %s%d at 0x%04x, BRG%d\n",
+ 			i,
+ 			(state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
+ 			PORT_NUM(state->smc_scc_num) + 1,
+ 			(unsigned int)(state->port),
+ 			state->smc_scc_num + 1);
+#ifdef CONFIG_SERIAL_CONSOLE
+		/* If we just printed the message on the console port, and
+		 * we are about to initialize it for general use, we have
+		 * to wait a couple of character times for the CR/NL to
+		 * make it out of the transmit buffer.
+		 */
+		if (i == CONFIG_SERIAL_CONSOLE_PORT)
+			mdelay(300);
+#endif
+		info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
+		if (info) {
+			/*memset(info, 0, sizeof(ser_info_t));*/
+			__clear_user(info,sizeof(ser_info_t));
+			init_waitqueue_head(&info->open_wait);
+			init_waitqueue_head(&info->close_wait);
+			info->magic = SERIAL_MAGIC;
+			info->flags = state->flags;
+			info->tqueue.routine = do_softint;
+			info->tqueue.data = info;
+			info->tqueue_hangup.routine = do_serial_hangup;
+			info->tqueue_hangup.data = info;
+			info->line = i;
+			info->state = state;
+			state->info = (struct async_struct *)info;
+
+			/* We need to allocate a transmit and receive buffer
+			 * descriptors from dual port ram, and a character
+			 * buffer area from host mem.
+			 */
+			dp_addr = cpm2_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO, 8);
+
+			/* Allocate space for FIFOs in the host memory.
+			*/
+			mem_addr = cpm2_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE, 1);
+
+			/* Set the physical address of the host memory
+			 * buffers in the buffer descriptors, and the
+			 * virtual address for us to work with.
+			 */
+			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+			info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
+
+			for (j=0; j<(RX_NUM_FIFO-1); j++) {
+				bdp->cbd_bufaddr = __pa(mem_addr);
+				bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+				mem_addr += RX_BUF_SIZE;
+				bdp++;
+			}
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+
+			if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
+				sp = &immap->im_smc[idx];
+				up = (smc_uart_t *)&immap->im_dprambase[state->port];
+				up->smc_rbase = dp_addr;
+			}
+			else {
+				scp = &immap->im_scc[idx - SCC_IDX_BASE];
+				sup = (scc_uart_t *)&immap->im_dprambase[state->port];
+				scp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+				sup->scc_genscc.scc_rbase = dp_addr;
+			}
+
+			dp_addr = cpm2_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO, 8);
+
+			/* Allocate space for FIFOs in the host memory.
+			*/
+			mem_addr = cpm2_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE, 1);
+
+			/* Set the physical address of the host memory
+			 * buffers in the buffer descriptors, and the
+			 * virtual address for us to work with.
+			 */
+			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+			info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
+
+			for (j=0; j<(TX_NUM_FIFO-1); j++) {
+				bdp->cbd_bufaddr = __pa(mem_addr);
+				bdp->cbd_sc = BD_SC_INTRPT;
+				mem_addr += TX_BUF_SIZE;
+				bdp++;
+			}
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
+
+			if (idx < SCC_NUM_BASE) {
+				up->smc_tbase = dp_addr;
+
+				/* Set up the uart parameters in the
+				 * parameter ram.
+				 */
+				up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+				up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+				/* Set this to 1 for now, so we get single
+				 * character interrupts.  Using idle charater
+				 * time requires some additional tuning.
+				 */
+				up->smc_mrblr = 1;
+				up->smc_maxidl = 0;
+				up->smc_brkcr = 1;
+
+				/* Send the CPM an initialize command.
+				*/
+				if (state->smc_scc_num == 0) {
+					page = CPM_CR_SMC1_PAGE;
+					sblock = CPM_CR_SMC1_SBLOCK;
+				}
+				else {
+					page = CPM_CR_SMC2_PAGE;
+					sblock = CPM_CR_SMC2_SBLOCK;
+				}
+
+				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+						CPM_CR_INIT_TRX) | CPM_CR_FLG;
+				while (cp->cp_cpcr & CPM_CR_FLG);
+
+				/* Set UART mode, 8 bit, no parity, one stop.
+				 * Enable receive and transmit.
+				 */
+				sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+				/* Disable all interrupts and clear all pending
+				 * events.
+				 */
+				sp->smc_smcm = 0;
+				sp->smc_smce = 0xff;
+			}
+			else {
+				sup->scc_genscc.scc_tbase = dp_addr;
+
+				/* Set up the uart parameters in the
+				 * parameter ram.
+				 */
+				sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+				sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+				/* Set this to 1 for now, so we get single
+				 * character interrupts.  Using idle charater
+				 * time requires some additional tuning.
+				 */
+				sup->scc_genscc.scc_mrblr = 1;
+				sup->scc_maxidl = 0;
+				sup->scc_brkcr = 1;
+				sup->scc_parec = 0;
+				sup->scc_frmec = 0;
+				sup->scc_nosec = 0;
+				sup->scc_brkec = 0;
+				sup->scc_uaddr1 = 0;
+				sup->scc_uaddr2 = 0;
+				sup->scc_toseq = 0;
+				sup->scc_char1 = 0x8000;
+				sup->scc_char2 = 0x8000;
+				sup->scc_char3 = 0x8000;
+				sup->scc_char4 = 0x8000;
+				sup->scc_char5 = 0x8000;
+				sup->scc_char6 = 0x8000;
+				sup->scc_char7 = 0x8000;
+				sup->scc_char8 = 0x8000;
+				sup->scc_rccm = 0xc0ff;
+
+				/* Send the CPM an initialize command.
+				*/
+#ifdef SCC_CONSOLE
+				switch (state->smc_scc_num) {
+				case 0:
+					page = CPM_CR_SCC1_PAGE;
+					sblock = CPM_CR_SCC1_SBLOCK;
+					break;
+				case 1:
+					page = CPM_CR_SCC2_PAGE;
+					sblock = CPM_CR_SCC2_SBLOCK;
+					break;
+				case 2:
+					page = CPM_CR_SCC3_PAGE;
+					sblock = CPM_CR_SCC3_SBLOCK;
+					break;
+				}
+#else
+				if (state->smc_scc_num == 2) {
+					page = CPM_CR_SCC2_PAGE;
+					sblock = CPM_CR_SCC2_SBLOCK;
+				}
+				else {
+					page = CPM_CR_SCC3_PAGE;
+					sblock = CPM_CR_SCC3_SBLOCK;
+				}
+#endif
+
+				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+						CPM_CR_INIT_TRX) | CPM_CR_FLG;
+				while (cp->cp_cpcr & CPM_CR_FLG);
+
+				/* Set UART mode, 8 bit, no parity, one stop.
+				 * Enable receive and transmit.
+				 */
+				scp->scc_gsmrh = 0;
+				scp->scc_gsmrl =
+					(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+				/* Disable all interrupts and clear all pending
+				 * events.
+				 */
+				scp->scc_sccm = 0;
+				scp->scc_scce = 0xffff;
+				scp->scc_dsr = 0x7e7e;
+				scp->scc_psmr = 0x3000;
+			}
+
+			/* Install interrupt handler.
+			*/
+			request_irq(state->irq, rs_8xx_interrupt, 0, "uart",
+					info);
+
+			/* Set up the baud rate generator.
+			*/
+			cpm2_setbrg(state->smc_scc_num,
+							baud_table[baud_idx]);
+
+			/* If the port is the console, enable Rx and Tx.
+			*/
+#ifdef CONFIG_SERIAL_CONSOLE
+			if (i == CONFIG_SERIAL_CONSOLE_PORT) {
+				if (idx < SCC_NUM_BASE)
+					sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+				else
+					scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+			}
+#endif
+		}
+	}
+	return 0;
+}
+
+/* This must always be called before the rs_8xx_init() function, otherwise
+ * it blows away the port control information.
+*/
+static int __init serial_console_setup(struct console *co, char *options)
+{
+	struct		serial_state *ser;
+	uint		mem_addr, dp_addr, bidx;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+	volatile	cpm2_map_t	*immap;
+#ifndef SCC_CONSOLE
+	volatile	smc_t		*sp;
+	volatile	smc_uart_t	*up;
+#endif
+	volatile	scc_t		*scp;
+	volatile	scc_uart_t	*sup;
+	volatile	iop_cpm2_t	*io;
+	bd_t				*bd;
+
+	bd = (bd_t *)__res;
+
+	for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
+		if (bd->bi_baudrate == baud_table[bidx])
+			break;
+
+	co->cflag = CREAD|CLOCAL|bidx|CS8;
+	baud_idx = bidx;
+
+	ser = rs_table + co->index;
+
+	immap = cpm2_immr;
+	cp = &immap->im_cpm;
+	io = &immap->im_ioport;
+
+#ifdef SCC_CONSOLE
+	scp = (scc_t *)&(immap->im_scc[SCC_CONSOLE-1]);
+	sup = (scc_uart_t *)&immap->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+	scp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+	scp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* Use Port D for SCC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00000003;
+	io->iop_psord &= ~0x00000001;	/* Rx */
+	io->iop_psord |= 0x00000002;	/* Tx */
+	io->iop_pdird &= ~0x00000001;	/* Rx */
+	io->iop_pdird |= 0x00000002;	/* Tx */
+
+#else
+	/* This should have been done long ago by the early boot code,
+	 * but do it again to make sure.
+	 */
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+	/* Right now, assume we are using SMCs.
+	*/
+	sp = &immap->im_smc[ser->smc_scc_num];
+
+	/* When we get here, the CPM has been reset, so we need
+	 * to configure the port.
+	 * We need to allocate a transmit and receive buffer descriptor
+	 * from dual port ram, and a character buffer area from host mem.
+	 */
+	up = (smc_uart_t *)&immap->im_dprambase[ser->port];
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+	/* Use Port D for SMC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00c00000;
+	io->iop_pdird |= 0x00400000;
+	io->iop_pdird &= ~0x00800000;
+	io->iop_psord &= ~0x00c00000;
+#endif
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	*/
+	dp_addr = cpm2_dpalloc(sizeof(cbd_t) * 2, 8);
+
+	/* Allocate space for two 2 byte FIFOs in the host memory.
+	*/
+	mem_addr = cpm2_hostalloc(4, 1);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+	bdp->cbd_bufaddr = __pa(mem_addr);
+	(bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
+
+	/* For the receive, set empty and wrap.
+	 * For transmit, set wrap.
+	 */
+	bdp->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	(bdp+1)->cbd_sc = BD_SC_WRAP;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+#ifdef SCC_CONSOLE
+	sup->scc_genscc.scc_rbase = dp_addr;
+	sup->scc_genscc.scc_tbase = dp_addr + sizeof(cbd_t);
+
+	/* Set up the uart parameters in the
+	 * parameter ram.
+	 */
+	sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	sup->scc_genscc.scc_mrblr = 1;
+	sup->scc_maxidl = 0;
+	sup->scc_brkcr = 1;
+	sup->scc_parec = 0;
+	sup->scc_frmec = 0;
+	sup->scc_nosec = 0;
+	sup->scc_brkec = 0;
+	sup->scc_uaddr1 = 0;
+	sup->scc_uaddr2 = 0;
+	sup->scc_toseq = 0;
+	sup->scc_char1 = 0x8000;
+	sup->scc_char2 = 0x8000;
+	sup->scc_char3 = 0x8000;
+	sup->scc_char4 = 0x8000;
+	sup->scc_char5 = 0x8000;
+	sup->scc_char6 = 0x8000;
+	sup->scc_char7 = 0x8000;
+	sup->scc_char8 = 0x8000;
+	sup->scc_rccm = 0xc0ff;
+
+	/* Send the CPM an initialize command.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	scp->scc_gsmrh = 0;
+	scp->scc_gsmrl = 
+		(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+	/* Disable all interrupts and clear all pending
+	 * events.
+	 */
+	scp->scc_sccm = 0;
+	scp->scc_scce = 0xffff;
+	scp->scc_dsr = 0x7e7e;
+	scp->scc_psmr = 0x3000;
+
+	/* Wire BRG1 to SCC1.  The serial init will take care of
+	 * others.
+	 */
+	immap->im_cpmux.cmx_scr = 0;
+
+	/* Set up the baud rate generator.
+	*/
+	cpm2_setbrg(ser->smc_scc_num, bd->bi_baudrate);
+
+	scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#else
+	up->smc_rbase = dp_addr;	/* Base of receive buffer desc. */
+	up->smc_tbase = dp_addr+sizeof(cbd_t);	/* Base of xmt buffer desc. */
+	up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	/* Set this to 1 for now, so we get single character interrupts.
+	*/
+	up->smc_mrblr = 1;		/* receive buffer length */
+	up->smc_maxidl = 0;		/* wait forever for next char */
+
+	/* Send the CPM an initialize command.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Set up the baud rate generator.
+	*/
+	cpm2_setbrg(ser->smc_scc_num, bd->bi_baudrate);
+
+	/* And finally, enable Rx and Tx.
+	*/
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+#endif
+
+	return 0;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/Makefile linux-2.4.26-pre6/arch/ppc/kernel/Makefile
--- linux-2.4.25/arch/ppc/kernel/Makefile	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/Makefile	2004-03-25 00:21:53.000000000 +0000
@@ -32,7 +32,8 @@ all: $(HEAD-y) kernel.o
 O_TARGET := kernel.o
 
 export-objs			:= ppc_ksyms.o time.o ocp.o ppc4xx_setup.o \
-					ppc4xx_dma.o ppc4xx_sgdma.o
+					ppc4xx_dma.o ppc4xx_sgdma.o \
+					ppc4xx_stbdma.o
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o ptrace.o align.o \
@@ -53,8 +54,10 @@ ifeq ($(CONFIG_SERIAL)$(CONFIG_GEN550),y
 obj-$(CONFIG_KGDB)		+= gen550_kgdb.o gen550_dbg.o
 obj-$(CONFIG_SERIAL_TEXT_DEBUG)	+= gen550_dbg.o
 endif
+obj-$(CONFIG_PPC_OCP)		+= ocp.o
 obj-$(CONFIG_40x)		+= ppc4xx_setup.o
-obj-$(CONFIG_4xx)		+= ocp.o ppc4xx_pic.o todc_time.o
+obj-$(CONFIG_4xx)		+= ppc4xx_pic.o todc_time.o
+obj-$(CONFIG_STBXXX_DMA)	+= ppc4xx_stbdma.o
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_40x)		+= ppc405_pci.o
 obj-$(CONFIG_4xx)		+= indirect_pci.o pci_auto.o
@@ -85,7 +88,7 @@ obj-$(CONFIG_PRPMC750)		+= open_pic.o in
 obj-$(CONFIG_SANDPOINT)		+= i8259.o open_pic.o mpc10x_common.o \
 					pci_auto.o indirect_pci.o todc_time.o
 obj-$(CONFIG_SPRUCE)		+= indirect_pci.o pci_auto.o todc_time.o
-obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
+obj-$(CONFIG_8260)		+= m8260_setup.o cpm2_pic.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/cpm2_pic.c linux-2.4.26-pre6/arch/ppc/kernel/cpm2_pic.c
--- linux-2.4.25/arch/ppc/kernel/cpm2_pic.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/cpm2_pic.c	2004-03-25 00:20:11.000000000 +0000
@@ -0,0 +1,128 @@
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/irq.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include "cpm2_pic.h"
+
+/* The CPM2 internal interrupt controller.  It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static	u_char	irq_to_siureg[] = {
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static	u_char	irq_to_siubit[] = {
+	31, 16, 17, 18, 19, 20, 21, 22,
+	23, 24, 25, 26, 27, 28, 29, 30,
+	29, 30, 16, 17, 18, 19, 20, 21,
+	22, 23, 24, 25, 26, 27, 28, 31,
+	 0,  1,  2,  3,  4,  5,  6,  7,
+	 8,  9, 10, 11, 12, 13, 14, 15,
+	15, 14, 13, 12, 11, 10,  9,  8,
+	 7,  6,  5,  4,  3,  2,  1,  0
+};
+
+static void cpm2_mask_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_unmask_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_mask_and_ack(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr, *sipnr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
+	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+	sipnr[word] = 1 << (31 - bit);
+}
+
+static void cpm2_end_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+
+		bit = irq_to_siubit[irq_nr];
+		word = irq_to_siureg[irq_nr];
+
+		simr = &(cpm2_immr->im_intctl.ic_simrh);
+		ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+		simr[word] = ppc_cached_irq_mask[word];
+	}
+}
+
+struct hw_interrupt_type cpm2_pic = {
+	" CPM2 SIU  ",
+	NULL,
+	NULL,
+	cpm2_unmask_irq,
+	cpm2_mask_irq,
+	cpm2_mask_and_ack,
+	cpm2_end_irq,
+	0
+};
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int
+cpm2_get_irq(struct pt_regs *regs)
+{
+	int irq;
+        unsigned long bits;
+
+        /* For CPM2, read the SIVEC register and shift the bits down
+         * to get the irq number.         */
+        bits = cpm2_immr->im_intctl.ic_sivec;
+        irq = bits >> 26;
+
+	if (irq == 0)	/* 0 --> no irq is pending */
+		irq = -1;
+
+	return irq;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/cpm2_pic.h linux-2.4.26-pre6/arch/ppc/kernel/cpm2_pic.h
--- linux-2.4.25/arch/ppc/kernel/cpm2_pic.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/cpm2_pic.h	2004-03-25 00:22:08.000000000 +0000
@@ -0,0 +1,13 @@
+#ifndef _PPC_KERNEL_CPM2_H
+#define _PPC_KERNEL_CPM2_H
+
+#include <linux/irq.h>
+
+extern struct hw_interrupt_type cpm2_pic;
+
+void cpm2_pic_init(void);
+void cpm2_do_IRQ(struct pt_regs *regs,
+                 int            cpu);
+int cpm2_get_irq(struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_CPM2_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/entry.S linux-2.4.26-pre6/arch/ppc/kernel/entry.S
--- linux-2.4.25/arch/ppc/kernel/entry.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/entry.S	2004-03-25 00:21:49.000000000 +0000
@@ -43,6 +43,10 @@ show_syscalls_task:
  * Handle a system call.
  */
 	.text
+	.stabs	"arch/ppc/kernel/",N_SO,0,0,0f
+	.stabs	"entry.S",N_SO,0,0,0f
+0:
+
 _GLOBAL(DoSyscall)
 	stw	r0,THREAD+LAST_SYSCALL(r2)
 	lwz	r11,_CCR(r1)	/* Clear SO bit in CR */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/head.S linux-2.4.26-pre6/arch/ppc/kernel/head.S
--- linux-2.4.25/arch/ppc/kernel/head.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/head.S	2004-03-25 00:16:56.000000000 +0000
@@ -69,6 +69,9 @@
 #endif /* CONFIG_PPC64BRIDGE */
 
 	.text
+	.stabs	"arch/ppc/kernel/",N_SO,0,0,0f
+	.stabs	"head.S",N_SO,0,0,0f
+0:
 	.globl	_stext
 _stext:
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/m8260_setup.c linux-2.4.26-pre6/arch/ppc/kernel/m8260_setup.c
--- linux-2.4.25/arch/ppc/kernel/m8260_setup.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/m8260_setup.c	2004-03-25 00:20:00.000000000 +0000
@@ -40,12 +40,12 @@
 #include <asm/pgtable.h>
 #include <asm/ide.h>
 #include <asm/mpc8260.h>
-#include <asm/immap_8260.h>
+#include <asm/immap_cpm2.h>
 #include <asm/machdep.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 
-#include "ppc8260_pic.h"
+#include "cpm2_pic.h"
 
 static int m8260_set_rtc_time(unsigned long time);
 static unsigned long m8260_get_rtc_time(void);
@@ -53,14 +53,14 @@ static void m8260_calibrate_decr(void);
 
 unsigned char __res[sizeof(bd_t)];
 
-extern void m8260_cpm_reset(void);
+extern void cpm2_reset(void);
 
 static void __init
 m8260_setup_arch(void)
 {
 	/* Reset the Communication Processor Module.
 	*/
-	m8260_cpm_reset();
+	cpm2_reset();
 }
 
 static void
@@ -172,18 +172,18 @@ m8260_init_IRQ(void)
 	void cpm_interrupt_init(void);
 
 #if 0
-        ppc8260_pic.irq_offset = 0;
+        cpm2_pic.irq_offset = 0;
 #endif
         for ( i = 0 ; i < NR_SIU_INTS ; i++ )
-                irq_desc[i].handler = &ppc8260_pic;
+                irq_desc[i].handler = &cpm2_pic;
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
 	 */
-	immr->im_intctl.ic_sicr = 0;
-	immr->im_intctl.ic_siprr = 0x05309770;
-	immr->im_intctl.ic_scprrh = 0x05309770;
-	immr->im_intctl.ic_scprrl = 0x05309770;
+	cpm2_immr->im_intctl.ic_sicr = 0;
+	cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+	cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+	cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
 
 }
 
@@ -242,7 +242,7 @@ platform_init(unsigned long r3, unsigned
 	ppc_md.show_percpuinfo		= m8260_show_percpuinfo;
 	ppc_md.irq_cannonicalize	= NULL;
 	ppc_md.init_IRQ			= m8260_init_IRQ;
-	ppc_md.get_irq			= m8260_get_irq;
+	ppc_md.get_irq			= cpm2_get_irq;
 	ppc_md.init			= NULL;
 
 	ppc_md.restart			= m8260_restart;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/misc.S linux-2.4.26-pre6/arch/ppc/kernel/misc.S
--- linux-2.4.25/arch/ppc/kernel/misc.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/misc.S	2004-03-25 00:21:59.000000000 +0000
@@ -694,29 +694,36 @@ _GLOBAL(clear_page)
 _GLOBAL(copy_page)
 	addi	r3,r3,-4
 	addi	r4,r4,-4
+
+#ifdef CONFIG_8xx
+	/* don't use prefetch on 8xx */
+    	li	r0,4096/L1_CACHE_LINE_SIZE
+	mtctr	r0
+1:	COPY_16_BYTES
+	bdnz	1b
+	blr
+
+#else	/* not 8xx, we can prefetch */
 	li	r5,4
 
-#ifndef CONFIG_8xx
-#if MAX_L1_COPY_PREFETCH > 1
-	li	r0,MAX_L1_COPY_PREFETCH
+#if MAX_COPY_PREFETCH > 1
+	li	r0,MAX_COPY_PREFETCH
 	li	r11,4
 	mtctr	r0
 11:	dcbt	r11,r4
 	addi	r11,r11,L1_CACHE_LINE_SIZE
 	bdnz	11b
-#else /* MAX_L1_COPY_PREFETCH == 1 */
+#else /* MAX_COPY_PREFETCH == 1 */
 	dcbt	r5,r4
 	li	r11,L1_CACHE_LINE_SIZE+4
-#endif /* MAX_L1_COPY_PREFETCH */
-#endif /* CONFIG_8xx */
-
-	li	r0,4096/L1_CACHE_LINE_SIZE
+#endif /* MAX_COPY_PREFETCH */
+	li	r0,4096/L1_CACHE_LINE_SIZE - MAX_COPY_PREFETCH
+	crclr	4*cr0+eq
+2:
 	mtctr	r0
 1:
-#ifndef CONFIG_8xx
 	dcbt	r11,r4
 	dcbz	r5,r3
-#endif
 	COPY_16_BYTES
 #if L1_CACHE_LINE_SIZE >= 32
 	COPY_16_BYTES
@@ -732,7 +739,12 @@ _GLOBAL(copy_page)
 #endif
 #endif
 	bdnz	1b
-	blr
+	beqlr
+	crnot	4*cr0+eq,4*cr0+eq
+	li	r0,MAX_COPY_PREFETCH
+	li	r11,4
+	b	2b
+#endif	/* CONFIG_8xx */
 
 /*
  * Atomic [test&set] exchange
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ocp.c linux-2.4.26-pre6/arch/ppc/kernel/ocp.c
--- linux-2.4.25/arch/ppc/kernel/ocp.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/ocp.c	2004-03-25 00:20:09.000000000 +0000
@@ -37,6 +37,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/pm.h>
+#include <linux/bootmem.h>
 #include <asm/io.h>
 #include <asm/ocp.h>
 #include <asm/errno.h>
@@ -46,6 +47,8 @@
 //#define DBG(x)	printk x
 #define DBG(x)
 
+extern int mem_init_done;
+
 extern struct ocp_def core_ocp[];	/* Static list of devices, provided by
 					   CPU core */
 
@@ -152,9 +155,9 @@ ocp_bind_drivers(struct ocp_driver *cand
  *	@drv: pointer to statically defined ocp_driver structure
  *
  *	The driver's probe() callback is called either recursively
- *	by this function or upon later call of ocp_init
+ *	by this function or upon later call of ocp_driver_init
  *
- *      NOTE: Probe is called with ocp_drivers_sem heocp_find_deviceld, it shouldn't
+ *      NOTE: Probe is called with ocp_drivers_sem held, it shouldn't
  *      call ocp_register/unregister_driver on his own code path.
  *      however, it _can_ call ocp_find_device().
  *
@@ -231,27 +234,15 @@ ocp_unregister_driver(struct ocp_driver 
 	DBG(("ocp: ocp_unregister_driver(%s)... done.\n", drv->name));
 }
 
-/**
- *	ocp_find_device	-	Find a device by function & index
- *      @vendor: vendor ID of the device (or OCP_ANY_ID)
- *	@function: function code of the device (or OCP_ANY_ID)
- *	@idx: index of the device (or OCP_ANY_INDEX)
- *
- *	This function allows a lookup of a given function by it's
- *	index, it's typically used to find the MAL or ZMII associated
- *	with an EMAC or similar horrors.
- *      You can pass vendor, though you usually want OCP_ANY_ID there...
- */
-struct ocp_device *
-ocp_find_device(unsigned int vendor, unsigned int function, int index)
+/* Core of ocp_find_device(). Caller must hold ocp_devices_sem */
+static struct ocp_device *
+__ocp_find_device(unsigned int vendor, unsigned int function, int index)
 {
 	struct list_head	*entry;
 	struct ocp_device	*dev, *found = NULL;
 
-	DBG(("ocp: ocp_find_device(vendor: %x, function: %x, index: %d)...\n",
-		vendor, function, index));
+	DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
 
-	down_read(&ocp_devices_sem);
 	list_for_each(entry, &ocp_devices) {
 		dev = list_entry(entry, struct ocp_device, link);
 		if (vendor != OCP_ANY_ID && vendor != dev->def->vendor)
@@ -263,9 +254,60 @@ ocp_find_device(unsigned int vendor, uns
 		found = dev;
 		break;
 	}
+
+	DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)... done\n", vendor, function, index));
+
+	return found;
+}
+
+/**
+ *	ocp_find_device	-	Find a device by function & index
+ *      @vendor: vendor ID of the device (or OCP_ANY_ID)
+ *	@function: function code of the device (or OCP_ANY_ID)
+ *	@idx: index of the device (or OCP_ANY_INDEX)
+ *
+ *	This function allows a lookup of a given function by it's
+ *	index, it's typically used to find the MAL or ZMII associated
+ *	with an EMAC or similar horrors.
+ *      You can pass vendor, though you usually want OCP_ANY_ID there...
+ */
+struct ocp_device *
+ocp_find_device(unsigned int vendor, unsigned int function, int index)
+{
+	struct ocp_device	*dev;
+
+	down_read(&ocp_devices_sem);
+	dev = __ocp_find_device(vendor, function, index);
 	up_read(&ocp_devices_sem);
 
-	DBG(("ocp: ocp_find_device(vendor: %x, function: %x, index: %d)... done.\n",
+	return dev;
+}
+
+/**
+ *	ocp_get_one_device -	Find a def by function & index
+ *      @vendor: vendor ID of the device (or OCP_ANY_ID)
+ *	@function: function code of the device (or OCP_ANY_ID)
+ *	@idx: index of the device (or OCP_ANY_INDEX)
+ *
+ *	This function allows a lookup of a given ocp_def by it's
+ *	vendor, function, and index.  The main purpose for is to
+ *	allow modification of the def before binding to the driver
+ */
+struct ocp_def *
+ocp_get_one_device(unsigned int vendor, unsigned int function, int index)
+{
+	struct ocp_device	*dev;
+	struct ocp_def		*found = NULL;
+
+	DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n",
+		vendor, function, index));
+
+	dev = ocp_find_device(vendor, function, index);
+
+	if (dev) 
+		found = dev->def;
+
+	DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n",
 		vendor, function, index));
 
 	return found;
@@ -275,28 +317,80 @@ ocp_find_device(unsigned int vendor, uns
  *	ocp_add_one_device	-	Add a device
  *	@def: static device definition structure
  *
- *	This function is solely meant to be called by ocp_init
- *	to add one device from the core static list to the
- *	device list
+ *	This function adds a device definition to the
+ *	device list. It may only be called before
+ *	ocp_driver_init() and will return an error
+ *	otherwise.
  */
-static void
+int
 ocp_add_one_device(struct ocp_def *def)
 {
 	struct	ocp_device	*dev;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
+
+	/* Can't be called after ocp driver init */
+	if (ocp_inited)
+		return 1;
+
+	if (mem_init_done)
+		dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	else
+		dev = alloc_bootmem(sizeof(*dev));
+
 	if (dev == NULL)
-		return;
+		return 1;
 	memset(dev, 0, sizeof(*dev));
 	dev->def = def;
 	dev->current_state = 4;
 	sprintf(dev->name, "OCP device %04x:%04x:%04x",
 		dev->def->vendor, dev->def->function, dev->def->index);
+	down_write(&ocp_devices_sem);
 	list_add_tail(&dev->link, &ocp_devices);
+	up_write(&ocp_devices_sem);
+
+	DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...done.\n", vendor, function, index));
+
+	return 0;
+}
+
+/**
+ *	ocp_remove_one_device -	Remove a device by function & index
+ *      @vendor: vendor ID of the device (or OCP_ANY_ID)
+ *	@function: function code of the device (or OCP_ANY_ID)
+ *	@idx: index of the device (or OCP_ANY_INDEX)
+ *
+ *	This function allows removal of a given function by its
+ *	index. It may only be called before ocp_driver_init()
+ *	and will return an error otherwise.
+ */
+int
+ocp_remove_one_device(unsigned int vendor, unsigned int function, int index)
+{
+	struct ocp_device *dev;
+	int	rc = 0;
+
+	DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
+
+	/* Can't be called after ocp driver init */
+	if (ocp_inited)
+		return 1;
+
+	down_write(&ocp_devices_sem);
+	dev = __ocp_find_device(vendor, function, index);
+	if (dev != NULL)
+		list_del((struct list_head *)dev);
+	else
+		rc = 1;
+	up_write(&ocp_devices_sem);
+
+	DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
+
+	return rc;
 }
 
 #ifdef CONFIG_PM
-/*
+/**
  * OCP Power management..
  *
  * This needs to be done centralized, so that we power manage PCI
@@ -400,35 +494,49 @@ ppc4xx_cpm_fr(u32 bits, int val)
 #endif /* CONFIG_PM */
 
 /**
- *	ocp_init	-	Init OCP device management
+ *	ocp_early_init	-	Init OCP device management
  *
- *	This function is meant to be called once, and only once to initialize
- *	the OCP device management and build the list of devices. Note that
- *	it can actually be called at any time, it's perfectly legal to
- *	register drivers before ocp_init() is called
+ *	This function builds the list of devices before setup_arch. 
+ *	This allows platform code to modify the device lists before
+ *	they are bound to drivers (changes to paddr, removing devices
+ *	etc)
  */
-int
-ocp_init(void)
+int __init
+ocp_early_init(void)
 {
 	struct ocp_def	*def;
 
-	/* ocp_init is by default an initcall. If your arch requires this to
-	 * be called earlier, then go on, ocp_init is non-static for that purpose,
-	 * and can safely be called twice
-	 */
-	if (ocp_inited)
-		return 0;
-	ocp_inited = 1;
-
-	DBG(("ocp: ocp_init()...\n"));
+	DBG(("ocp: ocp_early_init()...\n"));
 
 	/* Fill the devices list */
-	down_write(&ocp_devices_sem);
 	for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++)
 		ocp_add_one_device(def);
-	up_write(&ocp_devices_sem);
 
-	DBG(("ocp: ocp_init()... added...\n"));
+	DBG(("ocp: ocp_early_init()... done.\n"));
+
+	return 0;
+}
+
+/**
+ *	ocp_driver_init	-	Init OCP device management
+ *
+ *	This function is meant to be called once, and only once to initialize
+ *	the OCP device management. Note that it can actually be called at any 
+ *	time, it's perfectly legal to register drivers before 
+ *	ocp_driver_init() is called
+ */
+int
+ocp_driver_init(void)
+{
+	/* ocp_driver_init is by default an initcall. If your arch requires 
+	 * this to be called earlier, then go on, ocp_driver_init is 
+	 * non-static for that purpose, and can safely be called twice
+	 */
+	if (ocp_inited)
+		return 0;
+	ocp_inited = 1;
+
+	DBG(("ocp: ocp_driver_init()...\n"));
 
 	/* Call drivers probes */
 	down(&ocp_drivers_sem);
@@ -439,12 +547,13 @@ ocp_init(void)
 	pm_register(PM_SYS_DEV, 0, ocp_pm_callback);
 #endif
 
-	DBG(("ocp: ocp_init()... done.\n"));
+	DBG(("ocp: ocp_driver_init()... done.\n"));
 
 	return 0;
 }
 
-__initcall(ocp_init);
+__initcall(ocp_driver_init);
 
+EXPORT_SYMBOL(ocp_find_device);
 EXPORT_SYMBOL(ocp_register_driver);
 EXPORT_SYMBOL(ocp_unregister_driver);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ppc4xx_stbdma.c linux-2.4.26-pre6/arch/ppc/kernel/ppc4xx_stbdma.c
--- linux-2.4.25/arch/ppc/kernel/ppc4xx_stbdma.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/ppc4xx_stbdma.c	2004-03-25 00:22:35.000000000 +0000
@@ -0,0 +1,134 @@
+/*
+ * arch/ppc/kernel/ppc4xx_stbdma.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IBM PPC4xx STBxxxx DMA Controller Functions
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         Armin Kuster <akuster@mvista.com>
+ *   
+ *   Based on ppc4xx_dma.c by
+ *         ppopov@mvista.com or source@mvista.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/ppc4xx_dma.h>
+
+int
+ppc4xx_clr_dma_status(unsigned int dmanr)
+{
+	unsigned int control;
+	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+	p_dma_ch->int_enable = 1;
+
+	switch (dmanr) {
+	case 0:
+		control = DMA_CS0 | DMA_CH0_ERR | DMA_CT0;	
+		break;
+	case 1:
+		control = DMA_CS1 | DMA_CH1_ERR | DMA_CT1;
+		break;
+	case 2:
+		control = DMA_CS2 | DMA_CH2_ERR | DMA_CT2;
+		break;
+	case 3:
+		control = DMA_CS3 | DMA_CH3_ERR | DMA_CT3;
+		break;
+	default:
+#ifdef DEBUG_4xxDMA
+		printk("ppc4xx_clr_dma_status: bad channel: %d\n", dmanr);
+#endif
+		return DMA_STATUS_BAD_CHANNEL;
+	}
+	mtdcr(DCRN_DMASR, control);
+	return DMA_STATUS_GOOD;
+}
+
+/*
+ * Maps a given port to a one of the dma
+ * channels
+ */
+int
+ppc4xx_map_dma_port(unsigned int dmanr, unsigned int ocp_dma,short dma_chan)
+{
+	unsigned int map;
+	int connect_port_to_chan, select; 
+
+	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+	
+	connect_port_to_chan = ((ocp_dma & 0x7)*4);
+	
+	select = ocp_dma >> 3;
+	switch (select) {
+	case 0:
+		map = mfdcr(DCRN_DMAS1);
+		map |= (connect_port_to_chan << dma_chan);	/* */
+		mtdcr(DCRN_DMAS1, map);
+		break;
+	case 1:
+		map = mfdcr(DCRN_DMAS2);
+		map |= (connect_port_to_chan << dma_chan);
+		mtdcr(DCRN_DMAS2, map);
+		break;
+	default:
+#ifdef DEBUG_4xxDMA
+		printk("map_dma_port: bad channel: %d\n", dmanr);
+#endif
+		return DMA_STATUS_BAD_CHANNEL;
+	}
+	return DMA_STATUS_GOOD;
+}
+
+int
+ppc4xx_disable_dma_port(unsigned int dmanr, unsigned int ocp_dma,short dma_chan)
+{
+	unsigned int map;
+	int connect_port_to_chan, select; 
+
+	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+	
+	connect_port_to_chan = ((ocp_dma & 0x7)*4);
+	
+	select = ocp_dma >> 3;
+	switch (select) {
+	case 0:
+		map = mfdcr(DCRN_DMAS1);
+		map &= ~(connect_port_to_chan << dma_chan);	/* */
+		mtdcr(DCRN_DMAS1, map);
+		break;
+	case 1:
+		map = mfdcr(DCRN_DMAS2);
+		map &= ~(connect_port_to_chan << dma_chan);
+		mtdcr(DCRN_DMAS2, map);
+		break;
+	default:
+#ifdef DEBUG_4xxDMA
+		printk("disable_dma_port: bad channel: %d\n", dmanr);
+#endif
+		return DMA_STATUS_BAD_CHANNEL;
+	}
+	return DMA_STATUS_GOOD;
+}
+
+EXPORT_SYMBOL(ppc4xx_disable_dma_port);
+EXPORT_SYMBOL(ppc4xx_map_dma_port);
+EXPORT_SYMBOL(ppc4xx_clr_dma_status);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ppc8260_pic.c linux-2.4.26-pre6/arch/ppc/kernel/ppc8260_pic.c
--- linux-2.4.25/arch/ppc/kernel/ppc8260_pic.c	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/ppc8260_pic.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,128 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <asm/irq.h>
-#include <asm/immap_8260.h>
-#include <asm/mpc8260.h>
-#include "ppc8260_pic.h"
-
-/* The 8260 internal interrupt controller.  It is usually
- * the only interrupt controller.
- * There are two 32-bit registers (high/low) for up to 64
- * possible interrupts.
- *
- * Now, the fun starts.....Interrupt Numbers DO NOT MAP
- * in a simple arithmetic fashion to mask or pending registers.
- * That is, interrupt 4 does not map to bit position 4.
- * We create two tables, indexed by vector number, to indicate
- * which register to use and which bit in the register to use.
- */
-static	u_char	irq_to_siureg[] = {
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static	u_char	irq_to_siubit[] = {
-	31, 16, 17, 18, 19, 20, 21, 22,
-	23, 24, 25, 26, 27, 28, 29, 30,
-	29, 30, 16, 17, 18, 19, 20, 21,
-	22, 23, 24, 25, 26, 27, 28, 31,
-	 0,  1,  2,  3,  4,  5,  6,  7,
-	 8,  9, 10, 11, 12, 13, 14, 15,
-	15, 14, 13, 12, 11, 10,  9,  8,
-	 7,  6,  5,  4,  3,  2,  1,  0
-};
-
-static void m8260_mask_irq(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr;
-
-	bit = irq_to_siubit[irq_nr];
-	word = irq_to_siureg[irq_nr];
-
-	simr = &(immr->im_intctl.ic_simrh);
-	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
-	simr[word] = ppc_cached_irq_mask[word];
-}
-
-static void m8260_unmask_irq(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr;
-
-	bit = irq_to_siubit[irq_nr];
-	word = irq_to_siureg[irq_nr];
-
-	simr = &(immr->im_intctl.ic_simrh);
-	ppc_cached_irq_mask[word] |= (1 << (31 - bit));
-	simr[word] = ppc_cached_irq_mask[word];
-}
-
-static void m8260_mask_and_ack(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr, *sipnr;
-
-	bit = irq_to_siubit[irq_nr];
-	word = irq_to_siureg[irq_nr];
-
-	simr = &(immr->im_intctl.ic_simrh);
-	sipnr = &(immr->im_intctl.ic_sipnrh);
-	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
-	simr[word] = ppc_cached_irq_mask[word];
-	sipnr[word] = 1 << (31 - bit);
-}
-
-static void m8260_end_irq(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr;
-
-	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-
-		bit = irq_to_siubit[irq_nr];
-		word = irq_to_siureg[irq_nr];
-
-		simr = &(immr->im_intctl.ic_simrh);
-		ppc_cached_irq_mask[word] |= (1 << (31 - bit));
-		simr[word] = ppc_cached_irq_mask[word];
-	}
-}
-
-struct hw_interrupt_type ppc8260_pic = {
-	" 8260 SIU  ",
-	NULL,
-	NULL,
-	m8260_unmask_irq,
-	m8260_mask_irq,
-	m8260_mask_and_ack,
-	m8260_end_irq,
-	0
-};
-
-/* Return an interrupt vector or -1 if no interrupt is pending. */
-int
-m8260_get_irq(struct pt_regs *regs)
-{
-	int irq;
-        unsigned long bits;
-
-        /* For MPC8260, read the SIVEC register and shift the bits down
-         * to get the irq number.         */
-        bits = immr->im_intctl.ic_sivec;
-        irq = bits >> 26;
-
-	if (irq == 0)	/* 0 --> no irq is pending */
-		irq = -1;
-
-	return irq;
-}
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ppc8260_pic.h linux-2.4.26-pre6/arch/ppc/kernel/ppc8260_pic.h
--- linux-2.4.25/arch/ppc/kernel/ppc8260_pic.h	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/ppc8260_pic.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,13 +0,0 @@
-#ifndef _PPC_KERNEL_PPC8260_H
-#define _PPC_KERNEL_PPC8260_H
-
-#include <linux/irq.h>
-
-extern struct hw_interrupt_type ppc8260_pic;
-
-void m8260_pic_init(void);
-void m8260_do_IRQ(struct pt_regs *regs,
-                 int            cpu);
-int m8260_get_irq(struct pt_regs *regs);
-
-#endif /* _PPC_KERNEL_PPC8260_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/setup.c linux-2.4.26-pre6/arch/ppc/kernel/setup.c
--- linux-2.4.25/arch/ppc/kernel/setup.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/kernel/setup.c	2004-03-25 00:22:06.000000000 +0000
@@ -603,6 +603,12 @@ void __init setup_arch(char **cmdline_p)
 	do_init_bootmem();
 	if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
 
+#ifdef CONFIG_PPC_OCP
+	/* Initialize OCP device list */
+	ocp_early_init();
+	if ( ppc_md.progress ) ppc_md.progress("setup_arch: ocp_early_init", 0x3eab);
+#endif
+
 	ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/lib/string.S linux-2.4.26-pre6/arch/ppc/lib/string.S
--- linux-2.4.25/arch/ppc/lib/string.S	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/lib/string.S	2004-03-25 00:20:30.000000000 +0000
@@ -62,13 +62,14 @@
 	.text
 
 	.text
+	.stabs	"arch/ppc/lib/",N_SO,0,0,0f
+	.stabs	"string.S",N_SO,0,0,0f
 
 CACHELINE_BYTES = L1_CACHE_LINE_SIZE
 LG_CACHELINE_BYTES = LG_L1_CACHE_LINE_SIZE
 CACHELINE_MASK = (L1_CACHE_LINE_SIZE-1)
 
-	.globl	strcpy
-strcpy:
+_GLOBAL(strcpy)
 	addi	r5,r3,-1
 	addi	r4,r4,-1
 1:	lbzu	r0,1(r4)
@@ -79,8 +80,7 @@ strcpy:
 
 /* This clears out any unused part of the destination buffer,
    just as the libc version does.  -- paulus */
-	.globl	strncpy
-strncpy:
+_GLOBAL(strncpy)
 	cmpwi	0,r5,0
 	beqlr
 	mtctr	r5
@@ -98,8 +98,7 @@ strncpy:
 	bdnz	2b
 	blr
 
-	.globl	strcat
-strcat:
+_GLOBAL(strcat)
 	addi	r5,r3,-1
 	addi	r4,r4,-1
 1:	lbzu	r0,1(r5)
@@ -112,8 +111,7 @@ strcat:
 	bne	1b
 	blr
 
-	.globl	strcmp
-strcmp:
+_GLOBAL(strcmp)
 	addi	r5,r3,-1
 	addi	r4,r4,-1
 1:	lbzu	r3,1(r5)
@@ -124,8 +122,7 @@ strcmp:
 	beq	1b
 	blr
 
-	.globl	strlen
-strlen:
+_GLOBAL(strlen)
 	addi	r4,r3,-1
 1:	lbzu	r0,1(r4)
 	cmpwi	0,r0,0
@@ -138,8 +135,7 @@ strlen:
  * to set them to zero.  This requires that the destination
  * area is cacheable.  -- paulus
  */
-	.globl	cacheable_memzero
-cacheable_memzero:
+_GLOBAL(cacheable_memzero)
 	mr	r5,r4
 	li	r4,0
 	addi	r6,r3,-4
@@ -189,8 +185,7 @@ cacheable_memzero:
 	bdnz	8b
 	blr
 
-	.globl	memset
-memset:
+_GLOBAL(memset)
 	rlwimi	r4,r4,8,16,23
 	rlwimi	r4,r4,16,0,15
 	addi	r6,r3,-4
@@ -215,8 +210,7 @@ memset:
 	bdnz	8b
 	blr
 
-	.globl	bcopy
-bcopy:
+_GLOBAL(bcopy)
 	mr	r6,r3
 	mr	r3,r4
 	mr	r4,r6
@@ -229,8 +223,7 @@ bcopy:
  * We only use this version if the source and dest don't overlap.
  * -- paulus.
  */
-	.global	cacheable_memcpy
-cacheable_memcpy:
+_GLOBAL(cacheable_memcpy)
 	add	r7,r3,r5		/* test if the src & dst overlap */
 	add	r8,r4,r5
 	cmplw	0,r4,r7
@@ -304,14 +297,12 @@ cacheable_memcpy:
 	bdnz	40b
 65:	blr
 
-	.globl	memmove
-memmove:
+_GLOBAL(memmove)
 	cmplw	0,r3,r4
 	bgt	backwards_memcpy
 	/* fall through */
 
-	.globl	memcpy
-memcpy:
+_GLOBAL(memcpy)
 	srwi.	r7,r5,3
 	addi	r6,r3,-4
 	addi	r4,r4,-4
@@ -352,8 +343,7 @@ memcpy:
 	mtctr	r7
 	b	1b
 
-	.globl	backwards_memcpy
-backwards_memcpy:
+_GLOBAL(backwards_memcpy)
 	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
 	add	r6,r3,r5
 	add	r4,r4,r5
@@ -389,8 +379,7 @@ backwards_memcpy:
 	mtctr	r7
 	b	1b
 
-	.globl	memcmp
-memcmp:
+_GLOBAL(memcmp)
 	cmpwi	0,r5,0
 	ble-	2f
 	mtctr	r5
@@ -404,8 +393,7 @@ memcmp:
 2:	li	r3,0
 	blr
 
-	.global	memchr
-memchr:
+_GLOBAL(memchr)
 	cmpwi	0,r5,0
 	ble-	2f
 	mtctr	r5
@@ -417,8 +405,7 @@ memchr:
 2:	li	r3,0
 	blr
 
-	.globl	__copy_tofrom_user
-__copy_tofrom_user:
+_GLOBAL(__copy_tofrom_user)
 	addi	r4,r4,-4
 	addi	r6,r3,-4
 	neg	r0,r3
@@ -443,48 +430,57 @@ __copy_tofrom_user:
 73:	stwu	r9,4(r6)
 	bdnz	72b
 
+	.section __ex_table,"a"
+	.align	2
+	.long	70b,100f
+	.long	71b,101f
+	.long	72b,102f
+	.long	73b,103f
+	.text
+
 58:	srwi.	r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
 	clrlwi	r5,r5,32-LG_CACHELINE_BYTES
 	li	r11,4
 	beq	63f
 
-#if !defined(CONFIG_8xx)
+#ifdef CONFIG_8xx
+	/* Don't use prefetch on 8xx */
+	mtctr	r0
+53:	COPY_16_BYTES_WITHEX(0)
+	bdnz	53b
+
+#else /* not CONFIG_8xx */
 	/* Here we decide how far ahead to prefetch the source */
+	li	r3,4
+	cmpwi	r0,1
+	li	r7,0
+	ble	114f
+	li	r7,1
 #if MAX_COPY_PREFETCH > 1
 	/* Heuristically, for large transfers we prefetch
 	   MAX_COPY_PREFETCH cachelines ahead.  For small transfers
 	   we prefetch 1 cacheline ahead. */
 	cmpwi	r0,MAX_COPY_PREFETCH
-	li	r7,1
-	li	r3,4
-	ble	111f
+	ble	112f
 	li	r7,MAX_COPY_PREFETCH
-111:	mtctr	r7
-112:	dcbt	r3,r4
+112:	mtctr	r7
+111:	dcbt	r3,r4
 	addi	r3,r3,CACHELINE_BYTES
-	bdnz	112b
-#else /* MAX_COPY_PREFETCH == 1 */
-	li	r3,CACHELINE_BYTES + 4
-	dcbt	r11,r4
-#endif /* MAX_COPY_PREFETCH */
-#endif /* CONFIG_8xx */
-
-	mtctr	r0
-53:
-#if !defined(CONFIG_8xx)
+	bdnz	111b
+#else
 	dcbt	r3,r4
+	addi	r3,r3,CACHELINE_BYTES
+#endif /* MAX_COPY_PREFETCH > 1 */
+
+114:	subf	r8,r7,r0
+	mr	r0,r7
+	mtctr	r8
+
+53:	dcbt	r3,r4
 54:	dcbz	r11,r6
-#endif
-/* had to move these to keep extable in order */
 	.section __ex_table,"a"
 	.align	2
-	.long	70b,100f
-	.long	71b,101f
-	.long	72b,102f
-	.long	73b,103f
-#if !defined(CONFIG_8xx)
 	.long	54b,105f
-#endif
 	.text
 /* the main body of the cacheline loop */
 	COPY_16_BYTES_WITHEX(0)
@@ -502,6 +498,11 @@ __copy_tofrom_user:
 #endif
 #endif
 	bdnz	53b
+	cmpwi	r0,0
+	li	r3,4
+	li	r7,0
+	bne	114b
+#endif /* CONFIG_8xx */	
 
 63:	srwi.	r0,r5,2
 	mtctr	r0
@@ -624,8 +625,7 @@ __copy_tofrom_user:
 	.long	114b,120b
 	.text
 
-	.globl	__clear_user
-__clear_user:
+_GLOBAL(__clear_user)
 	addi	r6,r3,-4
 	li	r3,0
 	li	r5,0
@@ -668,8 +668,7 @@ __clear_user:
 	.long	8b,92b
 	.text
 
-	.globl	__strncpy_from_user
-__strncpy_from_user:
+_GLOBAL(__strncpy_from_user)
 	addi	r6,r3,-1
 	addi	r4,r4,-1
 	cmpwi	0,r5,0
@@ -692,8 +691,7 @@ __strncpy_from_user:
 	.text
 
 /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
-	.globl	__strnlen_user
-__strnlen_user:
+_GLOBAL(__strnlen_user)
 	addi	r7,r3,-1
 	subf	r6,r7,r5	/* top+1 - str */
 	cmplw	0,r4,r6
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/Makefile linux-2.4.26-pre6/arch/ppc/platforms/Makefile
--- linux-2.4.25/arch/ppc/platforms/Makefile	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/Makefile	2004-03-25 00:22:36.000000000 +0000
@@ -33,6 +33,9 @@ obj-$(CONFIG_440GP)		+= ibm440gp.o
 obj-$(CONFIG_440GX)		+= ibm440gx.o
 
 obj-$(CONFIG_CPCI405)		+= cpci405.o
+obj-$(CONFIG_EP405)		+= ep405.o
+obj-$(CONFIG_REDWOOD_5)		+= redwood5.o ibmstb4.o
+obj-$(CONFIG_REDWOOD_6)		+= redwood6.o ibmstbx25.o
 obj-$(CONFIG_EBONY)		+= ebony.o
 obj-$(CONFIG_OCOTEA)		+= ocotea.o
 obj-$(CONFIG_WALNUT)		+= walnut.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ep405.c linux-2.4.26-pre6/arch/ppc/platforms/ep405.c
--- linux-2.4.25/arch/ppc/platforms/ep405.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/ep405.c	2004-03-25 00:18:07.000000000 +0000
@@ -0,0 +1,196 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ *
+ *    Copyright 2001 MontaVista Software Inc.
+ *        <mlocke@mvista.com>
+ *
+ * 	Not much needed for the Embedded Planet 405gp board
+ *
+ *  	History: 11/09/2001 - armin
+ *      added board_init to add in additional instuctions needed during platfrom_init
+ *	cleaned up map_irq.
+ *	 
+ *	1/22/2002 - Armin
+ *      converted pci to ocp
+ *
+ * Please read the COPYING file for all license details.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <platforms/ibm_ocp.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u8 *ep405_bcsr;
+u8 *ep405_nvram;
+
+static struct {
+	u8 cpld_xirq_select;
+	int pci_idsel;
+	int irq;
+} ep405_devtable[] = {
+#ifdef CONFIG_EP405PC
+	{0x07, 0x0E, 25},		/* EP405PC: USB */
+#endif
+};
+#define EP405_DEVTABLE_SIZE (sizeof(ep405_devtable)/sizeof(ep405_devtable[0]))
+
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	int i;
+
+	/* AFAICT this is only called a few times during PCI setup, so
+	   performance is not critical */
+	for (i = 0; i < EP405_DEVTABLE_SIZE; i++) {
+		if (idsel == ep405_devtable[i].pci_idsel)
+			return ep405_devtable[i].irq;
+	}
+	return -1;
+};
+
+void __init
+board_setup_arch(void)
+{
+	bd_t *bip = (bd_t *) __res;
+
+	if (bip->bi_nvramsize == 512*1024) {
+		/* FIXME: we should properly handle NVRTCs of different sizes */
+		TODC_INIT(TODC_TYPE_DS1557, ep405_nvram, ep405_nvram, ep405_nvram, 8);
+	}
+}
+
+#ifdef CONFIG_PCI
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+	unsigned int bar_response, bar;
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 */
+
+	/* Disable region zero first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000000);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Configure PTM (PCI->PLB) region 1 */
+	out_le32((void *) &(pcip->ptm1la), 0x00000000); /* PLB base address */
+	/* Disable PTM region 2 */
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+	/* end work arround */
+}
+#endif
+
+void __init
+board_io_mapping(void)
+{
+	bd_t *bip = (bd_t *) __res;
+
+	ep405_bcsr = ioremap(EP405_BCSR_PADDR, EP405_BCSR_SIZE);
+
+	if (bip->bi_nvramsize > 0) {
+		ep405_nvram = ioremap(EP405_NVRAM_PADDR, bip->bi_nvramsize);
+	}
+}
+
+void __init
+board_setup_irq(void)
+{
+	int i;
+
+	/* Workaround for a bug in the firmware it incorrectly sets
+	   the IRQ polarities for XIRQ0 and XIRQ1 */
+	mtdcr(DCRN_UIC_PR(DCRN_UIC0_BASE), 0xffffff80); /* set the polarity */
+	mtdcr(DCRN_UIC_SR(DCRN_UIC0_BASE), 0x00000060); /* clear bogus interrupts */
+
+	/* Activate the XIRQs from the CPLD */
+	writeb(0xf0, ep405_bcsr+10);
+
+	/* Set up IRQ routing */
+	for (i = 0; i < EP405_DEVTABLE_SIZE; i++) {
+		if ( (ep405_devtable[i].irq >= 25)
+		     && (ep405_devtable[i].irq) <= 31) {
+			writeb(ep405_devtable[i].cpld_xirq_select, ep405_bcsr+5);
+			writeb(ep405_devtable[i].irq - 25, ep405_bcsr+6);
+		}
+	}
+}
+
+void __init
+board_init(void)
+{
+	bd_t *bip = (bd_t *) __res;
+
+#ifdef CONFIG_PPC_RTC
+	/* FIXME: we should be able to access the NVRAM even if PPC_RTC is not configured */
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+	if (bip->bi_nvramsize == 512*1024) {
+		ppc_md.time_init = todc_time_init;
+		ppc_md.set_rtc_time = todc_set_rtc_time;
+		ppc_md.get_rtc_time = todc_get_rtc_time;
+	} else {
+		printk("EP405: NVRTC size is not 512k (not a DS1557).  Not sure what to do with it\n");
+	}
+
+#endif
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ep405.h linux-2.4.26-pre6/arch/ppc/platforms/ep405.h
--- linux-2.4.25/arch/ppc/platforms/ep405.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/ep405.h	2004-03-25 00:20:52.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ *    Copyright 2000 MontaVista Software Inc.
+ *    	http://www.mvista.com
+ *	<mlocke@mvista.com>
+ *
+ *         Embedded Planet 405GP board
+ *         http://www.embeddedplanet.com
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_EP405_H__
+#define __ASM_EP405_H__
+
+/* We have a 405GP core */
+#include <platforms/ibm405gp.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+	unsigned int	 bi_nvramsize;		/* Size of the NVRAM/RTC */
+	unsigned int	 bi_opb_busfreq;	/* OPB Bus speed, in Hz */
+	int		 bi_iic_fast[1];	/* Use fast i2c mode */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+extern u8 *ep405_bcsr;
+extern u8 *ep405_nvram;
+
+/* Map for the BCSR and NVRAM space */
+#define EP405_BCSR_PADDR	((uint)0xf4000000)
+#define EP405_BCSR_SIZE		((uint)16)
+#define EP405_NVRAM_PADDR	((uint)0xf4200000)
+
+/* serial defines */
+#define BASE_BAUD		399193
+
+#define PPC4xx_MACHINE_NAME "Embedded Planet 405GP"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_EP405_H__ */
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/est8260.h linux-2.4.26-pre6/arch/ppc/platforms/est8260.h
--- linux-2.4.25/arch/ppc/platforms/est8260.h	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/est8260.h	2004-03-25 00:21:12.000000000 +0000
@@ -4,7 +4,7 @@
  * the configuration SCMR and the Power-On-Reset word.
  */
 
-#define IMAP_ADDR	((uint)0xf0000000)
+#define CPM_MAP_ADDR	((uint)0xf0000000)
 
 
 /* A Board Information structure that is given to a program when
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ibmstb4.c linux-2.4.26-pre6/arch/ppc/platforms/ibmstb4.c
--- linux-2.4.25/arch/ppc/platforms/ibmstb4.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/ibmstb4.c	2004-03-25 00:19:32.000000000 +0000
@@ -0,0 +1,101 @@
+/*
+ *
+ *    Copyright 2000-2001 MontaVista Software Inc.
+ *      Completed implementation.
+ *	Current maintainer
+ *      Armin Kuster akuster@mvista.com
+ *
+ *    Module name: ibmstb4.c
+ *
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *      History: 12/26/2001 - armin
+ *		initial release
+ *
+ *		: 05/05/02 - Armin
+ *		  replaced all const strcuts with new core_ocp
+ *
+ *		: 07/07/02 - Armin
+ *		added OCP_IRQ_MUL to define EMAC
+ *		and added PM register
+ *
+ */
+
+#include <linux/init.h>
+#include <platforms/ibmstb4.h>
+#include <asm/ocp.h>
+
+struct ocp_def core_ocp[] __initdata = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= UART2_IO_BASE,
+	  .irq		= UART2_INT,
+	  .pm		= IBM_CPM_UART2,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= IIC0_BASE,
+	  .irq		= IIC0_IRQ,
+	  .pm		= IBM_CPM_IIC0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= IIC1_BASE,
+	  .irq		= IIC1_IRQ,
+	  .pm		= IBM_CPM_IIC1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= GPIO0_BASE,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IDE,
+	  .paddr	= IDE0_BASE,
+	  .irq		= IDE0_IRQ,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_USB,
+	  .paddr	= USB0_BASE,
+	  .irq		= USB0_IRQ,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID,
+	}
+};
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ibmstb4.h linux-2.4.26-pre6/arch/ppc/platforms/ibmstb4.h
--- linux-2.4.25/arch/ppc/platforms/ibmstb4.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/ibmstb4.h	2004-03-25 00:20:06.000000000 +0000
@@ -0,0 +1,285 @@
+/*
+ * ibmstb4.h
+ *
+ *	This was dirived from the ibm405gp.h and other previus works in ppc4xx.h
+ *
+ *      Current maintainer
+ *      Armin Kuster akuster@mvista.com
+ *      DEC, 2001
+ *
+ *
+ * Copyright 2001 MontaVista Softare Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	Version 1.0 (01/10/10) - A. Kuster
+ *	Initial version	
+ *
+ *	Version 1.1 02/01/17 - A. Kuster
+ *	moved common offsets to ibm405.h
+ *
+ *	Version 1.2 02/22/02 - A. Kuster
+ *	Added UIC and
+ *	Added early serial boot #define support - David G.
+ *	fixed __BOOTER__ 
+ *
+ *	Version 1.3 03/29/02 - Armin
+ *	Added i2c & usb ocp support
+ *
+ *	Version 1.4 04/30/02 - Armin
+ *		Added IIC_PORT_DFNS macros
+ *	Version 1.5 - 05/05/02 _ armin
+ *		removed IIC_PORT now using core_ocp[]
+ *
+ *	Version 1.6 07/22/02 - Armin
+ *	added default power managment setting
+ *
+ *	
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMSTB4_H__
+#define __ASM_IBMSTB4_H__
+
+#include <linux/config.h>
+#include <platforms/ibm_ocp.h>
+
+/* serial port defines */
+#define STB04xxx_IO_BASE	((uint)0xe0000000)
+#define PPC4xx_PCI_IO_ADDR	STB04xxx_IO_BASE
+#define PPC4xx_ONB_IO_PADDR	STB04xxx_IO_BASE
+#define PPC4xx_ONB_IO_VADDR	((uint)0xe0000000)
+#define PPC4xx_ONB_IO_SIZE	((uint)14*64*1024)
+
+/*
+ * map STB04xxx internal i/o address (0x400x00xx) to an address
+ * which is below the 2GB limit...
+ *
+ * 4000 000x	uart1		-> 0xe000 000x
+ * 4001 00xx	ppu
+ * 4002 00xx	smart card
+ * 4003 000x	iic
+ * 4004 000x	uart0
+ * 4005 0xxx	timer
+ * 4006 00xx	gpio
+ * 4007 00xx	smart card
+ * 400b 000x	iic
+ * 400c 000x	scp
+ * 400d 000x	modem
+ * 400e 000x	uart2
+*/
+#define STB04xxx_MAP_IO_ADDR(a)	(((uint)(a)) + (STB04xxx_IO_BASE - 0x40000000))
+
+#define RS_TABLE_SIZE		3
+#define UART0_INT		20
+
+#ifdef __BOOTER__
+#define UART0_IO_BASE		0x40040000
+#else
+#define UART0_IO_BASE		0xe0040000
+#endif
+
+#define UART1_INT		21
+
+#ifdef __BOOTER__
+#define UART1_IO_BASE		0x40000000
+#else
+#define UART1_IO_BASE		0xe0000000
+#endif
+
+#define UART2_INT		31
+#ifdef __BOOTER__
+#define UART2_IO_BASE		0x400e0000
+#else
+#define UART2_IO_BASE		0xe00e0000
+#endif
+
+#define IDE0_BASE	0x400F0000
+#define IDE0_SIZE	0x200
+#define IDE0_IRQ	25
+#define IIC0_BASE	0x40030000
+#define IIC1_BASE	0x400b0000
+#define OPB0_BASE	0x40000000
+#define GPIO0_BASE	0x40060000
+
+#define USB0_IRQ	18
+#define USB0_BASE	STB04xxx_MAP_IO_ADDR(0x40010000)
+#define USB0_EXTENT 4096
+
+#define IIC_NUMS 2
+#define UART_NUMS	3
+#define IIC0_IRQ	9
+#define IIC1_IRQ	10
+#define IIC_OWN		0x55
+#define IIC_CLOCK	50
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(1)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS2)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(2)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+#endif
+
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRNCAP_DMA_CC		1	/* have DMA chained count capability */
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_PLB0_BASE		0x054
+#define DCRN_PLB1_BASE		0x064
+#define DCRN_POB0_BASE		0x0B0
+#define DCRN_SCCR_BASE		0x120
+#define DCRN_UIC0_BASE		0x040
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRN_CIC_BASE 		0x030
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_EBIMC_BASE		0x070
+#define DCRN_DCRX_BASE		0x020
+#define DCRN_CPMFR_BASE		0x102
+#define DCRN_SCCR_BASE		0x120
+#define UIC0 DCRN_UIC0_BASE
+
+#define IBM_CPM_IIC0	0x80000000	/* IIC 0 interface */
+#define IBM_CPM_USB0	0x40000000	/* IEEE-1284 */
+#define IBM_CPM_IIC1	0x20000000	/* IIC 1 interface */
+#define IBM_CPM_CPU	0x10000000	/* PPC405B3 clock control */
+#define IBM_CPM_AUD	0x08000000	/* Audio Decoder */
+#define IBM_CPM_EBIU	0x04000000	/* External Bus Interface Unit */
+#define IBM_CPM_SDRAM1	0x02000000	/* SDRAM 1 memory controller */
+#define IBM_CPM_DMA	0x01000000	/* DMA controller */
+#define IBM_CPM_DMA1	0x00800000	/* reserved */
+#define IBM_CPM_XPT1	0x00400000	/* reserved */
+#define IBM_CPM_XPT2	0x00200000	/* reserved */
+#define IBM_CPM_UART1	0x00100000	/* Serial 1 / Infrared */
+#define IBM_CPM_UART0	0x00080000	/* Serial 0 / 16550 */
+#define IBM_CPM_EPI	0x00040000	/* DCR Extension */
+#define IBM_CPM_SC0	0x00020000	/* Smart Card 0 */
+#define IBM_CPM_VID	0x00010000	/* reserved */
+#define IBM_CPM_SC1	0x00008000	/* Smart Card 1 */
+#define IBM_CPM_USBSDRA	0x00004000	/* SDRAM 0 memory controller */
+#define IBM_CPM_XPT0	0x00002000	/* Transport - 54 Mhz */
+#define IBM_CPM_CBS	0x00001000	/* Cross Bar Switch */
+#define IBM_CPM_GPT	0x00000800	/* GPTPWM */
+#define IBM_CPM_GPIO0	0x00000400	/* General Purpose IO 0 */
+#define IBM_CPM_DENC	0x00000200	/* Digital video Encoder */
+#define IBM_CPM_TMRCLK	0x00000100	/* CPU timers */
+#define IBM_CPM_XPT27	0x00000080	/* Transport - 27 Mhz */
+#define IBM_CPM_UIC	0x00000040	/* Universal Interrupt Controller */
+#define IBM_CPM_SSP	0x00000010	/* Modem Serial Interface (SSP) */
+#define IBM_CPM_UART2	0x00000008	/* Serial Control Port */
+#define IBM_CPM_DDIO	0x00000004	/* Descrambler */
+#define IBM_CPM_VID2	0x00000002	/* Video Decoder clock domain 2 */
+
+#define DFLT_IBM4xx_PM	~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_SDRAM1 \
+			| IBM_CPM_DMA | IBM_CPM_DMA1 | IBM_CPM_CBS \
+			| IBM_CPM_USBSDRA | IBM_CPM_XPT0 | IBM_CPM_TMRCLK \
+			| IBM_CPM_XPT27 | IBM_CPM_UIC )
+
+#define DCRN_BEAR	(DCRN_BE_BASE + 0x0)	/* Bus Error Address Register */
+#define DCRN_BESR	(DCRN_BE_BASE + 0x1)	/* Bus Error Syndrome Register */
+/* DCRN_BESR */
+#define BESR_DSES	0x80000000	/* Data-Side Error Status */
+#define BESR_DMES	0x40000000	/* DMA Error Status */
+#define BESR_RWS	0x20000000	/* Read/Write Status */
+#define BESR_ETMASK	0x1C000000	/* Error Type */
+#define ET_PROT		0
+#define ET_PARITY	1
+#define ET_NCFG		2
+#define ET_BUSERR	4
+#define ET_BUSTO	6
+
+#define CHR1_CETE	0x00800000	/* CPU external timer enable */
+#define CHR1_PCIPW	0x00008000	/* PCI Int enable/Peripheral Write enable */
+
+#define DCRN_CICCR	(DCRN_CIC_BASE + 0x0)	/* CIC Control Register */
+#define DCRN_DMAS1	(DCRN_CIC_BASE + 0x1)	/* DMA Select1 Register */
+#define DCRN_DMAS2	(DCRN_CIC_BASE + 0x2)	/* DMA Select2 Register */
+#define DCRN_CICVCR	(DCRN_CIC_BASE + 0x3)	/* CIC Video COntro Register */
+#define DCRN_CICSEL3	(DCRN_CIC_BASE + 0x5)	/* CIC Select 3 Register */
+#define DCRN_SGPO	(DCRN_CIC_BASE + 0x6)	/* CIC GPIO Output Register */
+#define DCRN_SGPOD	(DCRN_CIC_BASE + 0x7)	/* CIC GPIO OD Register */
+#define DCRN_SGPTC	(DCRN_CIC_BASE + 0x8)	/* CIC GPIO Tristate Ctrl Reg */
+#define DCRN_SGPI	(DCRN_CIC_BASE + 0x9)	/* CIC GPIO Input Reg */
+
+#define DCRN_DCRXICR	(DCRN_DCRX_BASE + 0x0)	/* Internal Control Register */
+#define DCRN_DCRXISR	(DCRN_DCRX_BASE + 0x1)	/* Internal Status Register */
+#define DCRN_DCRXECR	(DCRN_DCRX_BASE + 0x2)	/* External Control Register */
+#define DCRN_DCRXESR	(DCRN_DCRX_BASE + 0x3)	/* External Status Register */
+#define DCRN_DCRXTAR	(DCRN_DCRX_BASE + 0x4)	/* Target Address Register */
+#define DCRN_DCRXTDR	(DCRN_DCRX_BASE + 0x5)	/* Target Data Register */
+#define DCRN_DCRXIGR	(DCRN_DCRX_BASE + 0x6)	/* Interrupt Generation Register */
+#define DCRN_DCRXBCR	(DCRN_DCRX_BASE + 0x7)	/* Line Buffer Control Register */
+
+#define DCRN_BRCRH0	(DCRN_EBIMC_BASE + 0x0)	/* Bus Region Config High 0 */
+#define DCRN_BRCRH1	(DCRN_EBIMC_BASE + 0x1)	/* Bus Region Config High 1 */
+#define DCRN_BRCRH2	(DCRN_EBIMC_BASE + 0x2)	/* Bus Region Config High 2 */
+#define DCRN_BRCRH3	(DCRN_EBIMC_BASE + 0x3)	/* Bus Region Config High 3 */
+#define DCRN_BRCRH4	(DCRN_EBIMC_BASE + 0x4)	/* Bus Region Config High 4 */
+#define DCRN_BRCRH5	(DCRN_EBIMC_BASE + 0x5)	/* Bus Region Config High 5 */
+#define DCRN_BRCRH6	(DCRN_EBIMC_BASE + 0x6)	/* Bus Region Config High 6 */
+#define DCRN_BRCRH7	(DCRN_EBIMC_BASE + 0x7)	/* Bus Region Config High 7 */
+#define DCRN_BRCR0	(DCRN_EBIMC_BASE + 0x10)	/* BRC 0 */
+#define DCRN_BRCR1	(DCRN_EBIMC_BASE + 0x11)	/* BRC 1 */
+#define DCRN_BRCR2	(DCRN_EBIMC_BASE + 0x12)	/* BRC 2 */
+#define DCRN_BRCR3	(DCRN_EBIMC_BASE + 0x13)	/* BRC 3 */
+#define DCRN_BRCR4	(DCRN_EBIMC_BASE + 0x14)	/* BRC 4 */
+#define DCRN_BRCR5	(DCRN_EBIMC_BASE + 0x15)	/* BRC 5 */
+#define DCRN_BRCR6	(DCRN_EBIMC_BASE + 0x16)	/* BRC 6 */
+#define DCRN_BRCR7	(DCRN_EBIMC_BASE + 0x17)	/* BRC 7 */
+#define DCRN_BEAR0	(DCRN_EBIMC_BASE + 0x20)	/* Bus Error Address Register */
+#define DCRN_BESR0	(DCRN_EBIMC_BASE + 0x21)	/* Bus Error Status Register */
+#define DCRN_BIUCR	(DCRN_EBIMC_BASE + 0x2A)	/* Bus Interfac Unit Ctrl Reg */
+
+#include <platforms/ibm405.h>
+
+#endif				/* __ASM_IBMSTB4_H__ */
+#endif				/* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ibmstbx25.c linux-2.4.26-pre6/arch/ppc/platforms/ibmstbx25.c
--- linux-2.4.25/arch/ppc/platforms/ibmstbx25.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/ibmstbx25.c	2004-03-25 00:22:32.000000000 +0000
@@ -0,0 +1,77 @@
+/*
+ *
+ *    Copyright 2000-2002 MontaVista Software Inc.
+ *      Completed implementation.
+ *	Current maintainer
+ *      Armin Kuster akuster@mvista.com
+ *
+ *    Module name: ibmstbx25.c
+ *
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *      History: July 10, 2002 - armin
+ *		initial release
+ *
+ *
+ */
+
+#include <linux/init.h>
+#include <platforms/ibmstbx25.h>
+#include <asm/ocp.h>
+
+struct ocp_def core_ocp[] __initdata = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index        = 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= UART2_IO_BASE,
+	  .irq		= UART2_INT,
+	  .pm		= IBM_CPM_UART2,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= IIC0_BASE,
+	  .irq		= IIC0_IRQ,
+	  .pm		= IBM_CPM_IIC0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= GPIO0_BASE,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ibmstbx25.h linux-2.4.26-pre6/arch/ppc/platforms/ibmstbx25.h
--- linux-2.4.25/arch/ppc/platforms/ibmstbx25.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/ibmstbx25.h	2004-03-25 00:16:53.000000000 +0000
@@ -0,0 +1,287 @@
+/*
+ * ibmstbx25.h
+ *
+ *      Current maintainer
+ *      Armin Kuster akuster@mvista.com
+ *      July, 2002
+ *
+ *
+ * Copyright 2002 MontaVista Softare Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	Version 1.0 July 10, 2002 - A. Kuster
+ *	Initial version	
+ *
+ *	Version 1.1 July 24, 02 - Armin
+ *	added Power Managment defines
+ *
+ *	
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMSTBX25_H__
+#define __ASM_IBMSTBX25_H__
+
+#include <linux/config.h>
+#include <platforms/ibm_ocp.h>
+
+/* serial port defines */
+#define STBx25xx_IO_BASE	((uint)0xe0000000)
+#define PPC4xx_ONB_IO_PADDR	STBx25xx_IO_BASE
+#define PPC4xx_ONB_IO_VADDR	((uint)0xe0000000)
+#define PPC4xx_ONB_IO_SIZE	((uint)14*64*1024)
+
+/*
+ * map STBxxxx internal i/o address (0x400x00xx) to an address
+ * which is below the 2GB limit...
+ *
+ * 4000 000x	uart1		-> 0xe000 000x
+ * 4001 00xx	uart2
+ * 4002 00xx	smart card
+ * 4003 000x	iic
+ * 4004 000x	uart0
+ * 4005 0xxx	timer
+ * 4006 00xx	gpio
+ * 4007 00xx	smart card
+ * 400b 000x	iic
+ * 400c 000x	scp
+ * 400d 000x	modem
+ * 400e 000x	uart2
+*/
+#define STBx25xx_MAP_IO_ADDR(a)	(((uint)(a)) + (STBx25xx_IO_BASE - 0x40000000))
+
+#define RS_TABLE_SIZE	3
+
+#ifdef __BOOTER__
+#define UART1_IO_BASE	0x40000000
+#define UART2_IO_BASE	0x40010000
+#else
+#define UART1_IO_BASE	0xe0000000
+#define UART2_IO_BASE	0xe0010000
+#endif
+#define SC0_BASE	0x40020000	/* smart card #0 */
+#define IIC0_BASE	0x40030000
+#ifdef __BOOTER__
+#define UART0_IO_BASE	0x40040000
+#else
+#define UART0_IO_BASE	0xe0040000
+#endif
+#define SCC0_BASE	0x40040000	/* Serial 0 controller IrdA */
+#define GPT0_BASE	0x40050000	/* General purpose timers */
+#define OPB0_BASE	0x40000000
+#define GPIO0_BASE	0x40060000
+#define SC0_base	0x40070000	/* smart card #1 */
+#define SCP0_base	0x400C0000	/* Serial Controller Port */
+#define SSP0_BASE	0x400D0000	/* Sync serial port */
+
+#define REDWOOD_IDE_CMD		0xf0100000
+#define REDWOOD_IDE_CTRL	0xf1100000
+
+#define RTCFPC_IRQ	0
+#define XPORT_IRQ	1
+#define AUD_IRQ		2
+#define AID_IRQ		3
+#define DMA0		4
+#define DMA1_IRQ	5
+#define DMA2_IRQ	6
+#define DMA3_IRQ	7
+#define SC0_IRQ		8
+#define IIC0_IRQ	9
+#define IIR0_IRQ	10
+#define GPT0_IRQ	11
+#define GPT1_IRQ	12
+#define SCP0_IRQ	13
+#define SSP0_IRQ	14
+#define GPT2_IRQ	15	/* count down timer */
+#define SC1_IRQ		16
+/* IRQ 17 - 19  external */
+#define UART0_INT	20
+#define UART1_INT	21
+#define UART2_INT	22
+#define XPTDMA_IRQ	23
+#define DCRIDE_IRQ	24
+/* IRQ 25 - 30 external */
+#define IDE0_IRQ	26
+
+#define IIC_NUMS	1
+#define UART_NUMS	3
+#define IIC_OWN		0x55
+#define IIC_CLOCK	50
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(1)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS2)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(2)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+#endif
+
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRNCAP_DMA_CC		1	/* have DMA chained count capability */
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_PLB0_BASE		0x054
+#define DCRN_PLB1_BASE		0x064
+#define DCRN_POB0_BASE		0x0B0
+#define DCRN_SCCR_BASE		0x120
+#define DCRN_UIC0_BASE		0x040
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRN_CIC_BASE 		0x030
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_EBIMC_BASE		0x070
+#define DCRN_DCRX_BASE		0x020
+#define DCRN_CPMFR_BASE		0x102
+#define DCRN_SCCR_BASE		0x120
+#define DCRN_RTCFP_BASE		0x310
+
+#define UIC0 DCRN_UIC0_BASE
+
+#define IBM_CPM_IIC0	0x80000000	/* IIC 0 interface */
+#define IBM_CPM_CPU	0x10000000	/* PPC405B3 clock control */
+#define IBM_CPM_AUD	0x08000000	/* Audio Decoder */
+#define IBM_CPM_EBIU	0x04000000	/* External Bus Interface Unit */
+#define IBM_CPM_IRR	0x02000000	/* Infrared reciever */
+#define IBM_CPM_DMA	0x01000000	/* DMA controller */
+#define IBM_CPM_UART2	0x00200000	/* Serial Control Port */
+#define IBM_CPM_UART1	0x00100000	/* Serial 1 / Infrared */
+#define IBM_CPM_UART0	0x00080000	/* Serial 0 / 16550 */
+#define IBM_PM_DCRIDE	0x00040000	/* DCR timeout & IDE line Mode clock */
+#define IBM_CPM_SC0	0x00020000	/* Smart Card 0 */
+#define IBM_CPM_VID	0x00010000	/* reserved */
+#define IBM_CPM_SC1	0x00008000	/* Smart Card 0 */
+#define IBM_CPM_XPT0	0x00002000	/* Transport - 54 Mhz */
+#define IBM_CPM_CBS	0x00001000	/* Cross Bar Switch */
+#define IBM_CPM_GPT	0x00000800	/* GPTPWM */
+#define IBM_CPM_GPIO0	0x00000400	/* General Purpose IO 0 */
+#define IBM_CPM_DENC	0x00000200	/* Digital video Encoder */
+#define IBM_CPM_C405T	0x00000100	/* CPU timers */
+#define IBM_CPM_XPT27	0x00000080	/* Transport - 27 Mhz */
+#define IBM_CPM_UIC	0x00000040	/* Universal Interrupt Controller */
+#define IBM_CPM_RTCFPC	0x00000020	/* Realtime clock and front panel */
+#define IBM_CPM_SSP	0x00000010	/* Modem Serial Interface (SSP) */
+#define IBM_CPM_VID2	0x00000002	/* Video Decoder clock domain 2 */
+#define DFLT_IBM4xx_PM	~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_DMA	\
+			| IBM_CPM_CBS | IBM_CPM_XPT0 | IBM_CPM_C405T 	\
+			| IBM_CPM_XPT27 | IBM_CPM_UIC)
+
+#define DCRN_BEAR	(DCRN_BE_BASE + 0x0)	/* Bus Error Address Register */
+#define DCRN_BESR	(DCRN_BE_BASE + 0x1)	/* Bus Error Syndrome Register */
+/* DCRN_BESR */
+#define BESR_DSES	0x80000000	/* Data-Side Error Status */
+#define BESR_DMES	0x40000000	/* DMA Error Status */
+#define BESR_RWS	0x20000000	/* Read/Write Status */
+#define BESR_ETMASK	0x1C000000	/* Error Type */
+#define ET_PROT		0
+#define ET_PARITY	1
+#define ET_NCFG		2
+#define ET_BUSERR	4
+#define ET_BUSTO	6
+
+#define CHR1_CETE	0x00800000	/* CPU external timer enable */
+#define CHR1_PCIPW	0x00008000	/* PCI Int enable/Peripheral Write enable */
+
+#define DCRN_CICCR	(DCRN_CIC_BASE + 0x0)	/* CIC Control Register */
+#define DCRN_DMAS1	(DCRN_CIC_BASE + 0x1)	/* DMA Select1 Register */
+#define DCRN_DMAS2	(DCRN_CIC_BASE + 0x2)	/* DMA Select2 Register */
+#define DCRN_CICVCR	(DCRN_CIC_BASE + 0x3)	/* CIC Video COntro Register */
+#define DCRN_CICSEL3	(DCRN_CIC_BASE + 0x5)	/* CIC Select 3 Register */
+#define DCRN_SGPO	(DCRN_CIC_BASE + 0x6)	/* CIC GPIO Output Register */
+#define DCRN_SGPOD	(DCRN_CIC_BASE + 0x7)	/* CIC GPIO OD Register */
+#define DCRN_SGPTC	(DCRN_CIC_BASE + 0x8)	/* CIC GPIO Tristate Ctrl Reg */
+#define DCRN_SGPI	(DCRN_CIC_BASE + 0x9)	/* CIC GPIO Input Reg */
+
+#define DCRN_DCRXICR	(DCRN_DCRX_BASE + 0x0)	/* Internal Control Register */
+#define DCRN_DCRXISR	(DCRN_DCRX_BASE + 0x1)	/* Internal Status Register */
+#define DCRN_DCRXECR	(DCRN_DCRX_BASE + 0x2)	/* External Control Register */
+#define DCRN_DCRXESR	(DCRN_DCRX_BASE + 0x3)	/* External Status Register */
+#define DCRN_DCRXTAR	(DCRN_DCRX_BASE + 0x4)	/* Target Address Register */
+#define DCRN_DCRXTDR	(DCRN_DCRX_BASE + 0x5)	/* Target Data Register */
+#define DCRN_DCRXIGR	(DCRN_DCRX_BASE + 0x6)	/* Interrupt Generation Register */
+#define DCRN_DCRXBCR	(DCRN_DCRX_BASE + 0x7)	/* Line Buffer Control Register */
+
+#define DCRN_BRCRH0	(DCRN_EBIMC_BASE + 0x0)	/* Bus Region Config High 0 */
+#define DCRN_BRCRH1	(DCRN_EBIMC_BASE + 0x1)	/* Bus Region Config High 1 */
+#define DCRN_BRCRH2	(DCRN_EBIMC_BASE + 0x2)	/* Bus Region Config High 2 */
+#define DCRN_BRCRH3	(DCRN_EBIMC_BASE + 0x3)	/* Bus Region Config High 3 */
+#define DCRN_BRCRH4	(DCRN_EBIMC_BASE + 0x4)	/* Bus Region Config High 4 */
+#define DCRN_BRCRH5	(DCRN_EBIMC_BASE + 0x5)	/* Bus Region Config High 5 */
+#define DCRN_BRCRH6	(DCRN_EBIMC_BASE + 0x6)	/* Bus Region Config High 6 */
+#define DCRN_BRCRH7	(DCRN_EBIMC_BASE + 0x7)	/* Bus Region Config High 7 */
+#define DCRN_BRCR0	(DCRN_EBIMC_BASE + 0x10)	/* BRC 0 */
+#define DCRN_BRCR1	(DCRN_EBIMC_BASE + 0x11)	/* BRC 1 */
+#define DCRN_BRCR2	(DCRN_EBIMC_BASE + 0x12)	/* BRC 2 */
+#define DCRN_BRCR3	(DCRN_EBIMC_BASE + 0x13)	/* BRC 3 */
+#define DCRN_BRCR4	(DCRN_EBIMC_BASE + 0x14)	/* BRC 4 */
+#define DCRN_BRCR5	(DCRN_EBIMC_BASE + 0x15)	/* BRC 5 */
+#define DCRN_BRCR6	(DCRN_EBIMC_BASE + 0x16)	/* BRC 6 */
+#define DCRN_BRCR7	(DCRN_EBIMC_BASE + 0x17)	/* BRC 7 */
+#define DCRN_BEAR0	(DCRN_EBIMC_BASE + 0x20)	/* Bus Error Address Register */
+#define DCRN_BESR0	(DCRN_EBIMC_BASE + 0x21)	/* Bus Error Status Register */
+#define DCRN_BIUCR	(DCRN_EBIMC_BASE + 0x2A)	/* Bus Interfac Unit Ctrl Reg */
+
+#define DCRN_RTC_FPC0_CNTL 	(DCRN_RTCFP_BASE + 0x00)	/* RTC cntl */
+#define DCRN_RTC_FPC0_INT 	(DCRN_RTCFP_BASE + 0x01)	/* RTC Interrupt */
+#define DCRN_RTC_FPC0_TIME 	(DCRN_RTCFP_BASE + 0x02)	/* RTC time reg */
+#define DCRN_RTC_FPC0_ALRM 	(DCRN_RTCFP_BASE + 0x03)	/* RTC Alarm reg */
+#define DCRN_RTC_FPC0_D1 	(DCRN_RTCFP_BASE + 0x04)	/* LED Data 1 */
+#define DCRN_RTC_FPC0_D2 	(DCRN_RTCFP_BASE + 0x05)	/* LED Data 2 */
+#define DCRN_RTC_FPC0_D3 	(DCRN_RTCFP_BASE + 0x06)	/* LED Data 3 */
+#define DCRN_RTC_FPC0_D4 	(DCRN_RTCFP_BASE + 0x07)	/* LED Data 4 */
+#define DCRN_RTC_FPC0_D5 	(DCRN_RTCFP_BASE + 0x08)	/* LED Data 5 */
+#define DCRN_RTC_FPC0_FCNTL 	(DCRN_RTCFP_BASE + 0x09)	/* LED control */
+#define DCRN_RTC_FPC0_BRT 	(DCRN_RTCFP_BASE + 0x0A)	/* Brightness cntl */
+
+#include <platforms/ibm405.h>
+
+#endif				/* __ASM_IBMSTBX25_H__ */
+#endif				/* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/pq2ads.h linux-2.4.26-pre6/arch/ppc/platforms/pq2ads.h
--- linux-2.4.25/arch/ppc/platforms/pq2ads.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/pq2ads.h	2004-03-25 00:17:30.000000000 +0000
@@ -0,0 +1,89 @@
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek (dan@mvista.com)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_ADS8260_DEFS
+#define __MACH_ADS8260_DEFS
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+#define BCSR_ADDR		((uint)0xf4500000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+ * only on word boundaries.
+ * Not all are used (yet), or are interesting to us (yet).
+ */
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_LED0		((uint)0x02000000)	/* 0 == on */
+#define BCSR0_LED1		((uint)0x01000000)	/* 0 == on */
+#define BCSR1_FETHIEN		((uint)0x08000000)	/* 0 == enable */
+#define BCSR1_FETH_RST		((uint)0x04000000)	/* 0 == reset */
+#define BCSR1_RS232_EN1		((uint)0x02000000)	/* 0 == enable */
+#define BCSR1_RS232_EN2		((uint)0x01000000)	/* 0 == enable */
+
+#define PHY_INTERRUPT	SIU_INT_IRQ7
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PCI_INT_STAT_REG	0xF8200000
+#define PCI_INT_MASK_REG	0xF8200004
+#define PIRQA			(NR_SIU_INTS + 0)
+#define PIRQB			(NR_SIU_INTS + 1)
+#define PIRQC			(NR_SIU_INTS + 2)
+#define PIRQD			(NR_SIU_INTS + 3)
+
+/*
+ * PCI memory map definitions for MPC8266ADS-PCI.
+ *
+ * processor view
+ *	local address		PCI address		target
+ *	0x80000000-0x9FFFFFFF	0x80000000-0x9FFFFFFF	PCI mem with prefetch
+ *	0xA0000000-0xBFFFFFFF	0xA0000000-0xBFFFFFFF	PCI mem w/o prefetch
+ *	0xF4000000-0xF7FFFFFF	0x00000000-0x03FFFFFF	PCI IO
+ *
+ * PCI master view
+ *	local address		PCI address		target
+ *	0x00000000-0x1FFFFFFF	0x00000000-0x1FFFFFFF	MPC8266 local memory
+ */
+
+/* window for a PCI master to access MPC8266 memory */
+#define PCI_SLV_MEM_LOCAL	0x00000000	/* Local base */
+#define PCI_SLV_MEM_BUS		0x00000000	/* PCI base */
+
+/* window for the processor to access PCI memory with prefetching */
+#define PCI_MSTR_MEM_LOCAL	0x80000000	/* Local base */
+#define PCI_MSTR_MEM_BUS	0x80000000	/* PCI base   */
+#define PCI_MSTR_MEM_SIZE	0x20000000	/* 512MB */
+
+/* window for the processor to access PCI memory without prefetching */
+#define PCI_MSTR_MEMIO_LOCAL	0xA0000000	/* Local base */
+#define PCI_MSTR_MEMIO_BUS	0xA0000000	/* PCI base   */
+#define PCI_MSTR_MEMIO_SIZE	0x20000000	/* 512MB */
+
+/* window for the processor to access PCI I/O */
+#define PCI_MSTR_IO_LOCAL	0xF4000000	/* Local base */
+#define PCI_MSTR_IO_BUS         0x00000000	/* PCI base   */
+#define PCI_MSTR_IO_SIZE        0x04000000	/* 64MB */
+
+#define _IO_BASE		PCI_MSTR_IO_LOCAL
+#define _ISA_MEM_BASE		PCI_MSTR_MEMIO_LOCAL
+#define PCI_DRAM_OFFSET		PCI_SLV_MEM_BUS
+#endif /* CONFIG_PCI */
+
+#endif /* __MACH_ADS8260_DEFS */
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/redwood5.c linux-2.4.26-pre6/arch/ppc/platforms/redwood5.c
--- linux-2.4.25/arch/ppc/platforms/redwood5.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/redwood5.c	2004-03-25 00:18:06.000000000 +0000
@@ -0,0 +1,82 @@
+/*
+ *
+ *    Copyright 2000-2001 MontaVista Software Inc.
+ *      Completed implementation.
+ *      Author: Armin Kuster
+ *
+ *    Module name: redwood5.c
+ *
+ *    Description:
+ *    	IBM redwood5 eval board file
+ *
+ *      History:  12/29/2001 - Armin
+ *    	initail release
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+void __init
+board_setup_arch(void)
+{
+
+	bd_t *bip = (bd_t *)__res;
+
+#ifdef CONFIG_DEBUG_BRINGUP
+	printk("\n");
+	printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+	printk("\n");
+	printk("bi_s_version\t %s\n",      bip->bi_s_version);
+	printk("bi_r_version\t %s\n",      bip->bi_r_version);
+	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,bip->bi_memsize/(1024*1000));
+	printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+	bip->bi_enetaddr[0], bip->bi_enetaddr[1],
+	bip->bi_enetaddr[2], bip->bi_enetaddr[3],
+	bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+
+	printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+	       bip->bi_intfreq, bip->bi_intfreq/ 1000000);
+
+	printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+		bip->bi_busfreq, bip->bi_busfreq / 1000000 );
+	printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
+	       bip->bi_tbfreq, bip->bi_tbfreq/1000000);
+
+	printk("\n");
+#endif
+
+}
+
+void __init
+board_io_mapping(void)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+	 unsigned long v, p;
+
+	/* 0x400x0000 -> 0xe00x0000 */
+	p = 0x40000000 | (i << 16);
+	v = STB04xxx_IO_BASE | (i << 16);
+
+	io_block_mapping(v, p, PAGE_SIZE,
+		 _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) | _PAGE_GUARDED);
+	}
+
+
+}
+
+void __init
+board_setup_irq(void)
+{
+}
+
+void __init
+board_init(void)
+{
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/redwood5.h linux-2.4.26-pre6/arch/ppc/platforms/redwood5.h
--- linux-2.4.25/arch/ppc/platforms/redwood5.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/redwood5.h	2004-03-25 00:17:15.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ *    Copyright 2001 MontaVista Software Inc.
+ *	PPC405 modifications
+ * 	Author: MontaVista Software, Inc.
+ *          Armin Kuster
+ *
+ *    Module name: redwood5.h
+ *
+ *    Description:
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      STB03xxx "Redwood" evaluation board.
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_REDWOOD5_H__
+#define __ASM_REDWOOD5_H__
+
+/* Redwood5 has an STB04xxx core */
+#include <platforms/ibmstb4.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+	unsigned char	bi_s_version[4];	/* Version of this structure */
+	unsigned char	bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	bi_memsize;		/* DRAM installed, in bytes */
+	unsigned int	bi_dummy;		/* field shouldn't exist */
+	unsigned char	bi_enetaddr[6];		/* Ethernet MAC address */
+	unsigned int	bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	bi_busfreq;		/* Bus speed, in Hz */
+	unsigned int	bi_tbfreq;		/* Software timebase freq */
+	unsigned int	bi_opb_busfreq;		/* OPB Bus speed, in Hz */
+	int		bi_iic_fast[2];		/* Use fast i2c mode */
+} bd_t;
+#endif /* !__ASSEMBLY__ */
+
+
+#define SMC91111_BASE_ADDR	0xf2000300
+#define SMC91111_IRQ		28
+
+#ifdef MAX_HWIFS
+#undef MAX_HWIFS
+#endif
+#define MAX_HWIFS		1
+
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+#define BASE_BAUD		(378000000 / 18 / 16)
+
+#define PPC4xx_MACHINE_NAME	"IBM Redwood5"
+
+#endif /* __ASM_REDWOOD5_H__ */
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/redwood6.c linux-2.4.26-pre6/arch/ppc/platforms/redwood6.c
--- linux-2.4.25/arch/ppc/platforms/redwood6.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/redwood6.c	2004-03-25 00:17:27.000000000 +0000
@@ -0,0 +1,174 @@
+/*
+ *
+ *    Module name: redwood6.c
+ *
+ *    Description:
+ *    	IBM redwood6 eval board file
+ *
+ *    Author: Armin Kuster
+ *    Copyright 2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
+ * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *      History:  July 10, 2002 - Armin
+ *    	initial release
+ *
+ *    		: July 16, 2002 - Armin
+ *    		added xilinx init code for ide interface
+ *    		added IRQ table 
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <asm/io.h>
+#include <asm/ppc4xx_pic.h>
+#include <linux/delay.h>
+#include <asm/machdep.h>
+
+
+/*
+ * Define all of the IRQ senses and polarities.  
+ */
+
+static u_char redwood6_IRQ_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 0: RTC/FPC */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 1: Transport */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 2: Audio Dec */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 3: Video Dec */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 4: DMA Chan 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 5: DMA Chan 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 6: DMA Chan 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 7: DMA Chan 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 8: SmartCard 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 9: IIC0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 10: IRR */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 11: Cap Timers */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 12: Cmp Timers */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 13: Serial Port */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 14: Soft Modem */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 15: Down Ctrs */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 16: SmartCard 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 17: Ext Int 7 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 18: Ext Int 8 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 19: Ext Int 9 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 20: Serial 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 21: Serial 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 22: Serial 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 23: XPT_DMA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 24: DCR timeout */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 25: Ext Int 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 26: Ext Int 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 27: Ext Int 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 28: Ext Int 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 29: Ext Int 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 30: Ext Int 5 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 31: Ext Int 6 */
+};
+
+
+void __init
+board_setup_arch(void)
+{
+#ifdef CONFIG_IDE
+	void *xilinx, *xilinx_1, *xilinx_2;
+	unsigned short us_reg5;
+
+	xilinx = (unsigned long) ioremap(IDE_XLINUX_MUX_BASE, 0x10);
+	/* init xilinx control registers - enable ide mux, clear reset bit */
+	if (!xilinx) {
+		printk(KERN_CRIT
+		       "redwood6_setup_arch() xilinxi ioremap failed\n");
+		return;
+	}
+	xilinx_1 = xilinx + 0xa;
+	xilinx_2 = xilinx + 0xe;
+
+	us_reg5 = readb(xilinx_1);
+	writeb(0x01d1, xilinx_1);
+	writeb(0x0008, xilinx_2);
+
+	udelay(10 * 1000);
+
+	writeb(0x01d1, xilinx_1);
+	writeb(0x0008, xilinx_2);
+#endif
+
+#ifdef DEBUG_BRINGUP
+	bd_t *bip = (bd_t *) __res;
+	printk("\n");
+	printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+	printk("\n");
+	printk("bi_s_version\t %s\n", bip->bi_s_version);
+	printk("bi_r_version\t %s\n", bip->bi_r_version);
+	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
+	       bip->bi_memsize / (1024 * 1000));
+	printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+	       bip->bi_enetaddr[0], bip->bi_enetaddr[1], bip->bi_enetaddr[2],
+	       bip->bi_enetaddr[3], bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+
+	printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+	       bip->bi_intfreq, bip->bi_intfreq / 1000000);
+
+	printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+	       bip->bi_busfreq, bip->bi_busfreq / 1000000);
+	printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
+	       bip->bi_tbfreq, bip->bi_tbfreq / 1000000);
+
+	printk("\n");
+#endif
+	ibm4xxPIC_InitSenses = redwood6_IRQ_initsenses;
+	ibm4xxPIC_NumInitSenses = sizeof(redwood6_IRQ_initsenses);
+
+	/* Identify the system */
+	printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n");
+	printk(KERN_INFO
+	       "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+void __init
+board_io_mapping(void)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		unsigned long v, p;
+
+		/* 0x400x0000 -> 0xe00x0000 */
+		p = 0x40000000 | (i << 16);
+		v = STBx25xx_IO_BASE | (i << 16);
+
+		io_block_mapping(v, p, PAGE_SIZE,
+				 _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) |
+				 _PAGE_GUARDED);
+	}
+}
+
+void __init
+board_setup_irq(void)
+{
+}
+
+void __init
+board_init(void)
+{
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/redwood6.h linux-2.4.26-pre6/arch/ppc/platforms/redwood6.h
--- linux-2.4.25/arch/ppc/platforms/redwood6.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/redwood6.h	2004-03-25 00:17:27.000000000 +0000
@@ -0,0 +1,78 @@
+/*
+ * 	Author: MontaVista Software, Inc.
+ *          Armin Kuster
+ *
+ *    Module name: redwood6.h
+ *
+ *    Description:
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      STBx25xx "Redwood6" evaluation board.
+ *
+ *    Copyright 2002 MontaVista Software Inc.
+ * 	Author: MontaVista Software, Inc.
+ *          Armin Kuster
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
+ * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_REDWOOD5_H__
+#define __ASM_REDWOOD5_H__
+
+/* Redwood6 has an STBx25xx core */
+#include <platforms/ibmstbx25.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+	unsigned char	bi_s_version[4];	/* Version of this structure */
+	unsigned char	bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	bi_memsize;		/* DRAM installed, in bytes */
+	unsigned int	bi_dummy;		/* field shouldn't exist */
+	unsigned char	bi_enetaddr[6];		/* Ethernet MAC address */
+	unsigned int	bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	bi_busfreq;		/* Bus speed, in Hz */
+	unsigned int	bi_tbfreq;		/* Software timebase freq */
+	unsigned int	bi_opb_busfreq;		/* OPB Bus speed, in Hz */
+	int		bi_iic_fast[1];		/* Use fast i2c mode */
+} bd_t;
+#endif				/* !__ASSEMBLY__ */
+
+#define SMC91111_BASE_ADDR	0xf2030300
+#define SMC91111_IRQ		27
+#define IDE_XLINUX_MUX_BASE        0xf2040000
+#define IDE_DMA_ADDR	0xfce00000
+
+#ifdef MAX_HWIFS
+#undef MAX_HWIFS
+#endif
+#define MAX_HWIFS		1
+
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+#define BASE_BAUD		(378000000 / 18 / 16)
+
+#define PPC4xx_MACHINE_NAME	"IBM Redwood6"
+
+#endif				/* __ASM_REDWOOD5_H__ */
+#endif				/* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/rpx8260.h linux-2.4.26-pre6/arch/ppc/platforms/rpx8260.h
--- linux-2.4.25/arch/ppc/platforms/rpx8260.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/ppc/platforms/rpx8260.h	2004-03-25 00:16:53.000000000 +0000
@@ -0,0 +1,73 @@
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Embedded Planet RPX6 (or RPX Super) MPC8260 board.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek (dan@embeddededge.com)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPXSUPER_DEFS
+#define __MACH_RPXSUPER_DEFS
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_nvsize;	/* NVRAM size in bytes (can be 0) */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+#define RPX_CSR_ADDR		((uint)0xfa000000)
+#define RPX_CSR_SIZE		((uint)(512 * 1024))
+#define RPX_NVRTC_ADDR		((uint)0xfa080000)
+#define RPX_NVRTC_SIZE		((uint)(512 * 1024))
+
+/* The RPX6 has 16, byte wide control/status registers.
+ * Not all are used (yet).
+ */
+extern volatile u_char *rpx6_csr_addr;
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ID_MASK		((u_char)0xf0)		/* Read only */
+#define BCSR0_SWITCH_MASK	((u_char)0x0f)		/* Read only */
+#define BCSR1_XCVR_SMC1		((u_char)0x80)
+#define BCSR1_XCVR_SMC2		((u_char)0x40)
+#define BCSR2_FLASH_WENABLE	((u_char)0x20)
+#define BCSR2_NVRAM_ENABLE	((u_char)0x10)
+#define BCSR2_ALT_IRQ2		((u_char)0x08)
+#define BCSR2_ALT_IRQ3		((u_char)0x04)
+#define BCSR2_PRST		((u_char)0x02)		/* Force reset */
+#define BCSR2_ENPRST		((u_char)0x01)		/* Enable POR */
+#define BCSR3_MODCLK_MASK	((u_char)0xe0)
+#define BCSR3_ENCLKHDR		((u_char)0x10)
+#define BCSR3_LED5		((u_char)0x04)		/* 0 == on */
+#define BCSR3_LED6		((u_char)0x02)		/* 0 == on */
+#define BCSR3_LED7		((u_char)0x01)		/* 0 == on */
+#define BCSR4_EN_PHY		((u_char)0x80)		/* Enable PHY */
+#define BCSR4_EN_MII		((u_char)0x40)		/* Enable PHY */
+#define BCSR4_MII_READ		((u_char)0x04)
+#define BCSR4_MII_MDC		((u_char)0x02)
+#define BCSR4_MII_MDIO		((u_char)0x02)
+#define BCSR13_FETH_IRQMASK	((u_char)0xf0)
+#define BCSR15_FETH_IRQ		((u_char)0x20)
+
+#endif
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc/defconfig linux-2.4.26-pre6/arch/sparc/defconfig
--- linux-2.4.25/arch/sparc/defconfig	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/sparc/defconfig	2004-03-25 00:21:12.000000000 +0000
@@ -161,9 +161,11 @@ CONFIG_IPV6=m
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -362,6 +364,7 @@ CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_UNIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc/kernel/sys_sunos.c linux-2.4.26-pre6/arch/sparc/kernel/sys_sunos.c
--- linux-2.4.25/arch/sparc/kernel/sys_sunos.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/sparc/kernel/sys_sunos.c	2004-03-25 00:19:21.000000000 +0000
@@ -688,8 +688,8 @@ static int get_default (int value, int d
 
 static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  server_fd;
-	char *the_name;
+	int  server_fd, err;
+	char *the_name, *mount_page;
 	struct nfs_mount_data linux_nfs_mount;
 	struct sunos_nfs_mount_args sunos_mount;
 
@@ -742,7 +742,16 @@ static int sunos_nfs_mount(char *dir_nam
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!mount_page)
+		return -ENOMEM;
+
+	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+
+	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+
+	free_page((unsigned long) mount_page);
+	return err;
 }
 
 asmlinkage int
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc64/defconfig linux-2.4.26-pre6/arch/sparc64/defconfig
--- linux-2.4.25/arch/sparc64/defconfig	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/sparc64/defconfig	2004-03-25 00:18:53.000000000 +0000
@@ -70,6 +70,7 @@ CONFIG_PARPORT_PC_CML1=m
 # CONFIG_PARPORT_SERIAL is not set
 CONFIG_PARPORT_PC_FIFO=y
 # CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
 # CONFIG_PARPORT_ATARI is not set
@@ -122,6 +123,7 @@ CONFIG_FB_CGSIX=y
 CONFIG_FB_PCI=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
+# CONFIG_FB_IT8181 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -314,9 +316,11 @@ CONFIG_IP6_NF_TARGET_MARK=m
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 CONFIG_VLAN_8021Q=m
 
@@ -351,12 +355,14 @@ CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_HFSC=m
 CONFIG_NET_SCH_PRIO=m
 CONFIG_NET_SCH_RED=m
 CONFIG_NET_SCH_SFQ=m
 CONFIG_NET_SCH_TEQL=m
 CONFIG_NET_SCH_TBF=m
 CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DELAY=m
 CONFIG_NET_SCH_DSMARK=m
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_QOS=y
@@ -453,6 +459,7 @@ CONFIG_BLK_DEV_PDC202XX=y
 CONFIG_BLK_DEV_ATARAID=m
 CONFIG_BLK_DEV_ATARAID_PDC=m
 CONFIG_BLK_DEV_ATARAID_HPT=m
+CONFIG_BLK_DEV_ATARAID_MEDLEY=m
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -617,6 +624,7 @@ CONFIG_E100=m
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
 CONFIG_NE2K_PCI=m
+CONFIG_FORCEDETH=m
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -738,8 +746,8 @@ CONFIG_HFSPLUS_FS=m
 CONFIG_BEFS_FS=m
 # CONFIG_BEFS_DEBUG is not set
 CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=m
-CONFIG_JBD=m
+CONFIG_EXT3_FS=y
+CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
@@ -763,8 +771,8 @@ CONFIG_MINIX_FS=m
 # CONFIG_NTFS_RW is not set
 CONFIG_HPFS_FS=m
 CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
@@ -974,7 +982,6 @@ CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_CATC=m
-CONFIG_USB_AX8817X=m
 CONFIG_USB_CDCETHER=m
 CONFIG_USB_USBNET=m
 
@@ -1034,13 +1041,20 @@ CONFIG_USB_LCD=m
 # Support for USB gadgets
 #
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_NET2280=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_CONTROLLER is not set
+CONFIG_USB_NET2280=y
+CONFIG_USB_GADGET_CONTROLLER=y
+CONFIG_USB_GADGET_DUALSPEED=y
 
 #
-# USB Peripheral Controller Drivers
+# USB Gadget Drivers
 #
-# CONFIG_USB_GADGET_CONTROLLER is not set
-# CONFIG_USB_NET2280 is not set
-# CONFIG_USB_GADGET_CONTROLLER is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_FILE_STORAGE_TEST is not set
 
 #
 # Bluetooth support
@@ -1084,6 +1098,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
+# CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_STACK_DEBUG is not set
 CONFIG_LOG_BUF_SHIFT=0
 
@@ -1104,6 +1119,8 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_TEST is not set
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc64/kernel/sys_sparc32.c linux-2.4.26-pre6/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.25/arch/sparc64/kernel/sys_sparc32.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/sparc64/kernel/sys_sparc32.c	2004-03-25 00:20:38.000000000 +0000
@@ -1799,14 +1799,13 @@ asmlinkage int sys32_mount(char *dev_nam
 	if (err)
 		goto out;
 
-	if (!type_page) {
-		err = -EINVAL;
-		goto out;
+	if (type_page) {
+		is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+		is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+	} else {
+		is_smb = is_ncp = 0;
 	}
 
-	is_smb = !strcmp((char *)type_page, SMBFS_NAME);
-	is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
-
 	err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
 	if (err)
 		goto type_out;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc64/kernel/sys_sunos32.c linux-2.4.26-pre6/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.25/arch/sparc64/kernel/sys_sunos32.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/sparc64/kernel/sys_sunos32.c	2004-03-25 00:20:32.000000000 +0000
@@ -654,8 +654,8 @@ static int get_default (int value, int d
 /* XXXXXXXXXXXXXXXXXXXX */
 static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  server_fd;
-	char *the_name;
+	int  server_fd, err;
+	char *the_name, *mount_page;
 	struct nfs_mount_data linux_nfs_mount;
 	struct sunos_nfs_mount_args sunos_mount;
 
@@ -708,7 +708,16 @@ static int sunos_nfs_mount(char *dir_nam
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!mount_page)
+		return -ENOMEM;
+
+	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+
+	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+
+	free_page((unsigned long) mount_page);
+	return err;
 }
 
 /* XXXXXXXXXXXXXXXXXXXX */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc64/mm/modutil.c linux-2.4.26-pre6/arch/sparc64/mm/modutil.c
--- linux-2.4.25/arch/sparc64/mm/modutil.c	2001-12-21 17:41:53.000000000 +0000
+++ linux-2.4.26-pre6/arch/sparc64/mm/modutil.c	2004-03-25 00:18:57.000000000 +0000
@@ -11,9 +11,9 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-static struct vm_struct * modvmlist = NULL;
+static struct vm_struct *modvmlist = NULL;
 
-void module_unmap (void * addr)
+void __module_unmap(void *addr, int free_area_pages)
 {
 	struct vm_struct **p, *tmp;
 
@@ -26,7 +26,9 @@ void module_unmap (void * addr)
 	for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
 			*p = tmp->next;
-			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+			if (free_area_pages)
+				vmfree_area_pages(VMALLOC_VMADDR(tmp->addr),
+						  tmp->size);
 			kfree(tmp);
 			return;
 		}
@@ -34,13 +36,19 @@ void module_unmap (void * addr)
 	printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
 }
 
-void * module_map (unsigned long size)
+void module_unmap(void *addr)
+{
+	__module_unmap(addr, 1);
+}
+
+void *module_map (unsigned long size)
 {
 	void * addr;
 	struct vm_struct **p, *tmp, *area;
 
 	size = PAGE_ALIGN(size);
-	if (!size || size > MODULES_LEN) return NULL;
+	if (!size || size > MODULES_LEN)
+		return NULL;
 		
 	addr = (void *) MODULES_VADDR;
 	for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
@@ -48,17 +56,19 @@ void * module_map (unsigned long size)
 			break;
 		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
 	}
-	if ((unsigned long) addr + size >= MODULES_END) return NULL;
+	if ((unsigned long) addr + size >= MODULES_END)
+		return NULL;
 	
 	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
-	if (!area) return NULL;
+	if (!area)
+		return NULL;
 	area->size = size + PAGE_SIZE;
 	area->addr = addr;
 	area->next = *p;
 	*p = area;
 
 	if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) {
-		module_unmap(addr);
+		__module_unmap(addr, 0);
 		return NULL;
 	}
 	return addr;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/Makefile linux-2.4.26-pre6/arch/x86_64/Makefile
--- linux-2.4.25/arch/x86_64/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/Makefile	2004-03-25 00:21:44.000000000 +0000
@@ -19,7 +19,7 @@
 # 20010105  Andi Kleen, add IA32 compiler.
 #           ....and later removed it again....
 #
-# $Id: Makefile,v 1.34 2003/09/25 02:50:05 ak Exp $
+# $Id: Makefile,v 1.36 2004/02/27 18:30:19 ak Exp $
 
 #
 # early bootup linking needs 32bit. You can either use real 32bit tools
@@ -53,8 +53,16 @@ CFLAGS += -Wno-sign-compare
 ifneq ($(CONFIG_X86_REMOTE_DEBUG),y)
 CFLAGS += -fno-asynchronous-unwind-tables
 endif
+# this is needed right now for the 32bit ioctl code
 CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
 
+ifdef CONFIG_MK8
+CFLAGS += $(call check_gcc,-march=k8,)
+endif
+ifdef CONFIG_MPSC
+CFLAGS += $(call check_gcc,-march=prescott,)
+endif
+
 HEAD := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
 
 SUBDIRS := arch/x86_64/tools $(SUBDIRS) arch/x86_64/kernel arch/x86_64/mm arch/x86_64/lib
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/boot/setup.S linux-2.4.26-pre6/arch/x86_64/boot/setup.S
--- linux-2.4.25/arch/x86_64/boot/setup.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/boot/setup.S	2004-03-25 00:20:53.000000000 +0000
@@ -289,8 +289,9 @@ loader_ok:
 	/* minimum CPUID flags for x86-64 */
 	/* see http://www.x86-64.org/lists/discuss/msg02971.html */		
 #define SSE_MASK ((1<<25)|(1<<26))
-#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<11)| \
-					   (1<<13)|(1<<15)|(1<<24)|(1<<29))
+#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
+					   (1<<13)|(1<<15)|(1<<24))
+#define REQUIRED_MASK2 (1<<29)
 
 	pushfl				/* standard way to check for cpuid */
 	popl	%eax
@@ -302,10 +303,10 @@ loader_ok:
 	popl	%eax
 	cmpl	%eax,%ebx
 	jz	no_longmode		/* cpu has no cpuid */
-	movl	$0x80000000,%eax
+	movl	$0x0,%eax
 	cpuid
-	cmpl	$0x80000001,%eax
-	jb	no_longmode		/* no extended cpuid */
+	cmpl	$0x1,%eax
+	jb	no_longmode		/* no cpuid 1 */
 	xor	%di,%di
 	cmpl	$0x68747541,%ebx	/* AuthenticAMD */
 	jnz	noamd
@@ -315,11 +316,20 @@ loader_ok:
 	jnz	noamd
 	mov	$1,%di			/* cpu is from AMD */
 noamd:		
-	movl	$0x80000001,%eax		
+	movl    $0x1,%eax
 	cpuid
 	andl	$REQUIRED_MASK1,%edx
 	xorl	$REQUIRED_MASK1,%edx
 	jnz	no_longmode
+	movl    $0x80000000,%eax
+	cpuid
+	cmpl    $0x80000001,%eax
+	jb      no_longmode             /* no extended cpuid */
+	movl    $0x80000001,%eax
+	cpuid
+	andl    $REQUIRED_MASK2,%edx
+	xorl    $REQUIRED_MASK2,%edx
+	jnz     no_longmode
 sse_test:		
 	movl	$1,%eax
 	cpuid
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/config.in linux-2.4.26-pre6/arch/x86_64/config.in
--- linux-2.4.25/arch/x86_64/config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/config.in	2004-03-25 00:20:56.000000000 +0000
@@ -34,13 +34,19 @@ mainmenu_option next_comment
 comment 'Processor type and features'
 choice 'Processor family' \
 	"AMD-Hammer			CONFIG_MK8 \
+	 Intel-x86-64			CONFIG_MPSC \
 	 Generic-x86-64			CONFIG_GENERIC_CPU" AMD-Hammer
 	
 #
 # Define implied options from the CPU selection here
 #
+if [ "$CONFIG_GENERIC_CPU" = "y" -o "$CONFIG_MPSC" = "y" ]; then
+define_int CONFIG_X86_L1_CACHE_BYTES 128
+define_int CONFIG_X86_L1_CACHE_SHIFT 7
+else
 define_int CONFIG_X86_L1_CACHE_BYTES 64
 define_int CONFIG_X86_L1_CACHE_SHIFT 6
+fi
 define_bool CONFIG_X86_TSC y
 define_bool CONFIG_X86_GOOD_APIC y
 
@@ -58,6 +64,9 @@ bool 'MTRR (Memory Type Range Register) 
 bool 'Symmetric multi-processing support' CONFIG_SMP
 bool 'HPET timers' CONFIG_HPET_TIMER
 bool 'IOMMU support' CONFIG_GART_IOMMU
+if [ "$CONFIG_GART_IOMMU" = "y" ]; then
+    bool 'SWIOTLB support' CONFIG_SWIOTLB
+fi
 
 if [ "$CONFIG_GART_IOMMU" != "y" ]; then
    define_bool CONFIG_DUMMY_IOMMU y
@@ -141,6 +150,7 @@ tristate 'ATA/IDE/MFM/RLL support' CONFI
 if [ "$CONFIG_IDE" != "n" ]; then
   source drivers/ide/Config.in
 else
+  define_bool CONFIG_BLK_DEV_IDE_MODES n
   define_bool CONFIG_BLK_DEV_HD n
 fi
 endmenu
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/defconfig linux-2.4.26-pre6/arch/x86_64/defconfig
--- linux-2.4.25/arch/x86_64/defconfig	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/defconfig	2004-03-25 00:19:43.000000000 +0000
@@ -26,10 +26,11 @@ CONFIG_MODULES=y
 #
 # Processor type and features
 #
-CONFIG_MK8=y
+# CONFIG_MK8 is not set
+CONFIG_MPSC=y
 # CONFIG_GENERIC_CPU is not set
-CONFIG_X86_L1_CACHE_BYTES=64
-CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_MSR=y
@@ -43,6 +44,7 @@ CONFIG_MTRR=y
 CONFIG_SMP=y
 CONFIG_HPET_TIMER=y
 CONFIG_GART_IOMMU=y
+CONFIG_SWIOTLB=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=4
 CONFIG_MCE=y
@@ -159,6 +161,9 @@ CONFIG_INET=y
 #
 CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -254,7 +259,7 @@ CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -275,6 +280,7 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -421,7 +427,8 @@ CONFIG_VORTEX=y
 #
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.26-pre6/arch/x86_64/ia32/ia32_ioctl.c
--- linux-2.4.25/arch/x86_64/ia32/ia32_ioctl.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/ia32/ia32_ioctl.c	2004-03-25 00:21:38.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: ia32_ioctl.c,v 1.39 2004/01/29 03:01:57 ak Exp $
+/* $Id: ia32_ioctl.c,v 1.44 2004/03/21 22:32:20 ak Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -1785,7 +1785,10 @@ struct cdrom_generic_command32 {
 	unsigned int		buflen;
 	int			stat;
 	__kernel_caddr_t32	sense;
-	__kernel_caddr_t32	reserved[3];
+	unsigned char		data_direction;
+	int			quiet;
+	int			timeout;
+	__kernel_caddr_t32	reserved[1];
 };
 
 static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -1827,17 +1830,25 @@ static int cdrom_ioctl_trans(unsigned in
 			return -EFAULT;
 		cdreadaudio.buf = (void *)A(addr);
 		break;
-	case CDROM_SEND_PACKET:
+	case CDROM_SEND_PACKET: {
+		__kernel_caddr_t32 sense;
 		karg = &cgc;
 		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
 		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
 		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
+		err |= __get_user(sense, &((struct cdrom_generic_command32 *)arg)->sense);
+		err |= __get_user(cgc.data_direction, &((struct cdrom_generic_command32 *)arg)->data_direction);
+		err |= __get_user(cgc.timeout, &((struct cdrom_generic_command32 *)arg)->timeout);
 		if (err)
 			return -EFAULT;
 		if (verify_area(VERIFY_WRITE, (void *)A(addr), cgc.buflen))
 			return -EFAULT;
+		if (sense && verify_area(VERIFY_WRITE, (void *)A(sense), sizeof(struct request_sense)))
+			return -EFAULT;
 		cgc.buffer = (void *)A(addr);
+		cgc.sense = (void *)A(sense);
 		break;
+	}
 	default:
 		do {
 			static int count;
@@ -2754,7 +2765,7 @@ static int tiocgdev(unsigned fd, unsigne
 	struct file *file = fget(fd);
 	struct tty_struct *real_tty;
 
-	if (!fd)
+	if (!file)
 		return -EBADF;
 	if (file->f_op->ioctl != tty_ioctl)
 		return -EINVAL; 
@@ -3535,6 +3546,33 @@ static int do_wireless_ioctl(unsigned in
 	return sys_ioctl(fd, cmd, (unsigned long) iwr);
 }
 
+struct compat_ctrlmsg_ioctl { 
+	struct usb_ctrlrequest req;
+	u32 data;
+}; 
+
+struct ctrlmsg_ioctl { 
+	struct usb_ctrlrequest req;
+	void *data;
+}; 
+
+#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest)
+
+static int scanner_ioctl_ctrlmsg(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ctrlmsg_ioctl *c64;
+	struct compat_ctrlmsg_ioctl *c32 = (void *)arg; 
+	u32 ptr;
+
+	c64 = compat_alloc_user_space(sizeof(struct ctrlmsg_ioctl));
+
+	if (copy_in_user(&c64->req, &c32->req, sizeof(struct usb_ctrlrequest)) ||
+	    get_user(ptr, &c32->data) || 
+	    put_user((void *)(unsigned long)ptr, &c64->data))
+		return -EFAULT;
+	return sys_ioctl(fd,cmd, (unsigned long)c64); 
+} 
+
 struct ioctl_trans {
 	unsigned long cmd;
 	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
@@ -4423,6 +4461,17 @@ HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_i
 HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl)
 HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl)
 COMPATIBLE_IOCTL(SIOCGIWNAME)
+
+COMPATIBLE_IOCTL(SIOCSIFNAME)
+/* usb scanner */
+#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
+#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
+
+COMPATIBLE_IOCTL(SCANNER_IOCTL_VENDOR)
+COMPATIBLE_IOCTL(SCANNER_IOCTL_PRODUCT)
+/* USB scanner 'U' */
+HANDLE_IOCTL(SCANNER_IOCTL_CTRLMSG, scanner_ioctl_ctrlmsg)
+
 IOCTL_TABLE_END
 
 #define IOCTL_HASHSIZE 256
@@ -4602,7 +4651,9 @@ asmlinkage long sys32_ioctl(unsigned int
 		t = (struct ioctl_trans *)t->next;
 	if (t) {
 		handler = t->handler;
+		lock_kernel();
 		error = handler(fd, cmd, arg, filp);
+		unlock_kernel();
 	} else if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
 		error = siocdevprivate_ioctl(fd, cmd, arg);
 	} else {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/ia32/ptrace32.c linux-2.4.26-pre6/arch/x86_64/ia32/ptrace32.c
--- linux-2.4.25/arch/x86_64/ia32/ptrace32.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/ia32/ptrace32.c	2004-03-25 00:22:01.000000000 +0000
@@ -8,7 +8,7 @@
  * This allows to access 64bit processes too; but there is no way to see the extended 
  * register contents.
  *
- * $Id: ptrace32.c,v 1.18 2004/01/29 00:50:29 ak Exp $
+ * $Id: ptrace32.c,v 1.19 2004/01/29 03:31:13 ak Exp $
  */ 
 
 #include <linux/kernel.h>
@@ -73,9 +73,12 @@ static int putreg32(struct task_struct *
 	R32(eip, rip);
 	R32(esp, rsp);
 
-	case offsetof(struct user32, regs.eflags): 
-		stack[offsetof(struct pt_regs, eflags)/8] = val & 0x44dd5; 
+	case offsetof(struct user32, regs.eflags): { 
+		__u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8];
+		val &= FLAG_MASK;
+		*flags = val | (*flags & ~FLAG_MASK);
 		break;
+	}
 
 	case offsetof(struct user32, u_debugreg[4]): 
 	case offsetof(struct user32, u_debugreg[5]):
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/ia32/sys_ia32.c linux-2.4.26-pre6/arch/x86_64/ia32/sys_ia32.c
--- linux-2.4.25/arch/x86_64/ia32/sys_ia32.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/ia32/sys_ia32.c	2004-03-25 00:21:46.000000000 +0000
@@ -16,7 +16,7 @@
  *
  * This file assumes that there is a hole at the end of user address space.
  *
- * $Id: sys_ia32.c,v 1.69 2004/01/29 02:52:13 ak Exp $
+ * $Id: sys_ia32.c,v 1.70 2004/03/03 23:36:43 ak Exp $
  */
 
 #include <linux/config.h>
@@ -1802,7 +1802,7 @@ sys32_rt_sigtimedwait(sigset32_t *uthese
 			return -EFAULT;
 	}
 	set_fs (KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
+	ret = sys_rt_sigtimedwait(&s, &info, uts ? &t : NULL, sigsetsize);
 	set_fs (old_fs);
 	if (ret >= 0 && uinfo) {
 		if (copy_to_user (uinfo, siginfo64to32(&info32, &info),
@@ -3042,7 +3042,7 @@ struct exec_domain ia32_exec_domain = { 
 
 static int __init ia32_init (void)
 {
-	printk("IA32 emulation $Id: sys_ia32.c,v 1.69 2004/01/29 02:52:13 ak Exp $\n");  
+	printk("IA32 emulation $Id: sys_ia32.c,v 1.70 2004/03/03 23:36:43 ak Exp $\n");  
 	ia32_exec_domain.signal_map = default_exec_domain.signal_map;
 	ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
 	register_exec_domain(&ia32_exec_domain);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/Makefile linux-2.4.26-pre6/arch/x86_64/kernel/Makefile
--- linux-2.4.25/arch/x86_64/kernel/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/Makefile	2004-03-25 00:18:00.000000000 +0000
@@ -14,8 +14,7 @@ all: kernel.o head.o head64.o init_task.
 
 O_TARGET := kernel.o
 
-
-export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o pci-gart.o setup.o
+export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o pci-gart.o setup.o swiotlb.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
@@ -34,6 +33,7 @@ obj-$(CONFIG_SMP)	+= smp.o smpboot.o tra
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o  nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
 obj-$(CONFIG_EARLY_PRINTK) +=  early_printk.o
+obj-$(CONFIG_SWIOTLB) += swiotlb.o
 obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o
 obj-$(CONFIG_MCE) += bluesmoke.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/acpi.c linux-2.4.26-pre6/arch/x86_64/kernel/acpi.c
--- linux-2.4.25/arch/x86_64/kernel/acpi.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/acpi.c	2004-03-25 00:22:12.000000000 +0000
@@ -47,14 +47,17 @@
 
 #define PREFIX			"ACPI: "
 
-int acpi_lapic = 0;
-int acpi_ioapic = 0;
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
 
+acpi_interrupt_flags acpi_sci_flags __initdata;
+int acpi_sci_override_gsi __initdata;
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_BOOT
+int acpi_ht __initdata = 1;	/* enable HT */
 
 enum acpi_irq_model_id		acpi_irq_model;
 
@@ -226,6 +229,54 @@ acpi_parse_ioapic (
 	return 0;
 }
 
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_parse_sci_int_src_ovr(u8 bus_irq, u16 polarity, u16 trigger, u32 global_irq)
+{
+	if (trigger == 0)	/* compatible SCI trigger is level */
+		trigger = 3;
+
+	if (polarity == 0)	/* compatible SCI polarity is low */
+		polarity = 3;
+
+	/* Command-line over-ride via acpi_sci= */
+	if (acpi_sci_flags.trigger)
+		trigger = acpi_sci_flags.trigger;
+
+	if (acpi_sci_flags.polarity)
+		polarity = acpi_sci_flags.polarity;
+
+	mp_override_legacy_irq(bus_irq, polarity, trigger, global_irq);
+
+	/*
+	 * stash over-ride to indicate we've been here
+	 * and for later update of acpi_fadt
+	 */
+	acpi_sci_override_gsi = global_irq;
+	return;
+}
+
+static int __init
+acpi_parse_fadt(unsigned long phys, unsigned long size)
+{
+	struct fadt_descriptor_rev2 *fadt =0;
+
+	fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
+	if (!fadt) {
+		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
+		return 0;
+	}
+
+#ifdef	CONFIG_ACPI_INTERPRETER
+	/* initialize sci_int early for INT_SRC_OVR MADT parsing */
+	acpi_fadt.sci_int = fadt->sci_int;
+#endif
+
+	return 0;
+}
+
 
 static int __init
 acpi_parse_int_src_ovr (
@@ -239,6 +290,13 @@ acpi_parse_int_src_ovr (
 
 	acpi_table_print_madt_entry(header);
 
+	if (intsrc->bus_irq == acpi_fadt.sci_int) {
+		acpi_parse_sci_int_src_ovr(intsrc->bus_irq,
+			intsrc->flags.polarity, intsrc->flags.trigger,
+			intsrc->global_irq);
+		return 0;
+	}
+
 	mp_override_legacy_irq (
 		intsrc->bus_irq,
 		intsrc->flags.polarity,
@@ -292,13 +350,12 @@ acpi_parse_hpet (
 
 #ifdef CONFIG_ACPI_BUS
 /*
- * "acpi_pic_sci=level" (current default)
- * programs the PIC-mode SCI to Level Trigger.
- * (NO-OP if the BIOS set Level Trigger already)
+ * acpi_pic_sci_set_trigger()
+ *
+ * use ELCR to set PIC-mode trigger type for SCI
  *
- * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
- * it may require Edge Trigger -- use "acpi_pic_sci=edge"
- * (NO-OP if the BIOS set Edge Trigger already)
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
+ * it may require Edge Trigger -- use "acpi_sci=edge"
  *
  * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
  * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
@@ -306,52 +363,32 @@ acpi_parse_hpet (
  * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
  */
 
-static __initdata int	acpi_pic_sci_trigger;	/* 0: level, 1: edge */
-
 void __init
-acpi_pic_sci_set_trigger(unsigned int irq)
+acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 {
 	unsigned char mask = 1 << (irq & 7);
 	unsigned int port = 0x4d0 + (irq >> 3);
 	unsigned char val = inb(port);
 
-	
+
 	printk(PREFIX "IRQ%d SCI:", irq);
 	if (!(val & mask)) {
 		printk(" Edge");
 
-		if (!acpi_pic_sci_trigger) {
+		if (trigger == 3) {
 			printk(" set to Level");
 			outb(val | mask, port);
 		}
 	} else {
 		printk(" Level");
 
-		if (acpi_pic_sci_trigger) {
+		if (trigger == 1) {
 			printk(" set to Edge");
-			outb(val | mask, port);
+			outb(val & ~mask, port);
 		}
 	}
 	printk(" Trigger.\n");
 }
-
-int __init
-acpi_pic_sci_setup(char *str)
-{
-	while (str && *str) {
-		if (strncmp(str, "level", 5) == 0)
-			acpi_pic_sci_trigger = 0;	/* force level trigger */
-		if (strncmp(str, "edge", 4) == 0)
-			acpi_pic_sci_trigger = 1;	/* force edge trigger */
-		str = strchr(str, ',');
-		if (str)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("acpi_pic_sci=", acpi_pic_sci_setup);
-
 #endif /* CONFIG_ACPI_BUS */
 
 static unsigned long __init
@@ -412,7 +449,7 @@ acpi_boot_init (void)
 	 */
 	result = acpi_table_init();
 	if (result) {
-		acpi_disabled = 1;
+		disable_acpi();
 		return result;
 	}
 
@@ -535,6 +572,9 @@ acpi_boot_init (void)
 	/* Build a default routing table for legacy (ISA) interrupts. */
 	mp_config_acpi_legacy_irqs();
 
+	/* Record sci_int for use when looking for MADT sci_int override */
+	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
+
 	result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
 	if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
@@ -542,6 +582,13 @@ acpi_boot_init (void)
 		return result;
 	}
 
+	/*
+	 * If BIOS did not supply an INT_SRC_OVR for the SCI
+	 * pretend we got one so we can set the SCI flags.
+	 */
+	if (!acpi_sci_override_gsi)
+		acpi_parse_sci_int_src_ovr(acpi_fadt.sci_int, 0, 0, acpi_fadt.sci_int);
+
 	result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
 	if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
@@ -567,8 +614,6 @@ acpi_boot_init (void)
 	return 0;
 }
 
-#endif /*CONFIG_ACPI_BOOT*/
-
 
 /* --------------------------------------------------------------------------
                               Low-Level Sleep Support
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/aperture.c linux-2.4.26-pre6/arch/x86_64/kernel/aperture.c
--- linux-2.4.25/arch/x86_64/kernel/aperture.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/aperture.c	2004-03-25 00:22:07.000000000 +0000
@@ -8,7 +8,7 @@
  * because only the bootmem allocator can allocate 32+MB. 
  * 
  * Copyright 2002 Andi Kleen, SuSE Labs.
- * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $
+ * $Id: aperture.c,v 1.8 2004/02/27 18:30:19 ak Exp $
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -27,6 +27,8 @@
 int fallback_aper_order __initdata = 1; /* 64MB */
 int fallback_aper_force __initdata = 0; 
 
+int iommu_aperture;
+
 extern int no_iommu, force_mmu;
 
 /* This code runs before the PCI subsystem is initialized, so just 
@@ -198,6 +200,8 @@ void __init iommu_hole_init(void) 
 		if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
 			continue;	
 
+		iommu_aperture = 1;
+
 		aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 
 		aper_size = (32 * 1024 * 1024) << aper_order; 
 		aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/e820.c linux-2.4.26-pre6/arch/x86_64/kernel/e820.c
--- linux-2.4.25/arch/x86_64/kernel/e820.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/e820.c	2004-03-25 00:18:57.000000000 +0000
@@ -1,12 +1,13 @@
 /* 
  * Handle the memory map.
  * The functions here do the job until bootmem takes over.
- * $Id: e820.c,v 1.12 2004/01/13 10:13:30 ak Exp $
+ * $Id: e820.c,v 1.13 2004/03/22 00:31:08 ak Exp $
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
 #include <asm/page.h>
@@ -21,6 +22,10 @@
 extern unsigned long table_start, table_end;
 extern char _end[];
 
+#ifdef	CONFIG_ACPI_BOOT
+extern acpi_interrupt_flags	acpi_sci_flags;
+#endif
+
 extern struct resource code_resource, data_resource, vram_resource;
 
 /* Check for some hardcoded bad areas that early boot is not allowed to touch */ 
@@ -541,12 +546,39 @@ void __init parse_mem_cmdline (char ** c
 			iommu_setup(from+6); 
 		} 	
 #endif
+#ifdef	CONFIG_SMP
+		/*
+		 * If the BIOS enumerates physical processors before logical,
+		 * maxcpus=N at enumeration-time can be used to disable HT.
+		 */
+		else if (!memcmp(from, "maxcpus=", 8)) {
+			extern unsigned int max_cpus;
+
+			max_cpus = simple_strtoul(from + 8, NULL, 0);
+		}
+#endif
+
 #ifdef	CONFIG_ACPI_BOOT
  		else if (!memcmp(from, "acpi=off", 8))
-  			acpi_disabled = 1;
+  			disable_acpi();
+
+		/* acpi=strict disables out-of-spec workarounds */
+		else if (!memcmp(from, "acpi=strict", 11)) {
+			acpi_strict = 1;
+		}
+
 		else if (!memcmp(from, "pci=noacpi", 10)) {
 			acpi_noirq_set();
 		}
+
+		else if (!memcmp(from, "acpi_sci=edge", 13))
+			acpi_sci_flags.trigger =  1;
+		else if (!memcmp(from, "acpi_sci=level", 14))
+			acpi_sci_flags.trigger = 3;
+		else if (!memcmp(from, "acpi_sci=high", 13))
+			acpi_sci_flags.polarity = 1;
+		else if (!memcmp(from, "acpi_sci=low", 12))
+			acpi_sci_flags.polarity = 3;
 #endif
 		else if (!memcmp(from,"maxcpus=0",9)) {
 			disable_ioapic_setup();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/head.S linux-2.4.26-pre6/arch/x86_64/kernel/head.S
--- linux-2.4.25/arch/x86_64/kernel/head.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/head.S	2004-03-25 00:20:32.000000000 +0000
@@ -6,7 +6,7 @@
  *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
  *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
  *
- *  $Id: head.S,v 1.58 2003/11/02 05:05:31 ak Exp $
+ *  $Id: head.S,v 1.59 2004/02/10 05:53:06 ak Exp $
  */
 
 
@@ -341,7 +341,7 @@ gdt32_end:	
 .align 64 /* cacheline aligned, keep this synchronized with asm/desc.h */
 ENTRY(gdt_table)
 	.quad	0x0000000000000000	/* This one is magic */
-	.quad	0x00af9a000000ffff ^ (1<<21)	/* __KERNEL_COMPAT32_CS */	
+	.quad	0x008f9a000000ffff	/* __KERNEL_COMPAT32_CS */	
 	.quad	0x00af9a000000ffff	/* __KERNEL_CS */
 	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
 	.quad	0x00cffe000000ffff	/* __USER32_CS */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/mpparse.c linux-2.4.26-pre6/arch/x86_64/kernel/mpparse.c
--- linux-2.4.25/arch/x86_64/kernel/mpparse.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/mpparse.c	2004-03-25 00:18:45.000000000 +0000
@@ -35,6 +35,9 @@
 
 /* Have we found an MP table */
 int smp_found_config = 0;
+#ifdef	CONFIG_SMP
+extern unsigned int max_cpus;
+#endif
 
 /*
  * Various Linux-internal data structures created from the
@@ -111,6 +114,20 @@ static void __init MP_processor_info (st
 		Dprintk("    Bootup CPU\n");
 		boot_cpu_id = m->mpc_apicid;
 	}
+
+#ifdef	CONFIG_SMP
+	if (num_processors >= NR_CPUS) {
+		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+			" Processor ignored.\n", NR_CPUS);
+		return;
+	}
+	if (num_processors >= max_cpus) {
+		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+			" Processor ignored.\n", max_cpus);
+		return;
+	}
+#endif
+
 	num_processors++;
 
 	if (m->mpc_apicid > MAX_APICS) {
@@ -794,7 +811,7 @@ void __init mp_override_legacy_irq (
 	 *      erroneously sets the trigger to level, resulting in a HUGE 
 	 *      increase of timer interrupts!
 	 */
-	if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3))
+	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
 	intsrc.mpc_type = MP_INTSRC;
@@ -815,7 +832,7 @@ void __init mp_override_legacy_irq (
 	 * Otherwise create a new entry (e.g. global_irq == 2).
 	 */
 	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) 
+		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
 			&& (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) {
 			mp_irqs[i] = intsrc;
 			found = 1;
@@ -862,9 +879,10 @@ void __init mp_config_acpi_legacy_irqs (
 	 */
 	for (i = 0; i < 16; i++) {
 
-		if (i == 2) continue;			/* Don't connect IRQ2 */
+		if (i == 2)
+			continue;			/* Don't connect IRQ2 */
 
-		intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT;   /* 8259A to #0 */
+		intsrc.mpc_irqtype = mp_INT;
 		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
 		intsrc.mpc_dstirq = i;
 
@@ -888,63 +906,6 @@ void __init mp_config_acpi_legacy_irqs (
 
 extern FADT_DESCRIPTOR acpi_fadt;
 
-void __init mp_config_ioapic_for_sci(int irq)
-{
-	int ioapic;
-	int ioapic_pin;
-	struct acpi_table_madt* madt;
-	struct acpi_table_int_src_ovr *entry = NULL;
-	acpi_interrupt_flags flags;
-	void *madt_end;
-	acpi_status status;
-
-	/*
-	 * Ensure that if there is an interrupt source override entry
-	 * for the ACPI SCI, we leave it as is. Unfortunately this involves
-	 * walking the MADT again.
-	 */
-	status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING,
-		(struct acpi_table_header **) &madt);
-	if (ACPI_SUCCESS(status)) {
-		madt_end = (void *) (unsigned long)madt + madt->header.length;
-
-		entry = (struct acpi_table_int_src_ovr *)
-                ((unsigned long) madt + sizeof(struct acpi_table_madt));
-
-		while ((void *) entry < madt_end) {
-                	if (entry->header.type == ACPI_MADT_INT_SRC_OVR &&
- 			    acpi_fadt.sci_int == entry->bus_irq)
- 				goto found;
-
-                	entry = (struct acpi_table_int_src_ovr *)
-                	        ((unsigned long) entry + entry->header.length);
-        	}
-	}
- 	/*
- 	 * Although the ACPI spec says that the SCI should be level/low
- 	 * don't reprogram it unless there is an explicit MADT OVR entry
- 	 * instructing us to do so -- otherwise we break Tyan boards which
- 	 * have the SCI wired edge/high but no MADT OVR.
- 	 */
- 	return;
-
-found:
- 	/*
- 	 * See the note at the end of ACPI 2.0b section
- 	 * 5.2.10.8 for what this is about.
- 	 */
- 	flags = entry->flags;
- 	acpi_fadt.sci_int = entry->global_irq;
- 	irq = entry->global_irq;
-
-	ioapic = mp_find_ioapic(irq);
-
-	ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
-
- 	io_apic_set_pci_routing(ioapic, ioapic_pin, irq, 
- 				(flags.trigger >> 1) , (flags.polarity >> 1));
-}
-
 #endif /*CONFIG_ACPI_HT_ONLY*/
 
 int acpi_tolerant;
@@ -1008,7 +969,7 @@ void __init mp_parse_prt (void)
 			continue;
 		}
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 			entry->irq = irq;
 			continue;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/mtrr.c linux-2.4.26-pre6/arch/x86_64/kernel/mtrr.c
--- linux-2.4.25/arch/x86_64/kernel/mtrr.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/mtrr.c	2004-03-25 00:17:26.000000000 +0000
@@ -144,11 +144,14 @@ static void set_mtrr_prepare (struct set
 	write_cr0(cr0);
 	wbinvd();
 
-	/* Disable MTRRs, and set the default type to uncached */
 	rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
-	wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
 }
 
+static void set_mtrr_disable(struct set_mtrr_context *ctxt) 
+{ 
+	/* Disable MTRRs, and set the default type to uncached */
+	wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
+} 
 
 /* Restore the processor after a set_mtrr_prepare */
 static void set_mtrr_done (struct set_mtrr_context *ctxt)
@@ -242,8 +245,10 @@ static void set_mtrr_up (unsigned int re
 	u64 base64;
 	u64 size64;
 
-	if (do_safe)
+	if (do_safe) { 
 		set_mtrr_prepare (&ctxt);
+		set_mtrr_disable (&ctxt); 
+	} 
 
 	if (size == 0) {
 		/* The invalid bit is kept in the mask, so we simply clear the
@@ -430,6 +435,7 @@ static u64 __init set_mtrr_state (struct
 
 
 static atomic_t undone_count;
+static volatile int wait_barrier_mtrr_disable = FALSE;
 static volatile int wait_barrier_execute = FALSE;
 static volatile int wait_barrier_cache_enable = FALSE;
 
@@ -451,8 +457,18 @@ static void ipi_handler (void *info)
 	set_mtrr_prepare (&ctxt);
 	/* Notify master that I've flushed and disabled my cache  */
 	atomic_dec (&undone_count);
-	while (wait_barrier_execute)
+
+	while (wait_barrier_mtrr_disable) {
+		rep_nop();
 		barrier ();
+	}	
+	set_mtrr_disable (&ctxt); 
+	/* wait again for disable confirmation*/
+	atomic_dec (&undone_count);
+	while (wait_barrier_execute) { 
+		rep_nop(); 
+		barrier(); 
+	}	
 
 	/* The master has cleared me to execute  */
 	set_mtrr_up (data->smp_reg, data->smp_base, data->smp_size,
@@ -462,8 +478,10 @@ static void ipi_handler (void *info)
 	atomic_dec (&undone_count);
 
 	/* Wait for master to clear me to enable cache and return  */
-	while (wait_barrier_cache_enable)
+	while (wait_barrier_cache_enable) {
+		rep_nop();
 		barrier ();
+	}	
 	set_mtrr_done (&ctxt);
 }
 
@@ -479,6 +497,7 @@ static void set_mtrr_smp (unsigned int r
 	data.smp_type = type;
 	wait_barrier_execute = TRUE;
 	wait_barrier_cache_enable = TRUE;
+	wait_barrier_mtrr_disable = TRUE;
 	atomic_set (&undone_count, smp_num_cpus - 1);
 
 	/*  Start the ball rolling on other CPUs  */
@@ -487,10 +506,21 @@ static void set_mtrr_smp (unsigned int r
 
 	/* Flush and disable the local CPU's cache */
 	set_mtrr_prepare (&ctxt);
+	while (atomic_read (&undone_count) > 0) { 
+		rep_nop();
+		barrier(); 
+	}
+
+	/* Set up for completion wait and then release other CPUs to change MTRRs*/
+	atomic_set (&undone_count, smp_num_cpus - 1);
+	wait_barrier_mtrr_disable = FALSE;
+	set_mtrr_disable (&ctxt);
 
 	/*  Wait for all other CPUs to flush and disable their caches  */
-	while (atomic_read (&undone_count) > 0)
+	while (atomic_read (&undone_count) > 0) { 
+		rep_nop ();
 		barrier ();
+	}	
 
 	/* Set up for completion wait and then release other CPUs to change MTRRs */
 	atomic_set (&undone_count, smp_num_cpus - 1);
@@ -498,8 +528,10 @@ static void set_mtrr_smp (unsigned int r
 	set_mtrr_up (reg, base, size, type, FALSE);
 
 	/*  Now wait for other CPUs to complete the function  */
-	while (atomic_read (&undone_count) > 0)
+	while (atomic_read (&undone_count) > 0) {
+		rep_nop();
 		barrier ();
+	} 	
 
 	/*  Now all CPUs should have finished the function. Release the barrier to
 	   allow them to re-enable their caches and return from their interrupt,
@@ -1282,6 +1314,7 @@ void __init mtrr_init_secondary_cpu (voi
 	   for this CPU while the MTRRs are changed, but changing this requires
 	   more invasive changes to the way the kernel boots  */
 	set_mtrr_prepare (&ctxt);
+	set_mtrr_disable (&ctxt);
 	mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
 	set_mtrr_done (&ctxt);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/nmi.c linux-2.4.26-pre6/arch/x86_64/kernel/nmi.c
--- linux-2.4.25/arch/x86_64/kernel/nmi.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/nmi.c	2004-03-25 00:18:37.000000000 +0000
@@ -34,6 +34,13 @@ int panic_on_timeout;
 
 int nmi_watchdog_disabled; 
 
+/* Small problem with theaw events is that they stop ticking
+   when the CPU is idling. This means you get varying NMI watchdog
+   frequencies depending on the CPU load.
+
+   I doubt it can be fixed because it's unlikely that the CPU does 
+   performance counters while being in C* states. -AK */
+
 #define K7_EVNTSEL_ENABLE	(1 << 22)
 #define K7_EVNTSEL_INT		(1 << 20)
 #define K7_EVNTSEL_OS		(1 << 17)
@@ -215,6 +222,11 @@ static void __pminit setup_k7_watchdog(v
 {
 	unsigned int evntsel;
 
+#if 0
+	/* No check, so can start with slow frequency */
+	nmi_hz = 1; 
+#endif	
+
 	nmi_perfctr_msr = MSR_K7_PERFCTR0;
 
 	clear_msr_range(MSR_K7_EVNTSEL0, 4);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/pci-gart.c linux-2.4.26-pre6/arch/x86_64/kernel/pci-gart.c
--- linux-2.4.25/arch/x86_64/kernel/pci-gart.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/pci-gart.c	2004-03-25 00:17:20.000000000 +0000
@@ -8,7 +8,7 @@
  * See Documentation/DMA-mapping.txt for the interface specification.
  * 
  * Copyright 2002 Andi Kleen, SuSE Labs.
- * $Id: pci-gart.c,v 1.30 2004/01/13 09:09:32 ak Exp $
+ * $Id: pci-gart.c,v 1.32 2004/02/27 18:30:19 ak Exp $
  */
 
 #include <linux/config.h>
@@ -220,7 +220,7 @@ void pci_free_consistent(struct pci_dev 
 	unsigned long iommu_page;
 
 	size = round_up(size, PAGE_SIZE); 
-	if (bus >= iommu_bus_base && bus <= iommu_bus_base + iommu_size) { 
+	if (bus >= iommu_bus_base && bus < iommu_bus_base + iommu_size) { 
 		unsigned pages = size >> PAGE_SHIFT;
 		iommu_page = (bus - iommu_bus_base) >> PAGE_SHIFT;
 		vaddr = __va(GPTE_DECODE(iommu_gatt_base[iommu_page]));
@@ -310,6 +310,12 @@ dma_addr_t pci_map_single(struct pci_dev
 
 	BUG_ON(dir == PCI_DMA_NONE);
 
+#ifdef CONFIG_SWIOTLB
+       if (swiotlb)
+               return swiotlb_map_single(dev,addr,size,dir);
+#endif
+
+
 	phys_mem = virt_to_phys(addr); 
 	if (!need_iommu(dev, phys_mem, size))
 		return phys_mem; 
@@ -352,8 +358,17 @@ void pci_unmap_single(struct pci_dev *hw
 {
 	unsigned long iommu_page; 
 	int npages;
+
+#ifdef CONFIG_SWIOTLB
+       if (swiotlb) {
+               swiotlb_unmap_single(hwdev,dma_addr,size,direction);
+              return;
+       }
+#endif
+
+
 	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || 
-	    dma_addr > iommu_bus_base + iommu_size)
+	    dma_addr >= iommu_bus_base + iommu_size)
 		return;
 	iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;	
 	npages = round_up(size + (dma_addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT;
@@ -488,7 +503,14 @@ void __init pci_iommu_init(void)
 	no_agp = no_agp || (agp_init() < 0) || (agp_copy_info(&info) < 0); 
 #endif	
 
-	if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { 
+	if (swiotlb) { 
+		no_iommu = 1;
+		printk(KERN_INFO "PCI-DMA: Using SWIOTLB\n"); 
+		return; 
+	} 
+
+
+	if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT) || !iommu_aperture) { 
 		printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); 
 		no_iommu = 1;
 		return;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/pci-pc.c linux-2.4.26-pre6/arch/x86_64/kernel/pci-pc.c
--- linux-2.4.25/arch/x86_64/kernel/pci-pc.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/pci-pc.c	2004-03-25 00:20:46.000000000 +0000
@@ -645,6 +645,9 @@ char * __devinit pcibios_setup(char *str
 	} else if (!strncmp(str, "lastbus=", 8)) {
 		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
 		return NULL;
+	} else if (!strncmp(str, "noacpi", 6)) {
+		acpi_noirq_set();
+		return NULL;
 	}
 	return str;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/process.c linux-2.4.26-pre6/arch/x86_64/kernel/process.c
--- linux-2.4.25/arch/x86_64/kernel/process.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/process.c	2004-03-25 00:19:15.000000000 +0000
@@ -9,7 +9,7 @@
  *  X86-64 port
  *	Andi Kleen.
  * 
- *  $Id: process.c,v 1.75 2004/01/13 09:04:32 ak Exp $
+ *  $Id: process.c,v 1.77 2004/03/22 00:37:29 ak Exp $
  */
 
 /*
@@ -147,11 +147,57 @@ void cpu_idle (void)
 	}
 }
 
+/*
+ * This is a kind of hybrid between poll and halt idle routines. This uses new
+ * Monitor/Mwait instructions on P4 processors with PNI. We Monitor 
+ * need_resched and go to optimized wait state through Mwait. 
+ * Whenever someone changes need_resched, we would be woken up from Mwait 
+ * (without an IPI).
+ */
+static void mwait_idle (void)
+{
+	int oldval;
+
+	__sti();
+	/* Setting need_resched to -1 skips sending IPI during idle resched */
+	oldval = xchg(&current->need_resched, -1);
+	if (!oldval) {
+		do {
+			__monitor((void *)&current->need_resched, 0, 0);
+			if (current->need_resched != -1)
+				break;
+			__mwait(0, 0);
+		} while (current->need_resched == -1);
+	}
+}
+
+int __init select_idle_routine(struct cpuinfo_x86 *c)
+{
+	if (cpu_has(c, X86_FEATURE_MWAIT)) {
+		printk("Monitor/Mwait feature present.\n");
+		/*
+		 * Take care of system with asymmetric CPUs.
+		 * Use, mwait_idle only if all cpus support it.
+		 * If not, we fallback to default_idle()
+		 */
+		if (!pm_idle) {
+			pm_idle = mwait_idle;
+		}
+		return 1;
+	}
+	pm_idle = default_idle;
+	return 1;
+}
+
+
 static int __init idle_setup (char *str)
 {
 	if (!strncmp(str, "poll", 4)) {
 		printk("using polling idle threads.\n");
 		pm_idle = poll_idle;
+	} else if (!strncmp(str, "halt", 4)) {
+		printk("using halt in idle threads.\n");
+                pm_idle = default_idle;
 	}
 
 	return 1;
@@ -301,7 +347,7 @@ void machine_restart(char * __unused)
 			/* force cold reboot to reinit all hardware*/
 			*((unsigned short *)__va(0x472)) = 0;
 
-		__asm__ __volatile__("lidt %0": :"m" (no_idt));
+			__asm__ __volatile__("lidt (%0)": :"r" (no_idt));
 		__asm__ __volatile__("int3");
 
 			reboot_type = BOOT_KBD;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/setup.c linux-2.4.26-pre6/arch/x86_64/kernel/setup.c
--- linux-2.4.25/arch/x86_64/kernel/setup.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/setup.c	2004-03-25 00:18:08.000000000 +0000
@@ -54,6 +54,10 @@ int acpi_noirq __initdata = 0;	/* skip A
 #endif
 
 
+int swiotlb;
+
+extern	int phys_proc_id[NR_CPUS];
+
 /*
  * Machine setup..
  */
@@ -228,6 +232,8 @@ void __init setup_arch(char **cmdline_p)
 
 	e820_end_of_ram();
 
+	check_efer();
+
 	init_memory_mapping(); 
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -308,8 +314,7 @@ void __init setup_arch(char **cmdline_p)
 	/*
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
 	 */
-	if (!acpi_disabled)
-		acpi_boot_init();
+	acpi_boot_init();
 #endif
 #ifdef CONFIG_X86_LOCAL_APIC
 	/*
@@ -341,6 +346,12 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_GART_IOMMU
 	iommu_hole_init();
 #endif
+#ifdef CONFIG_SWIOTLB
+       if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT) { 
+              swiotlb_init();
+              swiotlb = 1;
+       }
+#endif
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
@@ -404,6 +415,198 @@ static void __init display_cacheinfo(str
 	}
 }
 
+#define LVL_1_INST      1
+#define LVL_1_DATA      2
+#define LVL_2           3
+#define LVL_3           4
+#define LVL_TRACE       5
+
+struct _cache_table
+{
+        unsigned char descriptor;
+        char cache_type;
+        short size;
+};
+
+/* all the cache descriptor types we care about (no TLB or trace cache entries) */
+static struct _cache_table cache_table[] __initdata =
+{
+	{ 0x06, LVL_1_INST, 8 },
+	{ 0x08, LVL_1_INST, 16 },
+	{ 0x0A, LVL_1_DATA, 8 },
+	{ 0x0C, LVL_1_DATA, 16 },
+	{ 0x22, LVL_3,      512 },
+	{ 0x23, LVL_3,      1024 },
+	{ 0x25, LVL_3,      2048 },
+	{ 0x29, LVL_3,      4096 },
+	{ 0x39, LVL_2,      128 },
+	{ 0x3C, LVL_2,      256 },
+	{ 0x41, LVL_2,      128 },
+	{ 0x42, LVL_2,      256 },
+	{ 0x43, LVL_2,      512 },
+	{ 0x44, LVL_2,      1024 },
+	{ 0x45, LVL_2,      2048 },
+	{ 0x66, LVL_1_DATA, 8 },
+	{ 0x67, LVL_1_DATA, 16 },
+	{ 0x68, LVL_1_DATA, 32 },
+	{ 0x70, LVL_TRACE,  12 },
+	{ 0x71, LVL_TRACE,  16 },
+	{ 0x72, LVL_TRACE,  32 },
+	{ 0x79, LVL_2,      128 },
+	{ 0x7A, LVL_2,      256 },
+	{ 0x7B, LVL_2,      512 },
+	{ 0x7C, LVL_2,      1024 },
+	{ 0x82, LVL_2,      256 },
+	{ 0x83, LVL_2,      512 },
+	{ 0x84, LVL_2,      1024 },
+	{ 0x85, LVL_2,      2048 },
+	{ 0x00, 0, 0}
+};
+
+int select_idle_routine(struct cpuinfo_x86 *c);
+
+static void __init init_intel(struct cpuinfo_x86 *c)
+{
+	unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
+	char *p = NULL;
+	u32 eax, dummy;
+
+	unsigned int n;
+
+
+	select_idle_routine(c);
+	if (c->cpuid_level > 1) {
+		/* supports eax=2  call */
+		int i, j, n;
+		int regs[4];
+		unsigned char *dp = (unsigned char *)regs;
+
+		/* Number of times to iterate */
+		n = cpuid_eax(2) & 0xFF;
+
+		for ( i = 0 ; i < n ; i++ ) {
+			cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
+			
+			/* If bit 31 is set, this is an unknown format */
+			for ( j = 0 ; j < 3 ; j++ ) {
+				if ( regs[j] < 0 ) regs[j] = 0;
+			}
+
+			/* Byte 0 is level count, not a descriptor */
+			for ( j = 1 ; j < 16 ; j++ ) {
+				unsigned char des = dp[j];
+				unsigned char k = 0;
+
+				/* look up this descriptor in the table */
+				while (cache_table[k].descriptor != 0)
+				{
+					if (cache_table[k].descriptor == des) {
+						switch (cache_table[k].cache_type) {
+						case LVL_1_INST:
+							l1i += cache_table[k].size;
+							break;
+						case LVL_1_DATA:
+							l1d += cache_table[k].size;
+							break;
+						case LVL_2:
+							l2 += cache_table[k].size;
+							break;
+						case LVL_3:
+							l3 += cache_table[k].size;
+							break;
+						case LVL_TRACE:
+							trace += cache_table[k].size;
+							break;
+						}
+						break;
+					}
+
+					k++;
+				}
+			}
+		}
+
+		if ( trace )
+			printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
+		else if ( l1i )
+			printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
+		if ( l1d )
+			printk(", L1 D cache: %dK\n", l1d);
+		else 
+			printk("\n");
+		if ( l2 )
+			printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
+		if ( l3 )
+			printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+
+		/*
+		 * This assumes the L3 cache is shared; it typically lives in
+		 * the northbridge.  The L1 caches are included by the L2
+		 * cache, and so should not be included for the purpose of
+		 * SMP switching weights.
+		 */
+		c->x86_cache_size = l2 ? l2 : (l1i+l1d);
+	}
+
+	if ( p )
+		strcpy(c->x86_model_id, p);
+	
+#ifdef CONFIG_SMP
+	if (test_bit(X86_FEATURE_HT, &c->x86_capability)) {		
+		int 	index_lsb, index_msb, tmp;
+		int	initial_apic_id;
+		int 	cpu = smp_processor_id();
+		u32 	ebx, ecx, edx;
+
+		cpuid(1, &eax, &ebx, &ecx, &edx);
+		smp_num_siblings = (ebx & 0xff0000) >> 16;
+
+		if (smp_num_siblings == 1) {
+			printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+		} else if (smp_num_siblings > 1 ) {
+			index_lsb = 0;
+			index_msb = 31;
+			/*
+			 * At this point we only support two siblings per
+			 * processor package.
+			 */
+#define NR_SIBLINGS	2
+			if (smp_num_siblings != NR_SIBLINGS) {
+				printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+				smp_num_siblings = 1;
+				return;
+			}
+			tmp = smp_num_siblings;
+			while ((tmp & 1) == 0) {
+				tmp >>=1 ;
+				index_lsb++;
+			}
+			tmp = smp_num_siblings;
+			while ((tmp & 0x80000000 ) == 0) {
+				tmp <<=1 ;
+				index_msb--;
+			}
+			if (index_lsb != index_msb )
+				index_msb++;
+			initial_apic_id = ebx >> 24 & 0xff;
+			phys_proc_id[cpu] = initial_apic_id >> index_msb;
+
+			printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+                               phys_proc_id[cpu]);
+		}
+
+	}
+#endif
+
+	n = cpuid_eax(0x80000000);
+	if (n >= 0x80000008) {
+		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy); 
+		c->x86_virt_bits = (eax >> 8) & 0xff;
+		c->x86_phys_bits = eax & 0xff;
+	}
+	
+}
+
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
 	int r;
@@ -433,6 +636,8 @@ void __init get_cpu_vendor(struct cpuinf
 
 	if (!strcmp(v, "AuthenticAMD"))
 		c->x86_vendor = X86_VENDOR_AMD;
+	else if (!strcmp(v, "GenuineIntel"))
+		c->x86_vendor = X86_VENDOR_INTEL;
 	else
 		c->x86_vendor = X86_VENDOR_UNKNOWN;
 }
@@ -448,7 +653,7 @@ struct cpu_model_info {
  */
 void __init identify_cpu(struct cpuinfo_x86 *c)
 {
-	int junk, i;
+	int i;
 	u32 xlvl, tfms;
 
 	c->loops_per_jiffy = loops_per_jiffy;
@@ -472,7 +677,7 @@ void __init identify_cpu(struct cpuinfo_
 	/* Intel-defined flags: level 0x00000001 */
 	if ( c->cpuid_level >= 0x00000001 ) {	
 		__u32 misc;
-		cpuid(0x00000001, &tfms, &misc, &junk,
+		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
 		      &c->x86_capability[0]);
 		c->x86 = (tfms >> 8) & 15;
 		c->x86_model = (tfms >> 4) & 15;
@@ -521,9 +726,12 @@ void __init identify_cpu(struct cpuinfo_
 			init_amd(c);
 			break;
 
+		case X86_VENDOR_INTEL:
+			init_intel(c);
+			break;
 		case X86_VENDOR_UNKNOWN:
 		default:
-			/* Not much we can do here... */
+			display_cacheinfo(c);
 			break;
 	}
 
@@ -581,7 +789,7 @@ static int show_cpuinfo(struct seq_file 
 	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
 	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
 	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-	        "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL,
+	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
 
 		/* AMD-defined */
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -600,6 +808,12 @@ static int show_cpuinfo(struct seq_file 
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+		/* Intel Defined (cpuid 1 and ecx) */
+		"pni", NULL, NULL, "monitor", "ds-cpl", NULL, NULL, "est",
+		"tm2", NULL, "cid", NULL, NULL, "cmpxchg16b", NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
 	static char *x86_power_flags[] = { 
 		"ts",	/* temperature sensor */
@@ -636,6 +850,11 @@ static int show_cpuinfo(struct seq_file 
 
 	seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
 	
+#ifdef CONFIG_SMP
+	seq_printf(m, "physical id\t: %d\n",phys_proc_id[c - cpu_data]);
+	seq_printf(m, "siblings\t: %d\n",smp_num_siblings);
+#endif
+
 	seq_printf(m,
 	        "fpu\t\t: yes\n"
 	        "fpu_exception\t: yes\n"
@@ -660,6 +879,7 @@ static int show_cpuinfo(struct seq_file 
 		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
 	seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
 
+	if (c->x86_phys_bits > 0) 
 	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 
 		   c->x86_phys_bits, c->x86_virt_bits);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/setup64.c linux-2.4.26-pre6/arch/x86_64/kernel/setup64.c
--- linux-2.4.25/arch/x86_64/kernel/setup64.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/setup64.c	2004-03-25 00:22:07.000000000 +0000
@@ -3,7 +3,7 @@
  * Copyright (C) 1995  Linus Torvalds
  * Copyright 2001, 2002 SuSE Labs / Andi Kleen.
  * See setup.c for older changelog.
- * $Id: setup64.c,v 1.26 2003/10/15 01:32:42 ak Exp $
+ * $Id: setup64.c,v 1.27 2004/02/27 18:30:19 ak Exp $
  */ 
 #include <linux/config.h>
 #include <linux/init.h>
@@ -160,6 +160,17 @@ void syscall_init(void)
 
 char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ];
 
+void check_efer(void)
+{
+	unsigned long efer;
+	rdmsrl(MSR_EFER, efer); 
+	if (!(efer & EFER_NX) || do_not_nx) { 
+		__supported_pte_mask &= ~_PAGE_NX; 
+	} else { 
+		__supported_pte_mask |= _PAGE_NX; 
+	} 
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -175,7 +186,7 @@ void __init cpu_init (void)
 	int nr = smp_processor_id();
 #endif
 	struct tss_struct * t = &init_tss[nr];
-	unsigned long v, efer; 	
+	unsigned long v; 	
 	unsigned long estack;
 
 	/* CPU 0 is initialised in head64.c */
@@ -202,12 +213,7 @@ void __init cpu_init (void)
 
 	syscall_init();
 
-		rdmsrl(MSR_EFER, efer); 
-	if (!(efer & EFER_NX) || do_not_nx) { 
-			__supported_pte_mask &= ~_PAGE_NX; 
-	} else { 
-		__supported_pte_mask |= _PAGE_NX; 
-		} 
+	check_efer();
 
 	t->io_map_base = INVALID_IO_BITMAP_OFFSET;	
 	memset(t->io_bitmap, 0xff, sizeof(t->io_bitmap));
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/smpboot.c linux-2.4.26-pre6/arch/x86_64/kernel/smpboot.c
--- linux-2.4.25/arch/x86_64/kernel/smpboot.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/smpboot.c	2004-03-25 00:21:27.000000000 +0000
@@ -53,13 +53,18 @@
 #include <asm/acpi.h>
 
 /* Setup configured maximum number of CPUs to activate */
-static int max_cpus = -1;
+unsigned int max_cpus = NR_CPUS;
 
 static int cpu_mask = -1; 
 
 /* Total count of live CPUs */
 int smp_num_cpus = 1;
 
+/* Number of siblings per CPU package */
+int smp_num_siblings = 1;
+int __initdata phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+int cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+
 /* Bitmask of currently online CPUs */
 unsigned long cpu_online_map;
 
@@ -84,10 +89,6 @@ extern void time_init_smp(void);
  *
  * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
  * activation entirely (the MPS table probe still happens, though).
- *
- * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- * greater than 0, limits the maximum number of CPUs activated in
- * SMP mode to <NUM>.
  */
 
 static int __init nosmp(char *str)
@@ -98,15 +99,6 @@ static int __init nosmp(char *str)
 
 __setup("nosmp", nosmp);
 
-static int __init maxcpus(char *str)
-{
-	get_option(&str, &max_cpus);
-	return 1;
-}
-
-__setup("maxcpus=", maxcpus);
-
-
 static int __init cpumask(char *str)
 {
 	get_option(&str, &cpu_mask);
@@ -936,8 +928,6 @@ void __init smp_boot_cpus(void)
 			continue;
 		if (((1<<apicid) & cpu_mask) == 0) 
 			continue;
-		if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
-			continue;
 
 		cpu = do_boot_cpu(apicid);
 
@@ -992,6 +982,34 @@ void __init smp_boot_cpus(void)
 	Dprintk("Boot done.\n");
 
 	/*
+	 * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so
+	 * that we can tell the sibling CPU efficiently.
+	 */
+	if (test_bit(X86_FEATURE_HT, boot_cpu_data.x86_capability)
+	    && smp_num_siblings > 1) {
+		for (cpu = 0; cpu < NR_CPUS; cpu++)
+			cpu_sibling_map[cpu] = NO_PROC_ID;
+		
+		for (cpu = 0; cpu < smp_num_cpus; cpu++) {
+			int 	i;
+			
+			for (i = 0; i < smp_num_cpus; i++) {
+				if (i == cpu)
+					continue;
+				if (phys_proc_id[cpu] == phys_proc_id[i]) {
+					cpu_sibling_map[cpu] = i;
+					printk("cpu_sibling_map[%d] = %d\n", cpu, cpu_sibling_map[cpu]);
+					break;
+				}
+			}
+			if (cpu_sibling_map[cpu] == NO_PROC_ID) {
+				smp_num_siblings = 1;
+				printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu);
+			}
+		}
+	}
+	     
+	/*
 	 * Here we can be sure that there is an IO-APIC in the system. Let's
 	 * go and set it up:
 	 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/swiotlb.c linux-2.4.26-pre6/arch/x86_64/kernel/swiotlb.c
--- linux-2.4.25/arch/x86_64/kernel/swiotlb.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/swiotlb.c	2004-03-25 00:19:32.000000000 +0000
@@ -0,0 +1 @@
+#include "../../ia64/lib/swiotlb.c"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/traps.c linux-2.4.26-pre6/arch/x86_64/kernel/traps.c
--- linux-2.4.25/arch/x86_64/kernel/traps.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/traps.c	2004-03-25 00:20:57.000000000 +0000
@@ -7,7 +7,7 @@
  *  Pentium III FXSR, SSE support
  *	Gareth Hughes <gareth@valinux.com>, May 2000
  *
- *  $Id: traps.c,v 1.69 2003/09/21 04:54:09 ak Exp $
+ *  $Id: traps.c,v 1.71 2004/02/27 22:07:36 ak Exp $
  */
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/x8664_ksyms.c linux-2.4.26-pre6/arch/x86_64/kernel/x8664_ksyms.c
--- linux-2.4.25/arch/x86_64/kernel/x8664_ksyms.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/kernel/x8664_ksyms.c	2004-03-25 00:20:36.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/string.h>
 #include <linux/nmi.h>
 
+#include <asm/ioctl32.h>
 #include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -53,6 +54,7 @@ EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(pm_idle);
 EXPORT_SYMBOL(pm_power_off);
+EXPORT_SYMBOL(sys_ioctl);
 
 #ifdef CONFIG_IO_DEBUG
 EXPORT_SYMBOL(__io_virt_debug);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/lib/copy_page.S linux-2.4.26-pre6/arch/x86_64/lib/copy_page.S
--- linux-2.4.25/arch/x86_64/lib/copy_page.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/lib/copy_page.S	2004-03-25 00:16:50.000000000 +0000
@@ -1,5 +1,7 @@
 /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
 	
+#include <linux/config.h>
+
 /* Don't use streaming store because it's better when the target
    ends up in cache. */
 	    
@@ -8,10 +10,13 @@
 	.globl copy_page
 	.p2align 4
 copy_page:
-	prefetch (%rsi) 
-	prefetch 1*64(%rsi)
+
+    prefetcht0 (%rsi) 
+    prefetcht0 1*64(%rsi)
+#ifdef CONFIG_MK8	
 	prefetchw (%rdi) 
 	prefetchw 1*64(%rdi) 
+#endif	
 
 	subq	$3*8,%rsp
 	movq	%rbx,(%rsp)
@@ -32,7 +37,7 @@ copy_page:
 	movq     48 (%rsi), %r11
 	movq     56 (%rsi), %r12
 
-	prefetch 5*64(%rsi)
+	prefetcht0 5*64(%rsi)
 
 	movq     %rax,    (%rdi)
 	movq     %rbx,  8 (%rdi)
@@ -43,7 +48,9 @@ copy_page:
 	movq     %r11, 48 (%rdi)
 	movq     %r12, 56 (%rdi)
 
+#ifdef CONFIG_MK8
 	prefetchw 5*64(%rdi)
+#endif	
 
 	leaq    64 (%rsi), %rsi
 	leaq    64 (%rdi), %rdi
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/lib/copy_user.S linux-2.4.26-pre6/arch/x86_64/lib/copy_user.S
--- linux-2.4.25/arch/x86_64/lib/copy_user.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/lib/copy_user.S	2004-03-25 00:19:19.000000000 +0000
@@ -4,6 +4,8 @@
  * Functions to copy from and to user space.		
  */		 
 
+	#include <linux/config.h>
+	
 /* #define FIX_ALIGNMENT 1 */
 
 	#include <asm/current.h>
@@ -59,8 +61,10 @@ bad_to_user:
 	.globl copy_user_generic	
 	.p2align 4
 copy_user_generic:	
-	prefetch (%rsi)
+	prefetcht0 (%rsi)
+#ifdef CONFIG_MK8
 	prefetchw (%rdi)
+#endif
 	pushq %rbx
 	xorl %eax,%eax		/*zero for the exception handler */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/lib/csum-copy.S linux-2.4.26-pre6/arch/x86_64/lib/csum-copy.S
--- linux-2.4.25/arch/x86_64/lib/csum-copy.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/lib/csum-copy.S	2004-03-25 00:21:13.000000000 +0000
@@ -44,32 +44,9 @@
 	.previous
 	.endm
 			
-	.macro ignore L=.Lignore
-30:
-	.section __ex_table,"a"
-	.align 8
-	.quad 30b,\L
-	.previous
-	.endm
-	
-				
 	.globl csum_partial_copy_generic
 	.p2align 4
 csum_partial_copy_generic:
-	cmpl	 $2*64,%edx
-	jle	 .Lignore
-
-	ignore
-	prefetch 1*64(%rdi)
-	ignore
-	prefetch 2*64(%rdi)
-	ignore
-	prefetchw (%rsi)
-	ignore
-	prefetchw 1*64(%rsi)
-	ignore
-
-.Lignore:		
 	subq  $7*8,%rsp
 	movq  %rbx,2*8(%rsp)
 	movq  %r12,3*8(%rsp)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/lib/csum-partial.c linux-2.4.26-pre6/arch/x86_64/lib/csum-partial.c
--- linux-2.4.25/arch/x86_64/lib/csum-partial.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/lib/csum-partial.c	2004-03-25 00:21:57.000000000 +0000
@@ -136,11 +136,10 @@ unsigned csum_partial(const unsigned cha
 }
 
 /*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
+ * this routine is used for miscellaneous IP-like checksums.
  */
 unsigned short ip_compute_csum(unsigned char * buff, int len)
 {
-	return ~csum_partial(buff,len,0); 
+	return csum_fold(csum_partial(buff,len,0)); 
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/lib/usercopy.c linux-2.4.26-pre6/arch/x86_64/lib/usercopy.c
--- linux-2.4.25/arch/x86_64/lib/usercopy.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/lib/usercopy.c	2004-03-25 00:20:18.000000000 +0000
@@ -126,3 +126,11 @@ long strnlen_user(const char *s, long n)
 		s++;
 	}
 }
+
+unsigned long copy_in_user(void *to, const void *from, unsigned len)
+{
+	if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 
+		return copy_user_generic(to, from, len);
+	} 
+	return len;		
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/mm/fault.c linux-2.4.26-pre6/arch/x86_64/mm/fault.c
--- linux-2.4.25/arch/x86_64/mm/fault.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/mm/fault.c	2004-03-25 00:22:23.000000000 +0000
@@ -327,7 +327,8 @@ bad_area_nosemaphore:
 					regs->rsp, error_code);
 	
 		tsk->thread.cr2 = address;
-		tsk->thread.error_code = error_code;
+		/* Kernel addresses are always protection faults */
+		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
 		tsk->thread.trap_no = 14;
 		info.si_signo = SIGSEGV;
 		info.si_errno = 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/mm/pageattr.c linux-2.4.26-pre6/arch/x86_64/mm/pageattr.c
--- linux-2.4.25/arch/x86_64/mm/pageattr.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.26-pre6/arch/x86_64/mm/pageattr.c	2004-03-25 00:18:07.000000000 +0000
@@ -52,7 +52,7 @@ static void flush_kernel_map(void * addr
 		/* is this worth it? */ 
 		int i;
 		for (i = 0; i < PAGE_SIZE; i += cpu->x86_clflush_size) 
-			asm volatile("clflush %0" :: "m" (address + i)); 
+			asm volatile("clflush (%0)" :: "r" (address + i)); 
 	} else
 		asm volatile("wbinvd":::"memory"); 
 	__flush_tlb_one(address);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/Config.in linux-2.4.26-pre6/crypto/Config.in
--- linux-2.4.25/crypto/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/crypto/Config.in	2004-03-25 00:21:53.000000000 +0000
@@ -72,6 +72,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then
   tristate       '  AES cipher algorithms' CONFIG_CRYPTO_AES
   tristate       '  CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5
   tristate       '  CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6
+  tristate       '  ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4
   if [ "$CONFIG_INET_IPCOMP" = "y" -o \
        "$CONFIG_INET_IPCOMP" = "m" -o \
        "$CONFIG_INET6_IPCOMP" = "y" -o \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/Makefile linux-2.4.26-pre6/crypto/Makefile
--- linux-2.4.25/crypto/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/crypto/Makefile	2004-03-25 00:18:28.000000000 +0000
@@ -9,7 +9,7 @@ export-objs := api.o hmac.o
 autoload-crypto-$(CONFIG_KMOD) = autoload.o
 proc-crypto-$(CONFIG_PROC_FS) = proc.o
 
-obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \
+obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
 			$(autoload-crypto-y) $(proc-crypto-y)
 
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
@@ -26,6 +26,7 @@ obj-$(CONFIG_CRYPTO_SERPENT) += serpent.
 obj-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
+obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/arc4.c linux-2.4.26-pre6/crypto/arc4.c
--- linux-2.4.25/crypto/arc4.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/crypto/arc4.c	2004-03-25 00:20:02.000000000 +0000
@@ -0,0 +1,107 @@
+/* 
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <jon@focalhost.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+
+#define ARC4_MIN_KEY_SIZE	1
+#define ARC4_MAX_KEY_SIZE	256
+#define ARC4_BLOCK_SIZE		1
+
+struct arc4_ctx {
+	u8 S[256];
+	u8 x, y;
+};
+
+static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+	int i, j = 0, k = 0;
+
+	ctx->x = 1;
+	ctx->y = 0;
+
+	for(i = 0; i < 256; i++)
+		ctx->S[i] = i;
+
+	for(i = 0; i < 256; i++)
+	{
+		u8 a = ctx->S[i];
+		j = (j + in_key[k] + a) & 0xff;
+		ctx->S[i] = ctx->S[j];
+		ctx->S[j] = a;
+		if(++k >= key_len)
+			k = 0;
+	}
+
+	/* TODO: dump the first 768 bytes generated as recommended
+	   by Ilya Mironov (http://eprint.iacr.org/2002/067/) to 
+	   increase the statistical strength of the state table */
+
+	return 0;
+}
+
+static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+
+	u8 *const S = ctx->S;
+	u8 x = ctx->x;
+	u8 y = ctx->y;
+	u8 a, b;
+
+	a = S[x];
+	y = (y + a) & 0xff;
+	b = S[y];
+	S[x] = b;
+	S[y] = a;
+	x = (x + 1) & 0xff;
+	*out++ = *in ^ S[(a + b) & 0xff];
+
+	ctx->x = x;
+	ctx->y = y;
+}
+
+static struct crypto_alg arc4_alg = {
+	.cra_name		=	"arc4",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	ARC4_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct arc4_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
+	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
+	.cia_setkey	   	= 	arc4_set_key,
+	.cia_encrypt	 	=	arc4_crypt,
+	.cia_decrypt	  	=	arc4_crypt } }
+};
+
+static int __init arc4_init(void)
+{
+	return crypto_register_alg(&arc4_alg);
+}
+
+
+static void __exit arc4_exit(void)
+{
+	crypto_unregister_alg(&arc4_alg);
+}
+
+module_init(arc4_init);
+module_exit(arc4_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
+MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/cipher.c linux-2.4.26-pre6/crypto/cipher.c
--- linux-2.4.25/crypto/cipher.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/crypto/cipher.c	2004-03-25 00:20:48.000000000 +0000
@@ -4,7 +4,6 @@
  * Cipher operations.
  *
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -17,30 +16,13 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
 #include <asm/scatterlist.h>
 #include "internal.h"
+#include "scatterwalk.h"
 
 typedef void (cryptfn_t)(void *, u8 *, const u8 *);
 typedef void (procfn_t)(struct crypto_tfm *, u8 *,
-                        u8*, cryptfn_t, int enc, void *);
-
-struct scatter_walk {
-	struct scatterlist	*sg;
-	struct page		*page;
-	void			*data;
-	unsigned int		len_this_page;
-	unsigned int		len_this_segment;
-	unsigned int		offset;
-};
-
-enum km_type crypto_km_types[] = {
-	KM_USER0,
-	KM_USER1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-};
+                        u8*, cryptfn_t, int enc, void *, int);
 
 static inline void xor_64(u8 *a, const u8 *b)
 {
@@ -57,108 +39,6 @@ static inline void xor_128(u8 *a, const 
 }
 
 
-/* Define sg_next is an inline routine now in case we want to change
-   scatterlist to a linked list later. */
-static inline struct scatterlist *sg_next(struct scatterlist *sg)
-{
-	return sg + 1;
-}
-
-void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
-{
-	if (nbytes <= walk->len_this_page &&
-	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
-	    PAGE_CACHE_SIZE)
-		return walk->data;
-	else
-		return scratch;
-}
-
-static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
-{
-	if (out)
-		memcpy(sgdata, buf, nbytes);
-	else
-		memcpy(buf, sgdata, nbytes);
-}
-
-static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
-{
-	unsigned int rest_of_page;
-
-	walk->sg = sg;
-
-	walk->page = sg->page;
-	walk->len_this_segment = sg->length;
-
-	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
-	walk->len_this_page = min(sg->length, rest_of_page);
-	walk->offset = sg->offset;
-}
-
-static void scatterwalk_map(struct scatter_walk *walk, int out)
-{
-	walk->data = crypto_kmap(walk->page, out) + walk->offset;
-}
-
-static void scatter_page_done(struct scatter_walk *walk, int out,
-			      unsigned int more)
-{
-	/* walk->data may be pointing the first byte of the next page;
-	   however, we know we transfered at least one byte.  So,
-	   walk->data - 1 will be a virutual address in the mapped page. */
-
-	if (out)
-		flush_dcache_page(walk->page);
-
-	if (more) {
-		walk->len_this_segment -= walk->len_this_page;
-
-		if (walk->len_this_segment) {
-			walk->page++;
-			walk->len_this_page = min(walk->len_this_segment,
-						  (unsigned)PAGE_CACHE_SIZE);
-			walk->offset = 0;
-		}
-		else
-			scatterwalk_start(walk, sg_next(walk->sg));
-	}
-}
-
-static void scatter_done(struct scatter_walk *walk, int out, int more)
-{
-	crypto_kunmap(walk->data, out);
-	if (walk->len_this_page == 0 || !more)
-		scatter_page_done(walk, out, more);
-}
-
-/*
- * Do not call this unless the total length of all of the fragments 
- * has been verified as multiple of the block size.
- */
-static int copy_chunks(void *buf, struct scatter_walk *walk,
-			size_t nbytes, int out)
-{
-	if (buf != walk->data) {
-		while (nbytes > walk->len_this_page) {
-			memcpy_dir(buf, walk->data, walk->len_this_page, out);
-			buf += walk->len_this_page;
-			nbytes -= walk->len_this_page;
-
-			crypto_kunmap(walk->data, out);
-			scatter_page_done(walk, out, 1);
-			scatterwalk_map(walk, out);
-		}
-
-		memcpy_dir(buf, walk->data, nbytes, out);
-	}
-
-	walk->offset += nbytes;
-	walk->len_this_page -= nbytes;
-	walk->len_this_segment -= nbytes;
-	return 0;
-}
-
 /* 
  * Generic encrypt/decrypt wrapper for ciphers, handles operations across
  * multiple page boundaries by using temporary blocks.  In user context,
@@ -191,19 +71,21 @@ static int crypt(struct crypto_tfm *tfm,
 
 		scatterwalk_map(&walk_in, 0);
 		scatterwalk_map(&walk_out, 1);
-		src_p = which_buf(&walk_in, bsize, tmp_src);
-		dst_p = which_buf(&walk_out, bsize, tmp_dst);
+		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
+		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
 
 		nbytes -= bsize;
 
-		copy_chunks(src_p, &walk_in, bsize, 0);
+		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
 
-		prfn(tfm, dst_p, src_p, crfn, enc, info);
+		prfn(tfm, dst_p, src_p, crfn, enc, info,
+		     scatterwalk_samebuf(&walk_in, &walk_out,
+					 src_p, dst_p));
 
-		scatter_done(&walk_in, 0, nbytes);
+		scatterwalk_done(&walk_in, 0, nbytes);
 
-		copy_chunks(dst_p, &walk_out, bsize, 1);
-		scatter_done(&walk_out, 1, nbytes);
+		scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
+		scatterwalk_done(&walk_out, 1, nbytes);
 
 		if (!nbytes)
 			return 0;
@@ -212,8 +94,8 @@ static int crypt(struct crypto_tfm *tfm,
 	}
 }
 
-static void cbc_process(struct crypto_tfm *tfm,
-                        u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info)
+static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t fn, int enc, void *info, int in_place)
 {
 	u8 *iv = info;
 	
@@ -226,10 +108,9 @@ static void cbc_process(struct crypto_tf
 		fn(crypto_tfm_ctx(tfm), dst, iv);
 		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
 	} else {
-		const int need_stack = (src == dst);
-		u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
-		u8 *buf = need_stack ? stack : dst;
-		
+		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
+		u8 *buf = in_place ? stack : dst;
+
 		fn(crypto_tfm_ctx(tfm), buf, src);
 		tfm->crt_u.cipher.cit_xor_block(buf, iv);
 		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
@@ -239,7 +120,7 @@ static void cbc_process(struct crypto_tf
 }
 
 static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-                        cryptfn_t fn, int enc, void *info)
+			cryptfn_t fn, int enc, void *info, int in_place)
 {
 	fn(crypto_tfm_ctx(tfm), dst, src);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/internal.h linux-2.4.26-pre6/crypto/internal.h
--- linux-2.4.25/crypto/internal.h	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-pre6/crypto/internal.h	2004-03-25 00:20:00.000000000 +0000
@@ -11,6 +11,7 @@
  */
 #ifndef _CRYPTO_INTERNAL_H
 #define _CRYPTO_INTERNAL_H
+#include <linux/crypto.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/scatterwalk.c linux-2.4.26-pre6/crypto/scatterwalk.c
--- linux-2.4.25/crypto/scatterwalk.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/crypto/scatterwalk.c	2004-03-25 00:16:53.000000000 +0000
@@ -0,0 +1,124 @@
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *               2002 Adam J. Richter <adam@yggdrasil.com>
+ *               2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <asm/scatterlist.h>
+#include "internal.h"
+#include "scatterwalk.h"
+
+enum km_type crypto_km_types[] = {
+	KM_USER0,
+	KM_USER1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+};
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
+{
+	if (nbytes <= walk->len_this_page &&
+	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
+	    PAGE_CACHE_SIZE)
+		return walk->data;
+	else
+		return scratch;
+}
+
+static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
+{
+	if (out)
+		memcpy(sgdata, buf, nbytes);
+	else
+		memcpy(buf, sgdata, nbytes);
+}
+
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
+{
+	unsigned int rest_of_page;
+
+	walk->sg = sg;
+
+	walk->page = sg->page;
+	walk->len_this_segment = sg->length;
+
+	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
+	walk->len_this_page = min(sg->length, rest_of_page);
+	walk->offset = sg->offset;
+}
+
+void scatterwalk_map(struct scatter_walk *walk, int out)
+{
+	walk->data = crypto_kmap(walk->page, out) + walk->offset;
+}
+
+static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+				 unsigned int more)
+{
+	/* walk->data may be pointing the first byte of the next page;
+	   however, we know we transfered at least one byte.  So,
+	   walk->data - 1 will be a virutual address in the mapped page. */
+
+	if (out)
+		flush_dcache_page(walk->page);
+
+	if (more) {
+		walk->len_this_segment -= walk->len_this_page;
+
+		if (walk->len_this_segment) {
+			walk->page++;
+			walk->len_this_page = min(walk->len_this_segment,
+						  (unsigned)PAGE_CACHE_SIZE);
+			walk->offset = 0;
+		}
+		else
+			scatterwalk_start(walk, sg_next(walk->sg));
+	}
+}
+
+void scatterwalk_done(struct scatter_walk *walk, int out, int more)
+{
+	crypto_kunmap(walk->data, out);
+	if (walk->len_this_page == 0 || !more)
+		scatterwalk_pagedone(walk, out, more);
+}
+
+/*
+ * Do not call this unless the total length of all of the fragments
+ * has been verified as multiple of the block size.
+ */
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+			   size_t nbytes, int out)
+{
+	if (buf != walk->data) {
+		while (nbytes > walk->len_this_page) {
+			memcpy_dir(buf, walk->data, walk->len_this_page, out);
+			buf += walk->len_this_page;
+			nbytes -= walk->len_this_page;
+
+			crypto_kunmap(walk->data, out);
+			scatterwalk_pagedone(walk, out, 1);
+			scatterwalk_map(walk, out);
+		}
+
+		memcpy_dir(buf, walk->data, nbytes, out);
+	}
+
+	walk->offset += nbytes;
+	walk->len_this_page -= nbytes;
+	walk->len_this_segment -= nbytes;
+	return 0;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/scatterwalk.h linux-2.4.26-pre6/crypto/scatterwalk.h
--- linux-2.4.25/crypto/scatterwalk.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/crypto/scatterwalk.h	2004-03-25 00:19:43.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
+ * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_SCATTERWALK_H
+#define _CRYPTO_SCATTERWALK_H
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+struct scatter_walk {
+	struct scatterlist	*sg;
+	struct page		*page;
+	void			*data;
+	unsigned int		len_this_page;
+	unsigned int		len_this_segment;
+	unsigned int		offset;
+};
+
+/* Define sg_next is an inline routine now in case we want to change
+   scatterlist to a linked list later. */
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+	return sg + 1;
+}
+
+static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
+				      struct scatter_walk *walk_out,
+				      void *src_p, void *dst_p)
+{
+	return walk_in->page == walk_out->page &&
+	       walk_in->data == src_p && walk_out->data == dst_p;
+}
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
+void scatterwalk_map(struct scatter_walk *walk, int out);
+void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+
+#endif  /* _CRYPTO_SCATTERWALK_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/tcrypt.c linux-2.4.26-pre6/crypto/tcrypt.c
--- linux-2.4.25/crypto/tcrypt.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/crypto/tcrypt.c	2004-03-25 00:20:41.000000000 +0000
@@ -63,7 +63,7 @@ static char *tvmem;
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"deflate", NULL
+	"arc4", "deflate", NULL
 };
 
 static void
@@ -558,6 +558,10 @@ do_test(void)
 		test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 
+		//ARC4
+		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
+		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_deflate();		
@@ -640,6 +644,11 @@ do_test(void)
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 		break;
 
+	case 16:
+		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
+		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+		break;
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/crypto/tcrypt.h linux-2.4.26-pre6/crypto/tcrypt.h
--- linux-2.4.25/crypto/tcrypt.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/crypto/tcrypt.h	2004-03-25 00:22:13.000000000 +0000
@@ -1488,6 +1488,147 @@ struct cipher_testvec cast5_dec_tv_templ
 	},
 };
 
+/* 
+ * ARC4 test vectors from OpenSSL 
+ */
+#define ARC4_ENC_TEST_VECTORS	7
+#define ARC4_DEC_TEST_VECTORS	7
+
+struct cipher_testvec arc4_enc_tv_template[] =
+{
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45},
+		.klen	= 4,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 20,
+		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+			    0x36, 0xb6, 0x78, 0x58 },
+		.rlen	= 20,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78 },
+		.ilen	= 28,
+		.result	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+			    0x40, 0x01, 0x1e, 0xcf },
+		.rlen	= 28,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45 },
+		.klen	= 4,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00 },
+		.ilen	= 10,
+		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61 },
+		.rlen	= 10,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+		.ilen	= 8,
+		.result	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
+		.rlen	= 8,
+	},
+};
+
+struct cipher_testvec arc4_dec_tv_template[] =
+{
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45},
+		.klen	= 4,
+		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+			    0x36, 0xb6, 0x78, 0x58 },
+		.ilen	= 20,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 20,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+			    0x40, 0x01, 0x1e, 0xcf },
+		.ilen	= 28,
+		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78 },
+		.rlen	= 28,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45 },
+		.klen	= 4,
+		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61 },
+		.ilen	= 10,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00 },
+		.rlen	= 10,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+		.rlen	= 8,
+	},
+};
+
+
 /*
  * Compression stuff.
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/Config.in linux-2.4.26-pre6/drivers/acpi/Config.in
--- linux-2.4.25/drivers/acpi/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/Config.in	2004-03-25 00:21:46.000000000 +0000
@@ -25,9 +25,6 @@ if [ "$CONFIG_X86" = "y" ]; then
     tristate     '  Fan'		CONFIG_ACPI_FAN
     tristate     '  Processor'	CONFIG_ACPI_PROCESSOR
     dep_tristate '  Thermal Zone' 	CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR
-    if [ "$CONFIG_NUMA" = "y" -a "$CONFIG_X86_64" != "y" ]; then
-      dep_bool       '  NUMA support'     CONFIG_ACPI_NUMA $CONFIG_NUMA
-    fi
     tristate     '  ASUS Laptop Extras'  CONFIG_ACPI_ASUS
     tristate     '  Toshiba Laptop Extras'	CONFIG_ACPI_TOSHIBA
     bool         '  Debug Statements'	CONFIG_ACPI_DEBUG
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/bus.c linux-2.4.26-pre6/drivers/acpi/bus.c
--- linux-2.4.25/drivers/acpi/bus.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/bus.c	2004-03-25 00:20:16.000000000 +0000
@@ -49,9 +49,7 @@ MODULE_LICENSE("GPL");
 
 #define	PREFIX			"ACPI: "
 
-extern void __init acpi_pic_sci_set_trigger(unsigned int irq);
-
-extern int			acpi_disabled;
+extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
 
 FADT_DESCRIPTOR			acpi_fadt;
 struct acpi_device		*acpi_root;
@@ -1877,11 +1875,18 @@ acpi_bus_init (void)
 	}
 
 #ifdef CONFIG_X86
-        /* Ensure the SCI is set to level-triggered, active-low */
-        if (acpi_ioapic)
-         	mp_config_ioapic_for_sci(acpi_fadt.sci_int);
-	else
-		acpi_pic_sci_set_trigger(acpi_fadt.sci_int);
+	if (!acpi_ioapic) {
+		extern acpi_interrupt_flags acpi_sci_flags;
+		/* Set PIC-mode SCI trigger type */
+		acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
+	} else {
+		extern int acpi_sci_override_gsi;
+		/*
+		 * now that acpi_fadt is initialized,
+		 * update it with result from INT_SRC_OVR parsing
+		 */
+		acpi_fadt.sci_int = acpi_sci_override_gsi;
+	}
 #endif
 
 	status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
@@ -2048,7 +2053,7 @@ acpi_init (void)
 
 	result = acpi_bus_init();
 	if (result) {
-		acpi_disabled = 1;
+		disable_acpi();
 		return_VALUE(result);
 	}
 
@@ -2074,19 +2079,3 @@ acpi_exit (void)
 	return_VOID;
 }
 
-
-int __init
-acpi_setup(char *str)
-{
-	while (str && *str) {
-		if (strncmp(str, "off", 3) == 0)
-			acpi_disabled = 1;
-		str = strchr(str, ',');
-		if (str)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-
-__setup("acpi=", acpi_setup);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsmethod.c linux-2.4.26-pre6/drivers/acpi/dispatcher/dsmethod.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsmethod.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/dispatcher/dsmethod.c	2004-03-25 00:19:54.000000000 +0000
@@ -106,7 +106,7 @@ acpi_ds_parse_method (
 
 	/* Create a mutex for the method if there is a concurrency limit */
 
-	if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) &&
+	if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
 		(!obj_desc->method.semaphore)) {
 		status = acpi_os_create_semaphore (obj_desc->method.concurrency,
 				   obj_desc->method.concurrency,
@@ -300,34 +300,37 @@ acpi_ds_call_control_method (
 		return_ACPI_STATUS (status);
 	}
 
-	/* 1) Parse: Create a new walk state for the preempting walk */
+	if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
+		/* 1) Parse: Create a new walk state for the preempting walk */
 
-	next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
-			  op, obj_desc, NULL);
-	if (!next_walk_state) {
-		return_ACPI_STATUS (AE_NO_MEMORY);
-	}
+		next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
+				  op, obj_desc, NULL);
+		if (!next_walk_state) {
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
 
-	/* Create and init a Root Node */
 
-	op = acpi_ps_create_scope_op ();
-	if (!op) {
-		status = AE_NO_MEMORY;
-		goto cleanup;
-	}
+		/* Create and init a Root Node */
 
-	status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
-			  obj_desc->method.aml_start, obj_desc->method.aml_length,
-			  NULL, NULL, 1);
-	if (ACPI_FAILURE (status)) {
-		acpi_ds_delete_walk_state (next_walk_state);
-		goto cleanup;
-	}
+		op = acpi_ps_create_scope_op ();
+		if (!op) {
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
+				  obj_desc->method.aml_start, obj_desc->method.aml_length,
+				  NULL, NULL, 1);
+		if (ACPI_FAILURE (status)) {
+			acpi_ds_delete_walk_state (next_walk_state);
+			goto cleanup;
+		}
 
-	/* Begin AML parse */
+		/* Begin AML parse */
 
-	status = acpi_ps_parse_aml (next_walk_state);
-	acpi_ps_delete_parse_tree (op);
+		status = acpi_ps_parse_aml (next_walk_state);
+		acpi_ps_delete_parse_tree (op);
+	}
 
 	/* 2) Execute: Create a new state for the preempting walk */
 
@@ -337,7 +340,6 @@ acpi_ds_call_control_method (
 		status = AE_NO_MEMORY;
 		goto cleanup;
 	}
-
 	/*
 	 * The resolved arguments were put on the previous walk state's operand
 	 * stack.  Operands on the previous walk state stack always
@@ -369,16 +371,25 @@ acpi_ds_call_control_method (
 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 		"Starting nested execution, newstate=%p\n", next_walk_state));
 
+	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
+		status = obj_desc->method.implementation (next_walk_state);
+		return_ACPI_STATUS (status);
+	}
+
 	return_ACPI_STATUS (AE_OK);
 
 
 	/* On error, we must delete the new walk state */
 
 cleanup:
+	if (next_walk_state->method_desc) {
+		/* Decrement the thread count on the method parse tree */
+
+	   next_walk_state->method_desc->method.thread_count--;
+	}
 	(void) acpi_ds_terminate_control_method (next_walk_state);
 	acpi_ds_delete_walk_state (next_walk_state);
 	return_ACPI_STATUS (status);
-
 }
 
 
@@ -500,11 +511,31 @@ acpi_ds_terminate_control_method (
 		}
 	}
 
-	/* Decrement the thread count on the method parse tree */
+	if (walk_state->method_desc->method.thread_count) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+			"*** Not deleting method namespace, there are still %d threads\n",
+			walk_state->method_desc->method.thread_count));
+	}
 
-	walk_state->method_desc->method.thread_count--;
 	if (!walk_state->method_desc->method.thread_count) {
 		/*
+		 * Support to dynamically change a method from not_serialized to
+		 * Serialized if it appears that the method is written foolishly and
+		 * does not support multiple thread execution.  The best example of this
+		 * is if such a method creates namespace objects and blocks.  A second
+		 * thread will fail with an AE_ALREADY_EXISTS exception
+		 *
+		 * This code is here because we must wait until the last thread exits
+		 * before creating the synchronization semaphore.
+		 */
+		if ((walk_state->method_desc->method.concurrency == 1) &&
+			(!walk_state->method_desc->method.semaphore)) {
+			status = acpi_os_create_semaphore (1,
+					 1,
+					 &walk_state->method_desc->method.semaphore);
+		}
+
+		/*
 		 * There are no more threads executing this method.  Perform
 		 * additional cleanup.
 		 *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsmthdat.c linux-2.4.26-pre6/drivers/acpi/dispatcher/dsmthdat.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsmthdat.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/dispatcher/dsmthdat.c	2004-03-25 00:19:04.000000000 +0000
@@ -206,8 +206,7 @@ acpi_ds_method_data_init_args (
 		 * Store the argument in the method/walk descriptor.
 		 * Do not copy the arg in order to implement call by reference
 		 */
-		status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index],
-				 walk_state);
+		status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], walk_state);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -465,6 +464,7 @@ acpi_ds_method_data_get_value (
 			return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
 
 		default:
+			ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
 	}
@@ -597,7 +597,10 @@ acpi_ds_store_object_to_local (
 
 	/*
 	 * If the reference count on the object is more than one, we must
-	 * take a copy of the object before we store.
+	 * take a copy of the object before we store.  A reference count
+	 * of exactly 1 means that the object was just created during the
+	 * evaluation of an expression, and we can safely use it since it
+	 * is not used anywhere else.
 	 */
 	new_obj_desc = obj_desc;
 	if (obj_desc->common.reference_count > 1) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsobject.c linux-2.4.26-pre6/drivers/acpi/dispatcher/dsobject.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsobject.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/dispatcher/dsobject.c	2004-03-25 00:17:08.000000000 +0000
@@ -582,6 +582,11 @@ acpi_ds_init_object_from_op (
 
 			obj_desc->reference.opcode = AML_ARG_OP;
 			obj_desc->reference.offset = opcode - AML_ARG_OP;
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+			status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
+					 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
+#endif
 			break;
 
 		default: /* Other literals, etc.. */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsopcode.c linux-2.4.26-pre6/drivers/acpi/dispatcher/dsopcode.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsopcode.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/dispatcher/dsopcode.c	2004-03-25 00:21:33.000000000 +0000
@@ -243,8 +243,8 @@ acpi_ds_get_buffer_arguments (
 
 	node = obj_desc->buffer.node;
 	if (!node) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-				"No pointer back to NS node in buffer %p\n", obj_desc));
+		ACPI_REPORT_ERROR ((
+				"No pointer back to NS node in buffer obj %p\n", obj_desc));
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
 
@@ -290,7 +290,7 @@ acpi_ds_get_package_arguments (
 
 	node = obj_desc->package.node;
 	if (!node) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+		ACPI_REPORT_ERROR ((
 				"No pointer back to NS node in package %p\n", obj_desc));
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsutils.c linux-2.4.26-pre6/drivers/acpi/dispatcher/dsutils.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsutils.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/dispatcher/dsutils.c	2004-03-25 00:19:44.000000000 +0000
@@ -280,7 +280,8 @@ acpi_ds_resolve_operands (
 
 	/*
 	 * Attempt to resolve each of the valid operands
-	 * Method arguments are passed by value, not by reference
+	 * Method arguments are passed by reference, not by value.  This means
+	 * that the actual objects are passed, not copies of the objects.
 	 */
 	for (i = 0; i < walk_state->num_operands; i++) {
 		status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dswstate.c linux-2.4.26-pre6/drivers/acpi/dispatcher/dswstate.c
--- linux-2.4.25/drivers/acpi/dispatcher/dswstate.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/dispatcher/dswstate.c	2004-03-25 00:21:46.000000000 +0000
@@ -328,7 +328,7 @@ acpi_ds_result_push (
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result stack frame\n"));
+		ACPI_REPORT_ERROR (("No result stack frame during push\n"));
 		return (AE_AML_INTERNAL);
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/events/evgpe.c linux-2.4.26-pre6/drivers/acpi/events/evgpe.c
--- linux-2.4.25/drivers/acpi/events/evgpe.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/events/evgpe.c	2004-03-25 00:20:55.000000000 +0000
@@ -149,6 +149,11 @@ acpi_ev_gpe_detect (
 
 	ACPI_FUNCTION_NAME ("ev_gpe_detect");
 
+	/* Check for the case where there are no GPEs */
+
+	if (!gpe_xrupt_list) {
+		return (int_status);
+	}
 
 	/* Examine all GPE blocks attached to this interrupt level */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exconvrt.c linux-2.4.26-pre6/drivers/acpi/executer/exconvrt.c
--- linux-2.4.25/drivers/acpi/executer/exconvrt.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exconvrt.c	2004-03-25 00:17:15.000000000 +0000
@@ -55,8 +55,9 @@
  *
  * FUNCTION:    acpi_ex_convert_to_integer
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
  *                                Integer, Buffer, or String
+ *              result_desc     - Where the new Integer object is returned
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -189,8 +190,9 @@ acpi_ex_convert_to_integer (
  *
  * FUNCTION:    acpi_ex_convert_to_buffer
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
  *                                Integer, Buffer, or String
+ *              result_desc     - Where the new buffer object is returned
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -319,6 +321,7 @@ acpi_ex_convert_to_ascii (
 
 	ACPI_FUNCTION_ENTRY ();
 
+
 	if (data_width < sizeof (acpi_integer)) {
 		leading_zero = FALSE;
 		length = data_width;
@@ -328,22 +331,21 @@ acpi_ex_convert_to_ascii (
 		length = sizeof (acpi_integer);
 	}
 
-
 	switch (base) {
 	case 10:
 
 		remainder = 0;
-		for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0 ; i--) {
+		for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0; i--) {
 			/* Divide by nth factor of 10 */
 
 			digit = integer;
-			for (j = 1; j < i; j++) {
+			for (j = 0; j < i; j++) {
 				(void) acpi_ut_short_divide (&digit, 10, &digit, &remainder);
 			}
 
 			/* Create the decimal digit */
 
-			if (digit != 0) {
+			if (remainder != 0) {
 				leading_zero = FALSE;
 			}
 
@@ -354,6 +356,7 @@ acpi_ex_convert_to_ascii (
 		}
 		break;
 
+
 	case 16:
 
 		/* Copy the integer to the buffer */
@@ -372,13 +375,14 @@ acpi_ex_convert_to_ascii (
 		}
 		break;
 
+
 	default:
 		break;
 	}
 
 	/*
 	 * Since leading zeros are supressed, we must check for the case where
-	 * the integer equals 0.
+	 * the integer equals 0
 	 *
 	 * Finally, null terminate the string and return the length
 	 */
@@ -396,8 +400,11 @@ acpi_ex_convert_to_ascii (
  *
  * FUNCTION:    acpi_ex_convert_to_string
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
- *                                Integer, Buffer, or String
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
+ *                                  Integer, Buffer, or String
+ *              result_desc     - Where the string object is returned
+ *              Base            - 10 or 16
+ *              max_length      - Max length of the returned string
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -415,10 +422,10 @@ acpi_ex_convert_to_string (
 	struct acpi_walk_state          *walk_state)
 {
 	union acpi_operand_object       *ret_desc;
-	u32                             i;
-	u32                             string_length;
 	u8                              *new_buf;
 	u8                              *pointer;
+	u32                             string_length;
+	u32                             i;
 
 
 	ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
@@ -539,7 +546,6 @@ acpi_ex_convert_to_string (
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
-
 	/*
 	 * If we are about to overwrite the original object on the operand stack,
 	 * we must remove a reference on the original object because we are
@@ -562,6 +568,7 @@ acpi_ex_convert_to_string (
  *
  * PARAMETERS:  destination_type    - Current type of the destination
  *              source_desc         - Source object to be converted.
+ *              result_desc         - Where the converted object is returned
  *              walk_state          - Current method state
  *
  * RETURN:      Status
@@ -653,6 +660,8 @@ acpi_ex_convert_to_target_type (
 
 
 		default:
+			ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
+				destination_type));
 			status = AE_AML_INTERNAL;
 			break;
 		}
@@ -672,6 +681,8 @@ acpi_ex_convert_to_target_type (
 			GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
 			walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
 
+		ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
+			GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
 		status = AE_AML_INTERNAL;
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/excreate.c linux-2.4.26-pre6/drivers/acpi/executer/excreate.c
--- linux-2.4.25/drivers/acpi/executer/excreate.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/excreate.c	2004-03-25 00:22:05.000000000 +0000
@@ -587,27 +587,33 @@ acpi_ex_create_method (
 	obj_desc->method.aml_start = aml_start;
 	obj_desc->method.aml_length = aml_length;
 
-	/* disassemble the method flags */
-
+	/*
+	 * Disassemble the method flags.  Split off the Arg Count
+	 * for efficiency
+	 */
 	method_flags = (u8) operand[1]->integer.value;
 
-	obj_desc->method.method_flags = method_flags;
-	obj_desc->method.param_count = (u8) (method_flags & METHOD_FLAGS_ARG_COUNT);
+	obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
+	obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
 
 	/*
 	 * Get the concurrency count.  If required, a semaphore will be
 	 * created for this method when it is parsed.
 	 */
-	if (method_flags & METHOD_FLAGS_SERIALIZED) {
+	if (acpi_gbl_all_methods_serialized) {
+		obj_desc->method.concurrency = 1;
+		obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
+	}
+	else if (method_flags & AML_METHOD_SERIALIZED) {
 		/*
 		 * ACPI 1.0: Concurrency = 1
 		 * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
 		 */
 		obj_desc->method.concurrency = (u8)
-				  (((method_flags & METHOD_FLAGS_SYNCH_LEVEL) >> 4) + 1);
+				  (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
 	}
 	else {
-		obj_desc->method.concurrency = INFINITE_CONCURRENCY;
+		obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
 	}
 
 	/* Attach the new object to the method Node */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exfldio.c linux-2.4.26-pre6/drivers/acpi/executer/exfldio.c
--- linux-2.4.25/drivers/acpi/executer/exfldio.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exfldio.c	2004-03-25 00:18:46.000000000 +0000
@@ -154,8 +154,7 @@ acpi_ex_setup_region (
 			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
 			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
 
-		#ifdef CONFIG_ACPI_RELAXED_AML
-		{
+		if (!acpi_strict) {
 			/*
 			 * Allow access to the field if it is within the region size
 			 * rounded up to a multiple of the access byte width.  This
@@ -186,9 +185,9 @@ acpi_ex_setup_region (
 				return_ACPI_STATUS (AE_OK);
 			}
 		}
-		#else
+		else {
 			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-		#endif
+		}
 	}
 
 	return_ACPI_STATUS (AE_OK);
@@ -507,8 +506,8 @@ acpi_ex_field_datum_io (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n",
-			obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+		ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
+			ACPI_GET_OBJECT_TYPE (obj_desc)));
 		status = AE_AML_INTERNAL;
 		break;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exmisc.c linux-2.4.26-pre6/drivers/acpi/executer/exmisc.c
--- linux-2.4.25/drivers/acpi/executer/exmisc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exmisc.c	2004-03-25 00:21:35.000000000 +0000
@@ -103,7 +103,7 @@ acpi_ex_get_object_reference (
 
 		default:
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference subtype %X\n",
+			ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n",
 				obj_desc->reference.opcode));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
@@ -121,8 +121,8 @@ acpi_ex_get_object_reference (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p has invalid descriptor [%s]\n",
-				obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
+		ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n",
+				ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
@@ -349,6 +349,8 @@ acpi_ex_do_concatenate (
 
 		/* Invalid object type, should not happen here */
 
+		ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
+				ACPI_GET_OBJECT_TYPE (obj_desc1)));
 		status = AE_AML_INTERNAL;
 		return_desc = NULL;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exmutex.c linux-2.4.26-pre6/drivers/acpi/executer/exmutex.c
--- linux-2.4.25/drivers/acpi/executer/exmutex.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exmutex.c	2004-03-25 00:21:22.000000000 +0000
@@ -176,15 +176,18 @@ acpi_ex_acquire_mutex (
 	/*
 	 * Support for multiple acquires by the owning thread
 	 */
+	if (obj_desc->mutex.owner_thread) {
+		/* Special case for Global Lock, allow all threads */
 
-	if ((obj_desc->mutex.owner_thread) &&
-		(obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id)) {
-		/*
-		 * The mutex is already owned by this thread,
-		 * just increment the acquisition depth
-		 */
-		obj_desc->mutex.acquisition_depth++;
-		return_ACPI_STATUS (AE_OK);
+		if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) ||
+			(obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) {
+			/*
+			 * The mutex is already owned by this thread,
+			 * just increment the acquisition depth
+			 */
+			obj_desc->mutex.acquisition_depth++;
+			return_ACPI_STATUS (AE_OK);
+		}
 	}
 
 	/* Acquire the mutex, wait if necessary */
@@ -254,9 +257,12 @@ acpi_ex_release_mutex (
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
 
-	/* The Mutex is owned, but this thread must be the owner */
-
-	if (obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) {
+	/*
+	 * The Mutex is owned, but this thread must be the owner.
+	 * Special case for Global Lock, any thread can release
+	 */
+	if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
+		(obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
 		ACPI_REPORT_ERROR ((
 			"Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
 			walk_state->thread->thread_id,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exoparg2.c linux-2.4.26-pre6/drivers/acpi/executer/exoparg2.c
--- linux-2.4.25/drivers/acpi/executer/exoparg2.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exoparg2.c	2004-03-25 00:20:02.000000000 +0000
@@ -329,6 +329,8 @@ acpi_ex_opcode_2A_1T_1R (
 			break;
 
 		default:
+			ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
+					ACPI_GET_OBJECT_TYPE (operand[0])));
 			status = AE_AML_INTERNAL;
 		}
 
@@ -433,7 +435,7 @@ acpi_ex_opcode_2A_1T_1R (
 			}
 
 			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
-			return_desc->reference.object    = operand[0]->package.elements [index];
+			return_desc->reference.object    = operand[0];
 			return_desc->reference.where     = &operand[0]->package.elements [index];
 		}
 		else {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exprep.c linux-2.4.26-pre6/drivers/acpi/executer/exprep.c
--- linux-2.4.25/drivers/acpi/executer/exprep.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exprep.c	2004-03-25 00:18:05.000000000 +0000
@@ -507,7 +507,7 @@ acpi_ex_prep_field_value (
 			(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));
 
 		if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n"));
+			ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exresolv.c linux-2.4.26-pre6/drivers/acpi/executer/exresolv.c
--- linux-2.4.25/drivers/acpi/executer/exresolv.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exresolv.c	2004-03-25 00:19:15.000000000 +0000
@@ -238,8 +238,8 @@ acpi_ex_resolve_object_to_value (
 
 				/* Invalid reference object */
 
-				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-					"Unknown target_type %X in Index/Reference obj %p\n",
+				ACPI_REPORT_ERROR ((
+					"During resolve, Unknown target_type %X in Index/Reference obj %p\n",
 					stack_desc->reference.target_type, stack_desc));
 				status = AE_AML_INTERNAL;
 				break;
@@ -258,7 +258,7 @@ acpi_ex_resolve_object_to_value (
 
 		default:
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X (%s) in %p\n",
+			ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n",
 				opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
 			status = AE_AML_INTERNAL;
 			break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exresop.c linux-2.4.26-pre6/drivers/acpi/executer/exresop.c
--- linux-2.4.25/drivers/acpi/executer/exresop.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exresop.c	2004-03-25 00:21:50.000000000 +0000
@@ -154,7 +154,7 @@ acpi_ex_resolve_operands (
 
 	arg_types = op_info->runtime_args;
 	if (arg_types == ARGI_INVALID_OPCODE) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - %X is not a valid AML opcode\n",
+		ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
 			opcode));
 
 		return_ACPI_STATUS (AE_AML_INTERNAL);
@@ -172,7 +172,7 @@ acpi_ex_resolve_operands (
 	 */
 	while (GET_CURRENT_ARG_TYPE (arg_types)) {
 		if (!stack_ptr || !*stack_ptr) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null stack entry at %p\n",
+			ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
 				stack_ptr));
 
 			return_ACPI_STATUS (AE_AML_INTERNAL);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exstore.c linux-2.4.26-pre6/drivers/acpi/executer/exstore.c
--- linux-2.4.25/drivers/acpi/executer/exstore.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exstore.c	2004-03-25 00:19:27.000000000 +0000
@@ -125,7 +125,7 @@ acpi_ex_store (
 
 	default:
 
-		/* Destination is not an Reference */
+		/* Destination is not a Reference object */
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Destination is not a Reference or Constant object [%p]\n", dest_desc));
@@ -189,35 +189,38 @@ acpi_ex_store (
 		switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
 		case ACPI_TYPE_INTEGER:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n",
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
 					ACPI_FORMAT_UINT64 (source_desc->integer.value)));
 			break;
 
 
 		case ACPI_TYPE_BUFFER:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length %.2X\n",
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X",
 					(u32) source_desc->buffer.length));
+			ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
+				(source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
 			break;
 
 
 		case ACPI_TYPE_STRING:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s\n", source_desc->string.pointer));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X, \"%s\"\n",
+					source_desc->string.length, source_desc->string.pointer));
 			break;
 
 
 		case ACPI_TYPE_PACKAGE:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Elements Ptr - %p\n",
-					source_desc->package.elements));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Size 0x%.2X Elements Ptr - %p\n",
+					source_desc->package.count, source_desc->package.elements));
 			break;
 
 
 		default:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Type %s %p\n",
-					acpi_ut_get_object_type_name (source_desc), source_desc));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n",
+					source_desc));
 			break;
 		}
 
@@ -227,7 +230,7 @@ acpi_ex_store (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X\n",
+		ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
 			ref_desc->reference.opcode));
 		ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
 
@@ -263,6 +266,7 @@ acpi_ex_store_object_to_index (
 	union acpi_operand_object       *obj_desc;
 	union acpi_operand_object       *new_desc;
 	u8                              value = 0;
+	u32                             i;
 
 
 	ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
@@ -283,6 +287,7 @@ acpi_ex_store_object_to_index (
 		/*
 		 * The object at *(index_desc->Reference.Where) is the
 		 * element within the package that is to be modified.
+		 * The parent package object is at index_desc->Reference.Object
 		 */
 		obj_desc = *(index_desc->reference.where);
 
@@ -309,6 +314,12 @@ acpi_ex_store_object_to_index (
 			if (new_desc == source_desc) {
 				acpi_ut_add_reference (new_desc);
 			}
+
+			/* Increment reference count by the ref count of the parent package -1 */
+
+			for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
+				acpi_ut_add_reference (new_desc);
+			}
 		}
 		break;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exstoren.c linux-2.4.26-pre6/drivers/acpi/executer/exstoren.c
--- linux-2.4.25/drivers/acpi/executer/exstoren.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/executer/exstoren.c	2004-03-25 00:17:34.000000000 +0000
@@ -112,6 +112,12 @@ acpi_ex_resolve_object (
 			}
 		}
 
+		/* For copy_object, no further validation necessary */
+
+		if (walk_state->opcode == AML_COPY_OP) {
+			break;
+		}
+
 		/*
 		 * Must have a Integer, Buffer, or String
 		 */
@@ -136,7 +142,7 @@ acpi_ex_resolve_object (
 		/*
 		 * Aliases are resolved by acpi_ex_prep_operands
 		 */
-		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into Alias - should never happen\n"));
+		ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
 		status = AE_AML_INTERNAL;
 		break;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/hardware/hwgpe.c linux-2.4.26-pre6/drivers/acpi/hardware/hwgpe.c
--- linux-2.4.25/drivers/acpi/hardware/hwgpe.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/hardware/hwgpe.c	2004-03-25 00:17:08.000000000 +0000
@@ -528,6 +528,14 @@ acpi_hw_enable_non_wakeup_gpe_block (
 	/* Examine each GPE register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+		/* Clear the entire status register */
+
+		status = acpi_hw_low_level_write (8, 0xFF,
+				 &gpe_block->register_info[i].status_address);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+
 		/*
 		 * We previously stored the enabled status of all GPEs.
 		 * Blast them back in.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/hardware/hwregs.c linux-2.4.26-pre6/drivers/acpi/hardware/hwregs.c
--- linux-2.4.25/drivers/acpi/hardware/hwregs.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/hardware/hwregs.c	2004-03-25 00:21:36.000000000 +0000
@@ -152,11 +152,11 @@ acpi_get_sleep_type_data (
 	/*
 	 * Evaluate the namespace object containing the values for this state
 	 */
-	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_db_sleep_states[sleep_state],
+	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
 			  NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
-			acpi_format_exception (status), acpi_gbl_db_sleep_states[sleep_state]));
+			acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
 
 		return_ACPI_STATUS (status);
 	}
@@ -201,7 +201,7 @@ acpi_get_sleep_type_data (
 
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-			acpi_gbl_db_sleep_states[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+			acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
 	}
 
 	acpi_ut_remove_reference (obj_desc);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/hardware/hwsleep.c linux-2.4.26-pre6/drivers/acpi/hardware/hwsleep.c
--- linux-2.4.25/drivers/acpi/hardware/hwsleep.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/hardware/hwsleep.c	2004-03-25 00:17:27.000000000 +0000
@@ -48,6 +48,19 @@
 	 ACPI_MODULE_NAME    ("hwsleep")
 
 
+#define METHOD_NAME__BFS        "\\_BFS"
+#define METHOD_NAME__GTS        "\\_GTS"
+#define METHOD_NAME__PTS        "\\_PTS"
+#define METHOD_NAME__SST        "\\_SI._SST"
+#define METHOD_NAME__WAK        "\\_WAK"
+
+#define ACPI_SST_INDICATOR_OFF  0
+#define ACPI_SST_WORKING        1
+#define ACPI_SST_WAKING         2
+#define ACPI_SST_SLEEPING       3
+#define ACPI_SST_SLEEP_CONTEXT  4
+
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_set_firmware_waking_vector
@@ -171,19 +184,41 @@ acpi_enter_sleep_state_prep (
 
 	/* Run the _PTS and _GTS methods */
 
-	status = acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS (status);
 	}
 
-	status = acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS (status);
 	}
 
+	/* Setup the argument to _SST */
+
+	switch (sleep_state) {
+	case ACPI_STATE_S0:
+		arg.integer.value = ACPI_SST_WORKING;
+		break;
+
+	case ACPI_STATE_S1:
+	case ACPI_STATE_S2:
+	case ACPI_STATE_S3:
+		arg.integer.value = ACPI_SST_SLEEPING;
+		break;
+
+	case ACPI_STATE_S4:
+		arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
+		break;
+
+	default:
+		arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
+		break;
+	}
+
 	/* Set the system indicators to show the desired sleep state. */
 
-	status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
 	}
@@ -477,19 +512,19 @@ acpi_leave_sleep_state (
 
 	/* Ignore any errors from these methods */
 
-	arg.integer.value = 0;
-	status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+	arg.integer.value = ACPI_SST_WAKING;
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
 	}
 
 	arg.integer.value = sleep_state;
-	status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status)));
 	}
 
-	status = acpi_evaluate_object (NULL, "\\_WAK", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status)));
 	}
@@ -501,8 +536,25 @@ acpi_leave_sleep_state (
 		return_ACPI_STATUS (status);
 	}
 
+	/* Enable power button */
+
+	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
+			1, ACPI_MTX_DO_NOT_LOCK);
+	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
+			1, ACPI_MTX_DO_NOT_LOCK);
+
 	/* Enable BM arbitration */
 
 	status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	arg.integer.value = ACPI_SST_WORKING;
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
+	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
+		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
+	}
+
 	return_ACPI_STATUS (status);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsaccess.c linux-2.4.26-pre6/drivers/acpi/namespace/nsaccess.c
--- linux-2.4.25/drivers/acpi/namespace/nsaccess.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/namespace/nsaccess.c	2004-03-25 00:22:12.000000000 +0000
@@ -105,8 +105,15 @@ acpi_ns_root_initialize (void)
 		"Entering predefined entries into namespace\n"));
 
 	for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
+		/* _OSI is optional for now, will be permanent later */
+
+		if (!ACPI_STRCMP (init_val->name, "_OSI") && !acpi_gbl_create_osi_method) {
+			continue;
+		}
+
 		status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
-				  ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node);
+				  ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
+				  NULL, &new_node);
 
 		if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
@@ -122,7 +129,8 @@ acpi_ns_root_initialize (void)
 		if (init_val->val) {
 			status = acpi_os_predefined_override (init_val, &val);
 			if (ACPI_FAILURE (status)) {
-				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n",
+				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+					"Could not override predefined %s\n",
 					init_val->name));
 			}
 
@@ -147,15 +155,20 @@ acpi_ns_root_initialize (void)
 			 */
 			switch (init_val->type) {
 			case ACPI_TYPE_METHOD:
-				obj_desc->method.param_count =
-						(u8) ACPI_STRTOUL (val, NULL, 10);
+				obj_desc->method.param_count = (u8) ACPI_STRTOUL
+						  (val, NULL, 10);
 				obj_desc->common.flags |= AOPOBJ_DATA_VALID;
 
-#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
+#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App)
 
-				/* Compiler cheats by putting parameter count in the owner_iD */
+				/* i_aSL Compiler cheats by putting parameter count in the owner_iD */
 
 				new_node->owner_id = obj_desc->method.param_count;
+#else
+				/* Mark this as a very SPECIAL method */
+
+				obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY;
+				obj_desc->method.implementation = acpi_ut_osi_implementation;
 #endif
 				break;
 
@@ -180,8 +193,8 @@ acpi_ns_root_initialize (void)
 			case ACPI_TYPE_MUTEX:
 
 				obj_desc->mutex.node = new_node;
-				obj_desc->mutex.sync_level =
-						 (u16) ACPI_STRTOUL (val, NULL, 10);
+				obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL
+						  (val, NULL, 10);
 
 				if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
 					/*
@@ -213,6 +226,7 @@ acpi_ns_root_initialize (void)
 
 
 			default:
+
 				ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
 					init_val->type));
 				acpi_ut_remove_reference (obj_desc);
@@ -314,7 +328,7 @@ acpi_ns_lookup (
 	else {
 		prefix_node = scope_info->scope.node;
 		if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p Not a namespace node [%s]\n",
+			ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
 					prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsalloc.c linux-2.4.26-pre6/drivers/acpi/namespace/nsalloc.c
--- linux-2.4.25/drivers/acpi/namespace/nsalloc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/namespace/nsalloc.c	2004-03-25 00:20:04.000000000 +0000
@@ -334,10 +334,11 @@ acpi_ns_install_node (
 	node->owner_id = owner_id;
 	node->type = (u8) type;
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s (%s) added to %4.4s (%s) %p at %p\n",
-		acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type),
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
+		"%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
+		acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id,
 		acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type),
-		parent_node, node));
+		parent_node));
 
 	/*
 	 * Increment the reference count(s) of all parents up to
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nseval.c linux-2.4.26-pre6/drivers/acpi/namespace/nseval.c
--- linux-2.4.25/drivers/acpi/namespace/nseval.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/namespace/nseval.c	2004-03-25 00:19:21.000000000 +0000
@@ -82,11 +82,11 @@ acpi_ns_evaluate_relative (
 	union acpi_operand_object       **params,
 	union acpi_operand_object       **return_object)
 {
-	struct acpi_namespace_node      *prefix_node;
 	acpi_status                     status;
+	struct acpi_namespace_node      *prefix_node;
 	struct acpi_namespace_node      *node = NULL;
+	union acpi_generic_state        *scope_info;
 	char                            *internal_path = NULL;
-	union acpi_generic_state        scope_info;
 
 
 	ACPI_FUNCTION_TRACE ("ns_evaluate_relative");
@@ -106,11 +106,16 @@ acpi_ns_evaluate_relative (
 		return_ACPI_STATUS (status);
 	}
 
+	scope_info = acpi_ut_create_generic_state ();
+	if (!scope_info) {
+		goto cleanup1;
+	}
+
 	/* Get the prefix handle and Node */
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	prefix_node = acpi_ns_map_handle_to_node (handle);
@@ -122,8 +127,8 @@ acpi_ns_evaluate_relative (
 
 	/* Lookup the name in the namespace */
 
-	scope_info.scope.node = prefix_node;
-	status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY,
+	scope_info->scope.node = prefix_node;
+	status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
 			 &node);
 
@@ -148,7 +153,9 @@ acpi_ns_evaluate_relative (
 		pathname));
 
 cleanup:
+	acpi_ut_delete_generic_state (scope_info);
 
+cleanup1:
 	ACPI_MEM_FREE (internal_path);
 	return_ACPI_STATUS (status);
 }
@@ -197,7 +204,7 @@ acpi_ns_evaluate_by_name (
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	/* Lookup the name in the namespace */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsutils.c linux-2.4.26-pre6/drivers/acpi/namespace/nsutils.c
--- linux-2.4.25/drivers/acpi/namespace/nsutils.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/namespace/nsutils.c	2004-03-25 00:19:57.000000000 +0000
@@ -918,7 +918,7 @@ acpi_ns_get_node_by_path (
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	/* Setup lookup scope (search starting point) */
@@ -936,10 +936,10 @@ acpi_ns_get_node_by_path (
 				internal_path, acpi_format_exception (status)));
 	}
 
-	/* Cleanup */
-
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
+cleanup:
+	/* Cleanup */
 	if (internal_path) {
 		ACPI_MEM_FREE (internal_path);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsxfname.c linux-2.4.26-pre6/drivers/acpi/namespace/nsxfname.c
--- linux-2.4.25/drivers/acpi/namespace/nsxfname.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/namespace/nsxfname.c	2004-03-25 00:18:20.000000000 +0000
@@ -326,6 +326,13 @@ acpi_get_object_info (
 			info.valid |= ACPI_VALID_ADR;
 		}
 
+		/* Execute the Device._sx_d methods */
+
+		status = acpi_ut_execute_sxds (node, info.highest_dstates);
+		if (ACPI_SUCCESS (status)) {
+			info.valid |= ACPI_VALID_STA;
+		}
+
 		status = AE_OK;
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/osl.c linux-2.4.26-pre6/drivers/acpi/osl.c
--- linux-2.4.25/drivers/acpi/osl.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/osl.c	2004-03-25 00:16:56.000000000 +0000
@@ -1021,3 +1021,39 @@ acpi_os_name_setup(char *str)
 }
 
 __setup("acpi_os_name=", acpi_os_name_setup);
+
+/*
+ * _OSI control
+ * empty string disables _OSI
+ * TBD additional string adds to _OSI
+ */
+int __init
+acpi_osi_setup(char *str)
+{
+	if (str == NULL || *str == '\0') {
+		printk(KERN_INFO PREFIX "_OSI method disabled\n");
+		acpi_gbl_create_osi_method = FALSE;
+	} else
+	{
+		/* TBD */
+		printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str);
+	}
+
+	return 1;
+}
+
+__setup("acpi_osi=", acpi_osi_setup);
+
+/* enable serialization to combat AE_ALREADY_EXISTS errors */
+int __init
+acpi_serialize_setup(char *str)
+{
+	printk(KERN_INFO PREFIX "serialize enabled\n");
+
+	acpi_gbl_all_methods_serialized = TRUE;
+
+	return 1;
+}
+
+__setup("acpi_serialize", acpi_serialize_setup);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/parser/psargs.c linux-2.4.26-pre6/drivers/acpi/parser/psargs.c
--- linux-2.4.25/drivers/acpi/parser/psargs.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/parser/psargs.c	2004-03-25 00:18:42.000000000 +0000
@@ -315,8 +315,8 @@ acpi_ps_get_next_namepath (
 				acpi_ps_append_arg (arg, name_op);
 
 				if (!method_desc) {
-					ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
-						"Control Method - %p has no attached object\n",
+					ACPI_REPORT_ERROR ((
+						"ps_get_next_namepath: Control Method %p has no attached object\n",
 						node));
 					return_ACPI_STATUS (AE_AML_INTERNAL);
 				}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/parser/psparse.c linux-2.4.26-pre6/drivers/acpi/parser/psparse.c
--- linux-2.4.25/drivers/acpi/parser/psparse.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/parser/psparse.c	2004-03-25 00:17:57.000000000 +0000
@@ -426,7 +426,7 @@ acpi_ps_parse_loop (
 	acpi_status                     status = AE_OK;
 	union acpi_parse_object         *op = NULL;     /* current op */
 	union acpi_parse_object         *arg = NULL;
-	union acpi_parse_object         pre_op;
+	union acpi_parse_object         *pre_op = NULL;
 	struct acpi_parse_state         *parser_state;
 	u8                              *aml_op_start = NULL;
 
@@ -547,8 +547,17 @@ acpi_ps_parse_loop (
 			/* Create Op structure and append to parent's argument list */
 
 			if (walk_state->op_info->flags & AML_NAMED) {
-				pre_op.common.value.arg = NULL;
-				pre_op.common.aml_opcode = walk_state->opcode;
+				/* Allocate a new pre_op if necessary */
+
+				if (!pre_op) {
+					pre_op = acpi_ps_alloc_op (walk_state->opcode);
+					if (!pre_op) {
+						return_ACPI_STATUS (AE_NO_MEMORY);
+					}
+				}
+
+				pre_op->common.value.arg = NULL;
+				pre_op->common.aml_opcode = walk_state->opcode;
 
 				/*
 				 * Get and append arguments until we find the node that contains
@@ -562,7 +571,7 @@ acpi_ps_parse_loop (
 						goto close_this_op;
 					}
 
-					acpi_ps_append_arg (&pre_op, arg);
+					acpi_ps_append_arg (pre_op, arg);
 					INCREMENT_ARG_LIST (walk_state->arg_types);
 				}
 
@@ -603,7 +612,7 @@ acpi_ps_parse_loop (
 					goto close_this_op;
 				}
 
-				acpi_ps_append_arg (op, pre_op.common.value.arg);
+				acpi_ps_append_arg (op, pre_op->common.value.arg);
 				acpi_gbl_depth++;
 
 				if (op->common.aml_opcode == AML_REGION_OP) {
@@ -854,6 +863,10 @@ close_this_op:
 
 		acpi_ps_complete_this_op (walk_state, op);
 		op = NULL;
+		if (pre_op) {
+			acpi_ps_free_op (pre_op);
+			pre_op = NULL;
+		}
 
 		switch (status) {
 		case AE_OK:
@@ -1118,6 +1131,27 @@ acpi_ps_parse_aml (
 		else if (status != AE_OK) {
 			ACPI_REPORT_METHOD_ERROR ("Method execution failed",
 				walk_state->method_node, NULL, status);
+
+			/* Check for possible multi-thread reentrancy problem */
+
+			if ((status == AE_ALREADY_EXISTS) &&
+				(!walk_state->method_desc->method.semaphore)) {
+				/*
+				 * This method is marked not_serialized, but it tried to create a named
+				 * object, causing the second thread entrance to fail.  We will workaround
+				 * this by marking the method permanently as Serialized.
+				 */
+				walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
+				walk_state->method_desc->method.concurrency = 1;
+			}
+		}
+
+		if (walk_state->method_desc) {
+			/* Decrement the thread count on the method parse tree */
+
+			if (walk_state->method_desc->method.thread_count) {
+				walk_state->method_desc->method.thread_count--;
+			}
 		}
 
 		/* We are done with this walk, move on to the parent if any */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/parser/psscope.c linux-2.4.26-pre6/drivers/acpi/parser/psscope.c
--- linux-2.4.25/drivers/acpi/parser/psscope.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/parser/psscope.c	2004-03-25 00:17:18.000000000 +0000
@@ -167,7 +167,6 @@ acpi_ps_push_scope (
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-
 	scope->common.data_type        = ACPI_DESC_TYPE_STATE_PSCOPE;
 	scope->parse_scope.op          = op;
 	scope->parse_scope.arg_list    = remaining_args;
@@ -178,13 +177,11 @@ acpi_ps_push_scope (
 
 	acpi_ut_push_generic_state (&parser_state->scope, scope);
 
-
 	if (arg_count == ACPI_VAR_ARGS) {
 		/* multiple arguments */
 
 		scope->parse_scope.arg_end = parser_state->pkg_end;
 	}
-
 	else {
 		/* single argument */
 
@@ -241,7 +238,6 @@ acpi_ps_pop_scope (
 
 		acpi_ut_delete_generic_state (scope);
 	}
-
 	else {
 		/* empty parse stack, prepare to fetch next opcode */
 
@@ -250,7 +246,6 @@ acpi_ps_pop_scope (
 		*arg_count              = 0;
 	}
 
-
 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *op, *arg_count));
 	return_VOID;
 }
@@ -275,14 +270,14 @@ acpi_ps_cleanup_scope (
 {
 	union acpi_generic_state        *scope;
 
+
 	ACPI_FUNCTION_TRACE_PTR ("ps_cleanup_scope", parser_state);
 
 
 	if (!parser_state) {
-		return;
+		return_VOID;
 	}
 
-
 	/* Delete anything on the scope stack */
 
 	while (parser_state->scope) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/pci_irq.c linux-2.4.26-pre6/drivers/acpi/pci_irq.c
--- linux-2.4.25/drivers/acpi/pci_irq.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/pci_irq.c	2004-03-25 00:22:21.000000000 +0000
@@ -277,6 +277,10 @@ acpi_pci_irq_lookup (
 	return_VALUE(entry->irq);
 }
 
+/*
+ * current thinking is that acpi_pci_irq_derive() adds no value
+ * and should be deleted, so warn if it actually does something.
+ */
 
 static int
 acpi_pci_irq_derive (
@@ -306,7 +310,8 @@ acpi_pci_irq_derive (
 		return_VALUE(0);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived IRQ %d\n", irq));
+	ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Derive IRQ %d for device %s from %s\n",
+		irq, pci_name(dev), pci_name(bridge)));
 
 	return_VALUE(irq);
 }
@@ -343,6 +348,13 @@ acpi_pci_irq_enable (
  	irq = acpi_pci_irq_lookup(0, dev->bus->number, PCI_SLOT(dev->devfn), pin);
  
 	/*
+	 * Check if the device has an IRQ,
+	 * Hotplug devices may get IRQs by scanning
+	 */
+	if (!irq && dev->irq)
+		irq = dev->irq;
+
+	/*
 	 * If no PRT entry was found, we'll try to derive an IRQ from the
 	 * device's parent bridge.
 	 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/pci_link.c linux-2.4.26-pre6/drivers/acpi/pci_link.c
--- linux-2.4.25/drivers/acpi/pci_link.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/pci_link.c	2004-03-25 00:22:36.000000000 +0000
@@ -767,7 +767,6 @@ __setup("acpi_irq_pci=", acpi_irq_pci);
 
 static int __init acpi_irq_nobalance_set(char *str)
 {
-printk("ACPI STATIC SET\n");
 	acpi_irq_balance = 0;
 	return(1);
 }
@@ -775,7 +774,6 @@ __setup("acpi_irq_nobalance", acpi_irq_n
 
 int __init acpi_irq_balance_set(char *str)
 {
-printk("ACPI BALANCE SET\n");
 	acpi_irq_balance = 1;
 	return(1);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/processor.c linux-2.4.26-pre6/drivers/acpi/processor.c
--- linux-2.4.25/drivers/acpi/processor.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/processor.c	2004-03-25 00:20:00.000000000 +0000
@@ -69,8 +69,6 @@ MODULE_LICENSE("GPL");
 #define ACPI_PROCESSOR_MAX_THROTTLE	250	/* 25% */
 #define ACPI_PROCESSOR_MAX_DUTY_WIDTH	4
 
-const u32 POWER_OF_2[] = {1,2,4,8,16,32,64};
-
 #define ACPI_PROCESSOR_LIMIT_USER	0
 #define ACPI_PROCESSOR_LIMIT_THERMAL	1
 
@@ -1377,7 +1375,7 @@ acpi_processor_get_throttling_info (
 		return_VALUE(0);
 	}
 
-	pr->throttling.state_count = POWER_OF_2[acpi_fadt.duty_width];
+	pr->throttling.state_count = 1 << acpi_fadt.duty_width;
 
 	/*
 	 * Compute state values. Note that throttling displays a linear power/
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/resources/rsxface.c linux-2.4.26-pre6/drivers/acpi/resources/rsxface.c
--- linux-2.4.25/drivers/acpi/resources/rsxface.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/resources/rsxface.c	2004-03-25 00:17:48.000000000 +0000
@@ -239,6 +239,7 @@ acpi_walk_resources (
 	acpi_status                         status;
 	struct acpi_buffer                  buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	struct acpi_resource                *resource;
+	struct acpi_resource                *buffer_end;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_walk_resources");
@@ -255,7 +256,13 @@ acpi_walk_resources (
 		return_ACPI_STATUS (status);
 	}
 
-	resource = (struct acpi_resource *) buffer.pointer;
+	/* Setup pointers */
+
+	resource  = (struct acpi_resource *) buffer.pointer;
+	buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length);
+
+	/* Walk the resource list */
+
 	for (;;) {
 		if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
 			break;
@@ -268,6 +275,7 @@ acpi_walk_resources (
 		case AE_CTRL_DEPTH:
 
 			/* Just keep going */
+
 			status = AE_OK;
 			break;
 
@@ -285,7 +293,15 @@ acpi_walk_resources (
 			goto cleanup;
 		}
 
+		/* Get the next resource descriptor */
+
 		resource = ACPI_NEXT_RESOURCE (resource);
+
+		/* Check for end-of-buffer */
+
+		if (resource >= buffer_end) {
+			goto cleanup;
+		}
 	}
 
 cleanup:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/system.c linux-2.4.26-pre6/drivers/acpi/system.c
--- linux-2.4.25/drivers/acpi/system.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/system.c	2004-03-25 00:19:19.000000000 +0000
@@ -40,15 +40,20 @@
 #include <asm/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <linux/sched.h>
 
-#ifdef CONFIG_X86
 #ifdef CONFIG_ACPI_SLEEP
 #include <linux/mc146818rtc.h>
 #include <linux/irq.h>
 #include <asm/hw_irq.h>
-#endif
-#endif
 
+acpi_status acpi_system_save_state(u32);
+#else
+static inline acpi_status acpi_system_save_state(u32 state)
+{
+	return AE_OK;
+}
+#endif /* !CONFIG_ACPI_SLEEP */
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME		("acpi_system")
@@ -95,6 +100,9 @@ acpi_power_off (void)
 {
 	if (unlikely(in_interrupt())) 
 		BUG();
+	/* Some SMP machines only can poweroff in boot CPU */
+	set_cpus_allowed(current, 1UL << cpu_logical_map(0));
+	acpi_system_save_state(ACPI_STATE_S5);
 	acpi_enter_sleep_state_prep(ACPI_STATE_S5);
 	ACPI_DISABLE_IRQS();
 	acpi_enter_sleep_state(ACPI_STATE_S5);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/toshiba_acpi.c linux-2.4.26-pre6/drivers/acpi/toshiba_acpi.c
--- linux-2.4.25/drivers/acpi/toshiba_acpi.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/toshiba_acpi.c	2004-03-25 00:17:32.000000000 +0000
@@ -33,7 +33,7 @@
  *
  */
 
-#define TOSHIBA_ACPI_VERSION	"0.17"
+#define TOSHIBA_ACPI_VERSION	"0.18"
 #define PROC_INTERFACE_VERSION	1
 
 #include <linux/kernel.h>
@@ -41,6 +41,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <asm/uaccess.h>
 #include <linux/version.h>
 
 #include <acpi/acpi_drivers.h>
@@ -106,24 +107,6 @@ _set_bit(u32* word, u32 mask, int value)
 	*word = (*word & ~mask) | (mask * value);
 }
 
-/* an sscanf that takes explicit string length */
-static int
-snscanf(const char* str, int n, const char* format, ...)
-{
-	va_list args;
-	int result;
-	char* str2 = kmalloc(n + 1, GFP_KERNEL);
-	if (str2 == 0) return 0;
-	/* NOTE: don't even _think_ about replacing this with strlcpy */
-	strncpy(str2, str, n);
-	str2[n] = 0;
-	va_start(args, format);
-	result = vsscanf(str2, format, args);
-	va_end(args);
-	kfree(str2);
-	return result;
-}
-
 /* acpi interface wrappers
  */
 
@@ -270,10 +253,26 @@ dispatch_read(char* page, char** start, 
 }
 
 static int
-dispatch_write(struct file* file, const char* buffer, unsigned long count,
-	ProcItem* item)
+dispatch_write(struct file* file, const char* buffer,
+	unsigned long count, ProcItem* item)
 {
-	return item->write_func(buffer, count);
+	int result;
+	char* tmp_buffer;
+
+	/* Arg buffer points to userspace memory, which can't be accessed
+	 * directly.  Since we're making a copy, zero-terminate the
+	 * destination so that sscanf can be used on it safely.
+	 */
+	tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
+	if (copy_from_user(tmp_buffer, buffer, count)) {
+		result = -EFAULT;
+	}
+	else {
+		tmp_buffer[count] = 0;
+		result = item->write_func(tmp_buffer, count);
+	}
+	kfree(tmp_buffer);
+	return result;
 }
 
 static char*
@@ -301,7 +300,7 @@ write_lcd(const char* buffer, unsigned l
 	int value;
 	u32 hci_result;
 
-	if (snscanf(buffer, count, " brightness : %i", &value) == 1 &&
+	if (sscanf(buffer, " brightness : %i", &value) == 1 &&
 			value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
 		value = value << HCI_LCD_BRIGHTNESS_SHIFT;
 		hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
@@ -351,11 +350,11 @@ write_video(const char* buffer, unsigned
 	 *  NOTE: to keep scanning simple, invalid fields are ignored
 	 */
 	while (remain) {
-		if (snscanf(buffer, remain, " lcd_out : %i", &value) == 1)
+		if (sscanf(buffer, " lcd_out : %i", &value) == 1)
 			lcd_out = value & 1;
-		else if (snscanf(buffer, remain, " crt_out : %i", &value) == 1)
+		else if (sscanf(buffer, " crt_out : %i", &value) == 1)
 			crt_out = value & 1;
-		else if (snscanf(buffer, remain, " tv_out : %i", &value) == 1)
+		else if (sscanf(buffer, " tv_out : %i", &value) == 1)
 			tv_out = value & 1;
 		/* advance to one character past the next ; */
 		do {
@@ -408,7 +407,7 @@ write_fan(const char* buffer, unsigned l
 	int value;
 	u32 hci_result;
 
-	if (snscanf(buffer, count, " force_on : %i", &value) == 1 &&
+	if (sscanf(buffer, " force_on : %i", &value) == 1 &&
 			value >= 0 && value <= 1) {
 		hci_write1(HCI_FAN, value, &hci_result);
 		if (hci_result != HCI_SUCCESS)
@@ -459,7 +458,7 @@ write_keys(const char* buffer, unsigned 
 {
 	int value;
 
-	if (snscanf(buffer, count, " hotkey_ready : %i", &value) == 1 &&
+	if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 &&
 			value == 0) {
 		key_event_valid = 0;
 	} else {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/utilities/uteval.c linux-2.4.26-pre6/drivers/acpi/utilities/uteval.c
--- linux-2.4.25/drivers/acpi/utilities/uteval.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/utilities/uteval.c	2004-03-25 00:17:25.000000000 +0000
@@ -53,6 +53,62 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_osi_implementation
+ *
+ * PARAMETERS:  walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Implementation of _OSI predefined control method
+ *              Supported = _OSI (String)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_osi_implementation (
+	struct acpi_walk_state          *walk_state)
+{
+	union acpi_operand_object       *string_desc;
+	union acpi_operand_object       *return_desc;
+	acpi_native_uint                i;
+
+
+	ACPI_FUNCTION_TRACE ("ut_osi_implementation");
+
+
+	/* Validate the string input argument */
+
+	string_desc = walk_state->arguments[0].object;
+	if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
+		return_ACPI_STATUS (AE_TYPE);
+	}
+
+	/* Create a return object (Default value = 0) */
+
+	return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+	if (!return_desc) {
+		return_ACPI_STATUS (AE_NO_MEMORY);
+	}
+
+	/* Compare input string to table of supported strings */
+
+	for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
+		if (!ACPI_STRCMP (string_desc->string.pointer,
+				   (char *) acpi_gbl_valid_osi_strings[i])) {
+			/* This string is supported */
+
+			return_desc->integer.value = 0xFFFFFFFF;
+			break;
+		}
+	}
+
+	walk_state->return_desc = return_desc;
+	return_ACPI_STATUS (AE_CTRL_TERMINATE);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_evaluate_object
  *
  * PARAMETERS:  prefix_node         - Starting node
@@ -562,3 +618,63 @@ acpi_ut_execute_STA (
 	acpi_ut_remove_reference (obj_desc);
 	return_ACPI_STATUS (status);
 }
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_execute_Sxds
+ *
+ * PARAMETERS:  device_node         - Node for the device
+ *              *Flags              - Where the status flags are returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Executes _STA for selected device and stores results in
+ *              *Flags.
+ *
+ *              NOTE: Internal function, no parameter validation
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_execute_sxds (
+	struct acpi_namespace_node      *device_node,
+	u8                              *highest)
+{
+	union acpi_operand_object       *obj_desc;
+	acpi_status                     status;
+	u32                             i;
+
+
+	ACPI_FUNCTION_TRACE ("ut_execute_Sxds");
+
+
+	for (i = 0; i < 4; i++) {
+		highest[i] = 0xFF;
+		status = acpi_ut_evaluate_object (device_node,
+				 (char *) acpi_gbl_highest_dstate_names[i],
+				 ACPI_BTYPE_INTEGER, &obj_desc);
+		if (ACPI_FAILURE (status)) {
+			if (status != AE_NOT_FOUND) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+					"%s on Device %4.4s, %s\n",
+					(char *) acpi_gbl_highest_dstate_names[i],
+					acpi_ut_get_node_name (device_node),
+					acpi_format_exception (status)));
+
+				return_ACPI_STATUS (status);
+			}
+		}
+		else {
+			/* Extract the Dstate value */
+
+			highest[i] = (u8) obj_desc->integer.value;
+
+			/* Delete the return object */
+
+			acpi_ut_remove_reference (obj_desc);
+		}
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/utilities/utglobal.c linux-2.4.26-pre6/drivers/acpi/utilities/utglobal.c
--- linux-2.4.25/drivers/acpi/utilities/utglobal.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/acpi/utilities/utglobal.c	2004-03-25 00:17:34.000000000 +0000
@@ -171,7 +171,7 @@ u8                                  acpi
 
 const u8                            acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
 
-const char                          *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT] = {
+const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
 			  "\\_S0_",
 			  "\\_S1_",
 			  "\\_S2_",
@@ -179,6 +179,20 @@ const char                          *acp
 			  "\\_S4_",
 			  "\\_S5_"};
 
+const char                          *acpi_gbl_highest_dstate_names[4] = {
+					   "_S1D",
+					   "_S2D",
+					   "_S3D",
+					   "_S4D"};
+
+/* Strings supported by the _OSI predefined (internal) method */
+
+const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
+							 "Linux",
+							 "Windows 2000",
+							 "Windows 2001",
+							 "Windows 2001.1"};
+
 
 /******************************************************************************
  *
@@ -190,14 +204,10 @@ const char                          *acp
 /*
  * Predefined ACPI Names (Built-in to the Interpreter)
  *
- * Initial values are currently supported only for types String and Number.
- * Both are specified as strings in this table.
- *
  * NOTES:
- * 1) _SB_ is defined to be a device to allow _SB_/_INI to be run
+ * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
  *    during the initialization sequence.
  */
-
 const struct acpi_predefined_names      acpi_gbl_pre_defined_names[] =
 { {"_GPE",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
 	{"_PR_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
@@ -208,7 +218,7 @@ const struct acpi_predefined_names      
 	{"_OS_",    ACPI_TYPE_STRING,           ACPI_OS_NAME},
 	{"_GL_",    ACPI_TYPE_MUTEX,            "0"},
 
-#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
+#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
 	{"_OSI",    ACPI_TYPE_METHOD,           "1"},
 #endif
 	{NULL,      ACPI_TYPE_ANY,              NULL}              /* Table terminator */
@@ -219,7 +229,6 @@ const struct acpi_predefined_names      
  * Properties of the ACPI Object Types, both internal and external.
  * The table is indexed by values of acpi_object_type
  */
-
 const u8                                acpi_gbl_ns_properties[] =
 {
 	ACPI_NS_NORMAL,                     /* 00 Any              */
@@ -298,10 +307,8 @@ acpi_ut_hex_to_ascii_char (
  *
  ******************************************************************************/
 
-
 struct acpi_table_list              acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
 
-
 struct acpi_table_support           acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] =
 {
 	/***********    Name,   Signature, Global typed pointer     Signature size,      Type                  How many allowed?,    Contains valid AML? */
@@ -465,9 +472,8 @@ acpi_ut_get_event_name (
  *
  * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; when
  * stored in a table it really means that we have thus far seen no evidence to
- * indicatewhat type is actually going to be stored for this entry.
+ * indicate what type is actually going to be stored for this entry.
  */
-
 static const char                   acpi_gbl_bad_type[] = "UNDEFINED";
 #define TYPE_NAME_LENGTH    12                           /* Maximum length of each string */
 
@@ -772,6 +778,11 @@ acpi_ut_init_globals (
 
 	ACPI_FUNCTION_TRACE ("ut_init_globals");
 
+	/* Runtime configuration */
+
+	acpi_gbl_create_osi_method = TRUE;
+	acpi_gbl_all_methods_serialized = FALSE;
+
 	/* Memory allocation and cache lists */
 
 	ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/block/ll_rw_blk.c linux-2.4.26-pre6/drivers/block/ll_rw_blk.c
--- linux-2.4.25/drivers/block/ll_rw_blk.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/block/ll_rw_blk.c	2004-03-25 00:17:31.000000000 +0000
@@ -942,6 +942,15 @@ static void attempt_merge(request_queue_
 		return;
 
 	q->elevator.elevator_merge_req_fn(req, next);
+	
+	/* At this point we have either done a back merge
+	 * or front merge. We need the smaller start_time of
+	 * the merged requests to be the current request
+	 * for accounting purposes.
+	 */
+	if (time_after(req->start_time, next->start_time))
+		req->start_time = next->start_time;
+		
 	req->bhtail->b_reqnext = next->bh;
 	req->bhtail = next->bhtail;
 	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/bluetooth/hci_usb.c linux-2.4.26-pre6/drivers/bluetooth/hci_usb.c
--- linux-2.4.25/drivers/bluetooth/hci_usb.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/bluetooth/hci_usb.c	2004-03-25 00:22:04.000000000 +0000
@@ -30,7 +30,7 @@
  *
  * $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $    
  */
-#define VERSION "2.4"
+#define VERSION "2.5"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -70,9 +70,6 @@
 static struct usb_driver hci_usb_driver; 
 
 static struct usb_device_id bluetooth_ids[] = {
-	/* Digianswer device */
-	{ USB_DEVICE(0x08fd, 0x0001), driver_info: HCI_DIGIANSWER },
-
 	/* Generic Bluetooth USB device */
 	{ USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) },
 
@@ -90,9 +87,15 @@ static struct usb_device_id bluetooth_id
 
 MODULE_DEVICE_TABLE (usb, bluetooth_ids);
 
-static struct usb_device_id ignore_ids[] = {
+static struct usb_device_id blacklist_ids[] = {
 	/* Broadcom BCM2033 without firmware */
-	{ USB_DEVICE(0x0a5c, 0x2033) },
+	{ USB_DEVICE(0x0a5c, 0x2033), driver_info: HCI_IGNORE },
+
+	/* Broadcom BCM2035 */
+	{ USB_DEVICE(0x0a5c, 0x200a), driver_info: HCI_RESET },
+
+	/* Digianswer device */
+	{ USB_DEVICE(0x08fd, 0x0001), driver_info: HCI_DIGIANSWER },
 
 	{ }	/* Terminating entry */
 };
@@ -648,7 +651,7 @@ static inline int __recv_frame(struct hc
 #endif
 			}
 			BT_DBG("new packet len %d", len);
-				
+
 			skb = bluez_skb_alloc(len, GFP_ATOMIC);
 			if (!skb) {
 				BT_ERR("%s no memory for the packet", husb->hdev.name);
@@ -796,8 +799,14 @@ static void *hci_usb_probe(struct usb_de
 
 	iface = &udev->actconfig->interface[0];
 
-	/* Check our black list */
-	if (usb_match_id(udev, iface, ignore_ids))
+	if (!id->driver_info) {
+		const struct usb_device_id *match;
+		match = usb_match_id(udev, iface, blacklist_ids);
+		if (match)
+			id = match;
+	}
+
+	if (id->driver_info & HCI_IGNORE)
 		return NULL;
 
 	/* Check number of endpoints */
@@ -921,6 +930,9 @@ static void *hci_usb_probe(struct usb_de
 	hdev->send  = hci_usb_send_frame;
 	hdev->destruct = hci_usb_destruct;
 
+	if (id->driver_info & HCI_RESET)
+		set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
+
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
 		goto probe_error;
@@ -983,6 +995,6 @@ void hci_usb_cleanup(void)
 module_init(hci_usb_init);
 module_exit(hci_usb_cleanup);
 
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
+MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("BlueZ HCI USB driver ver " VERSION);
 MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/bluetooth/hci_usb.h linux-2.4.26-pre6/drivers/bluetooth/hci_usb.h
--- linux-2.4.25/drivers/bluetooth/hci_usb.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/bluetooth/hci_usb.h	2004-03-25 00:20:30.000000000 +0000
@@ -37,7 +37,9 @@
 #define HCI_CTRL_REQ	     0x20
 #define HCI_DIGI_REQ	     0x40
 
-#define HCI_DIGIANSWER       0x01
+#define HCI_IGNORE           0x01
+#define HCI_RESET            0x02
+#define HCI_DIGIANSWER       0x04
 
 #define HCI_MAX_IFACE_NUM	3 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/agp/agpgart_be.c linux-2.4.26-pre6/drivers/char/agp/agpgart_be.c
--- linux-2.4.25/drivers/char/agp/agpgart_be.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/char/agp/agpgart_be.c	2004-03-25 00:17:50.000000000 +0000
@@ -6181,12 +6181,6 @@ static struct {
 		"SiS",
 		"650",
 		sis_generic_setup },
-	{ PCI_DEVICE_ID_SI_651,
-		PCI_VENDOR_ID_SI,
-		SIS_GENERIC,
-		"SiS",
-		"651",
-		sis_generic_setup },
 	{ PCI_DEVICE_ID_SI_645,
 		PCI_VENDOR_ID_SI,
 		SIS_GENERIC,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/q40_keyb.c linux-2.4.26-pre6/drivers/char/q40_keyb.c
--- linux-2.4.25/drivers/char/q40_keyb.c	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.26-pre6/drivers/char/q40_keyb.c	2004-03-25 00:20:00.000000000 +0000
@@ -400,7 +400,7 @@ exit:
 #define KBD_NO_DATA	(-1)	/* No data */
 #define KBD_BAD_DATA	(-2)	/* Parity or other error */
 
-static int __init kbd_read_input(void)
+static int __init q40kbd_read_input(void)
 {
 	int retval = KBD_NO_DATA;
 	unsigned char status;
@@ -421,7 +421,7 @@ static void __init kbd_clear_input(void)
 	int maxread = 100;	/* Random number */
 
 	do {
-		if (kbd_read_input() == KBD_NO_DATA)
+		if (q40kbd_read_input() == KBD_NO_DATA)
 			break;
 	} while (--maxread);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/sonypi.c linux-2.4.26-pre6/drivers/char/sonypi.c
--- linux-2.4.25/drivers/char/sonypi.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/char/sonypi.c	2004-03-25 00:20:59.000000000 +0000
@@ -129,7 +129,7 @@ static int ec_read16(u8 addr, u16 *value
 }
 
 /* Initializes the device - this comes from the AML code in the ACPI bios */
-static void __devinit sonypi_type1_srs(void) {
+static void sonypi_type1_srs(void) {
 	u32 v;
 
 	pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
@@ -151,7 +151,7 @@ static void __devinit sonypi_type1_srs(v
 	pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
 }
 
-static void __devinit sonypi_type2_srs(void) {
+static void sonypi_type2_srs(void) {
 	if (sonypi_ec_write(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8))
 		printk(KERN_WARNING "ec_write failed\n");
 	if (sonypi_ec_write(SONYPI_SLOB,  sonypi_device.ioport1 & 0x00FF))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/sonypi.h linux-2.4.26-pre6/drivers/char/sonypi.h
--- linux-2.4.25/drivers/char/sonypi.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/char/sonypi.h	2004-03-25 00:17:11.000000000 +0000
@@ -37,7 +37,7 @@
 #ifdef __KERNEL__
 
 #define SONYPI_DRIVER_MAJORVERSION	 1
-#define SONYPI_DRIVER_MINORVERSION	21
+#define SONYPI_DRIVER_MINORVERSION	22
 
 #define SONYPI_DEVICE_MODEL_TYPE1	1
 #define SONYPI_DEVICE_MODEL_TYPE2	2
@@ -239,6 +239,7 @@ static struct sonypi_event sonypi_pkeyev
 	{ 0x01, SONYPI_EVENT_PKEY_P1 },
 	{ 0x02, SONYPI_EVENT_PKEY_P2 },
 	{ 0x04, SONYPI_EVENT_PKEY_P3 },
+	{ 0x5c, SONYPI_EVENT_PKEY_P1 },
 	{ 0, 0 }
 };
 
@@ -333,6 +334,7 @@ struct sonypi_eventtypes {
 	{ SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
 	{ SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
 	{ SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
 
 	{ 0, 0, 0, 0 }
 };
@@ -394,7 +396,6 @@ struct sonypi_device {
 }
 
 #ifdef CONFIG_ACPI
-extern int acpi_disabled;
 #define SONYPI_ACPI_ACTIVE (!acpi_disabled)
 #else
 #define SONYPI_ACPI_ACTIVE 0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/tty_io.c linux-2.4.26-pre6/drivers/char/tty_io.c
--- linux-2.4.25/drivers/char/tty_io.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/char/tty_io.c	2004-03-25 00:20:28.000000000 +0000
@@ -2249,7 +2249,7 @@ void __init console_init(void)
 	au1x00_serial_console_init();
 #endif
 #ifdef CONFIG_SERIAL_CONSOLE
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+#if (defined(CONFIG_8xx) || defined(CONFIG_CPM2))
 	console_8xx_init();
 #elif defined(CONFIG_MAC_SERIAL) && defined(CONFIG_SERIAL)
 	if (_machine == _MACH_Pmac)
@@ -2435,7 +2435,7 @@ void __init tty_init(void)
 #ifdef CONFIG_SPECIALIX
 	specialix_init();
 #endif
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+#if (defined(CONFIG_8xx) || defined(CONFIG_CPM2))
 	rs_8xx_init();
 #endif /* CONFIG_8xx */
 	pty_init();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/i2c/Config.in linux-2.4.26-pre6/drivers/i2c/Config.in
--- linux-2.4.25/drivers/i2c/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/i2c/Config.in	2004-03-25 00:22:17.000000000 +0000
@@ -12,7 +12,7 @@ if [ "$CONFIG_I2C" != "n" ]; then
       dep_tristate '  Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT $CONFIG_PARPORT
       dep_tristate '  ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT
       dep_tristate '  Velleman K8000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT
-      dep_tristate '  NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200 $CONFIG_I2C_ALGOBIT
+      dep_tristate '  NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200_GPIO $CONFIG_I2C_ALGOBIT
       if [ "$CONFIG_SCx200_I2C" != "n" ]; then
          int  '    GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12
          int  '    GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/Config.in linux-2.4.26-pre6/drivers/ide/Config.in
--- linux-2.4.25/drivers/ide/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/Config.in	2004-03-25 00:22:00.000000000 +0000
@@ -190,6 +190,7 @@ fi
 dep_tristate 'Support for IDE Raid controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL
 dep_tristate '   Support Promise software RAID (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
 dep_tristate '   Highpoint 370 software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
+dep_tristate '   CMD/Silicon Image Medley Software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_MEDLEY $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
 dep_tristate '   Silicon Image Medley software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_SII $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
 
 endmenu
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/Makefile linux-2.4.26-pre6/drivers/ide/Makefile
--- linux-2.4.25/drivers/ide/Makefile	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/Makefile	2004-03-25 00:20:41.000000000 +0000
@@ -28,9 +28,13 @@ endif
 
 # Core IDE code - must come before legacy
 
-ide-core-objs	:= ide-iops.o ide-taskfile.o ide.o ide-lib.o ide-io.o ide-default.o ide-proc.o ide-probe.o ide-geometry.o
+ide-core-objs	:= ide-iops.o ide-taskfile.o ide.o ide-lib.o ide-io.o \
+		   ide-default.o ide-probe.o ide-geometry.o
 ide-detect-objs	:= ide-probe-mini.o
 
+ifeq ($(CONFIG_PROC_FS),y)
+ide-core-objs	+= ide-proc.o
+endif
 ifeq ($(CONFIG_BLK_DEV_IDEPCI),y)
 ide-core-objs += setup-pci.o
 endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/ide-proc.c linux-2.4.26-pre6/drivers/ide/ide-proc.c
--- linux-2.4.25/drivers/ide/ide-proc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/ide-proc.c	2004-03-25 00:17:16.000000000 +0000
@@ -811,35 +811,6 @@ void create_proc_ide_drives(ide_hwif_t *
 
 EXPORT_SYMBOL(create_proc_ide_drives);
 
-void recreate_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
-{
-	struct proc_dir_entry *ent;
-	struct proc_dir_entry *parent = hwif->proc;
-	char name[64];
-//	ide_driver_t *driver = drive->driver;
-
-	if (drive->present && !drive->proc) {
-		drive->proc = proc_mkdir(drive->name, parent);
-		if (drive->proc)
-			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-
-/*
- * assume that we have these already, however, should test FIXME!
- * if (driver) {
- *      ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
- *      ide_add_proc_entries(drive->proc, driver->proc, drive);
- * }
- *
- */
-		sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
-		ent = proc_symlink(drive->name, proc_ide_root, name);
-		if (!ent)
-			return;
-	}
-}
-
-EXPORT_SYMBOL(recreate_proc_ide_device);
-
 void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	ide_driver_t *driver = drive->driver;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/amd74xx.c linux-2.4.26-pre6/drivers/ide/pci/amd74xx.c
--- linux-2.4.25/drivers/ide/pci/amd74xx.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/pci/amd74xx.c	2004-03-25 00:20:18.000000000 +0000
@@ -1,7 +1,7 @@
 /*
- * Version 2.10
+ * Version 2.13
  *
- * AMD 755/756/766/8111 and nVidia nForce IDE driver for Linux.
+ * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s IDE driver for Linux.
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
  *
@@ -40,9 +40,11 @@
 #define AMD_UDMA_33		0x01
 #define AMD_UDMA_66		0x02
 #define AMD_UDMA_100		0x03
+#define AMD_UDMA_133		0x04
 #define AMD_CHECK_SWDMA		0x08
 #define AMD_BAD_SWDMA		0x10
 #define AMD_BAD_FIFO		0x20
+#define AMD_CHECK_SERENADE	0x40
 
 /*
  * AMD SouthBridge chips.
@@ -50,29 +52,32 @@
 
 static struct amd_ide_chip {
 	unsigned short id;
-	unsigned char rev;
 	unsigned long base;
 	unsigned char flags;
 } amd_ide_chips[] = {
-	{ PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },	/* AMD-755 Cobra */
-	{ PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },	/* AMD-756 Viper */
-	{ PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO },	/* AMD-766 Viper */
-	{ PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 },			/* AMD-768 Opus */
-	{ PCI_DEVICE_ID_AMD_8111_IDE,  0x00, 0x40, AMD_UDMA_100 },			/* AMD-8111 */
-        { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 },                  /* nVidia nForce */
-        { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x00, 0x50, AMD_UDMA_100 },                  /* nVidia nForce */
-
+	{ PCI_DEVICE_ID_AMD_COBRA_7401,		0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
+	{ PCI_DEVICE_ID_AMD_VIPER_7409,		0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
+	{ PCI_DEVICE_ID_AMD_VIPER_7411,		0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
+	{ PCI_DEVICE_ID_AMD_OPUS_7441,		0x40, AMD_UDMA_100 },
+	{ PCI_DEVICE_ID_AMD_8111_IDE,		0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	0x50, AMD_UDMA_100 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
 	{ 0 }
 };
 
 static struct amd_ide_chip *amd_config;
-static unsigned char amd_enabled;
+static ide_pci_device_t *amd_chipset;
 static unsigned int amd_80w;
 static unsigned int amd_clock;
 
-static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3 };
-static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 1 };
-static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" };
+static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
 
 /*
  * AMD /proc entry.
@@ -83,6 +88,7 @@ static char *amd_dma[] = { "MWDMA16", "U
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
+static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 };
 static unsigned long amd_base;
 static struct pci_dev *bmide_dev;
 extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
@@ -104,7 +110,7 @@ static int amd74xx_get_info(char *buffer
 
 	amd_print("----------AMD BusMastering IDE Configuration----------------");
 
-	amd_print("Driver Version:                     2.10");
+	amd_print("Driver Version:                     2.13");
 	amd_print("South Bridge:                       %s", bmide_dev->name);
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
@@ -155,6 +161,12 @@ static int amd74xx_get_info(char *buffer
 			continue;
 		}
 
+		if (den[i] && uen[i] && udma[i] == 15) {
+			speed[i] = amd_clock * 4;
+			cycle[i] = 500000 / amd_clock;
+			continue;
+		}
+
 		speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2);
 		cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2;
 	}
@@ -200,6 +212,7 @@ static void amd_set_speed(struct pci_dev
 		case AMD_UDMA_33:  t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
 		case AMD_UDMA_66:  t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
 		case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+		case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
 		default: return;
 	}
 
@@ -234,6 +247,7 @@ static int amd_set_drive(ide_drive_t *dr
 	}
 
 	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
+	if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
 
 	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
 
@@ -251,9 +265,6 @@ static int amd_set_drive(ide_drive_t *dr
 
 static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
 {
-	if (!((amd_enabled >> HWIF(drive)->channel) & 1))
-		return;
-
 	if (pio == 255) {
 		amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
 		return;
@@ -276,7 +287,8 @@ static int amd74xx_ide_dma_check(ide_dri
 		XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
 		((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
 		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0));
+		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
+		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
 
 	amd_set_drive(drive, speed);
 
@@ -312,13 +324,15 @@ static unsigned int __init init_chipset_
 
 	switch (amd_config->flags & AMD_UDMA) {
 
+		case AMD_UDMA_133:
 		case AMD_UDMA_100:
 			pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
 			pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
 			amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
-					printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits corectly. Enabling workaround.\n");
+					printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n",
+						amd_chipset->name);
 					amd_80w |= (1 << (1 - (i >> 4)));
 				}
 			break;
@@ -331,9 +345,6 @@ static unsigned int __init init_chipset_
 			break;
 	}
 
-	pci_read_config_dword(dev, AMD_IDE_ENABLE, &u);
-	amd_enabled = ((u & 1) ? 2 : 0) | ((u & 2) ? 1 : 0);
-
 /*
  * Take care of prefetch & postwrite.
  */
@@ -343,6 +354,15 @@ static unsigned int __init init_chipset_
 		(amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
 
 /*
+ * Take care of incorrectly wired Serenade mainboards.
+ */
+
+	if ((amd_config->flags & AMD_CHECK_SERENADE) &&
+		dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+		dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+			amd_config->flags = AMD_UDMA_100;
+
+/*
  * Determine the system bus clock.
  */
 
@@ -355,8 +375,10 @@ static unsigned int __init init_chipset_
 	}
 
 	if (amd_clock < 20000 || amd_clock > 50000) {
-		printk(KERN_WARNING "AMD_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", amd_clock);
-		printk(KERN_WARNING "AMD_IDE: Use ide0=ata66 if you want to assume 80-wire cable\n");
+		printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
+			amd_chipset->name, amd_clock);
+		printk(KERN_WARNING "%s: Use ide0=ata66 if you want to assume 80-wire cable\n",
+			amd_chipset->name);
 		amd_clock = 33333;
 	}
 
@@ -365,8 +387,8 @@ static unsigned int __init init_chipset_
  */
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-	printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n",
-		dev->name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name);
+	printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
+		amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
 
 /*
  * Register /proc/ide/amd74xx entry
@@ -381,13 +403,7 @@ static unsigned int __init init_chipset_
         }
 #endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */
 
-
-	return 0;
-}
-
-static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
-{
-	return ((amd_enabled & amd_80w) >> hwif->channel) & 1;
+	return dev->irq;
 }
 
 static void __init init_hwif_amd74xx(ide_hwif_t *hwif)
@@ -414,8 +430,8 @@ static void __init init_hwif_amd74xx(ide
         hwif->mwdma_mask = 0x07;
         hwif->swdma_mask = 0x07;
 
-        if (!(hwif->udma_four))
-                hwif->udma_four = ((amd_enabled & amd_80w) >> hwif->channel) & 1;
+	if (!hwif->udma_four)
+		hwif->udma_four = (amd_80w >> hwif->channel) & 1;
         hwif->ide_dma_check = &amd74xx_ide_dma_check;
         if (!noautodma)
                 hwif->autodma = 1;
@@ -423,37 +439,31 @@ static void __init init_hwif_amd74xx(ide
         hwif->drives[1].autodma = hwif->autodma;
 }
 
-/*
- * We allow the BM-DMA driver only work on enabled interfaces.
- */
-
-static void __init init_dma_amd74xx(ide_hwif_t *hwif, unsigned long dmabase)
-{
-	if ((amd_enabled >> hwif->channel) & 1)
-		ide_setup_dma(hwif, dmabase, 8);
-}
-
-extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
-
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	ide_pci_device_t *d = amd74xx_chipsets + id->driver_data;
+	amd_chipset = amd74xx_chipsets + id->driver_data;
 	amd_config = amd_ide_chips + id->driver_data;
-	if (dev->device != d->device) BUG();
+	if (dev->device != amd_chipset->device) BUG();
 	if (dev->device != amd_config->id) BUG();
-	ide_setup_pci_device(dev, d);
+	ide_setup_pci_device(dev, amd_chipset);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
 static struct pci_device_id amd74xx_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, 	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_COBRA_7401,		PCI_ANY_ID, PCI_ANY_ID, 0, 0,  0 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7409,		PCI_ANY_ID, PCI_ANY_ID, 0, 0,  1 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7411,		PCI_ANY_ID, PCI_ANY_ID, 0, 0,  2 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_OPUS_7441,		PCI_ANY_ID, PCI_ANY_ID, 0, 0,  3 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_8111_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0,  4 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  5 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  6 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  7 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  8 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  9 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
 	{ 0, },
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/amd74xx.h linux-2.4.26-pre6/drivers/ide/pci/amd74xx.h
--- linux-2.4.25/drivers/ide/pci/amd74xx.h	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/pci/amd74xx.h	2004-03-25 00:21:59.000000000 +0000
@@ -27,7 +27,6 @@ static ide_pci_host_proc_t amd74xx_procs
 
 static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *);
 static void init_hwif_amd74xx(ide_hwif_t *);
-static void init_dma_amd74xx(ide_hwif_t *, unsigned long);
 
 static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
 	{	/* 0 */
@@ -35,9 +34,7 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_AMD_COBRA_7401,
 		.name		= "AMD7401",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
@@ -48,9 +45,7 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_AMD_VIPER_7409,
 		.name		= "AMD7409",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
@@ -61,9 +56,7 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_AMD_VIPER_7411,
 		.name		= "AMD7411",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
@@ -74,9 +67,7 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_AMD_OPUS_7441,
 		.name		= "AMD7441",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
@@ -87,9 +78,7 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_AMD_8111_IDE,
 		.name		= "AMD8111",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.autodma	= AUTODMA,
 		.channels	= 2,
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
@@ -101,9 +90,7 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
 		.name		= "NFORCE",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
@@ -115,15 +102,79 @@ static ide_pci_device_t amd74xx_chipsets
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,
 		.name		= "NFORCE2",
 		.init_chipset	= init_chipset_amd74xx,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_amd74xx,
-		.init_dma	= init_dma_amd74xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
 		.bootable	= ON_BOARD,
 		.extra		= 0,
 	},
+	{	/* 7 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,
+		.name		= "NFORCE2S",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 8 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
+		.name		= "NFORCE2S-SATA",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 9 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,
+		.name		= "NFORCE3",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 10 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,
+		.name		= "NFORCE3S",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 11 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
+		.name		= "NFORCE3S-SATA",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 12 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
+		.name		= "NFORCE3S-SATA2",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
 	{
 		.vendor		= 0,
 		.device		= 0,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/generic.h linux-2.4.26-pre6/drivers/ide/pci/generic.h
--- linux-2.4.25/drivers/ide/pci/generic.h	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/pci/generic.h	2004-03-25 00:17:55.000000000 +0000
@@ -148,6 +148,7 @@ static ide_pci_device_t generic_chipsets
 	}
 };
 
+#if 0
 static ide_pci_device_t unknown_chipset[] __devinitdata = {
 	{	/* 0 */
 		.vendor		= 0,
@@ -170,5 +171,6 @@ static ide_pci_device_t unknown_chipset[
 	}
 
 };
+#endif
 
 #endif /* IDE_GENERIC_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/piix.c linux-2.4.26-pre6/drivers/ide/pci/piix.c
--- linux-2.4.25/drivers/ide/pci/piix.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/pci/piix.c	2004-03-25 00:22:05.000000000 +0000
@@ -153,6 +153,8 @@ static int piix_get_info (char *buffer, 
 			case PCI_DEVICE_ID_INTEL_82801DB_11:
 			case PCI_DEVICE_ID_INTEL_82801EB_11:
 			case PCI_DEVICE_ID_INTEL_82801E_11:
+			case PCI_DEVICE_ID_INTEL_ESB_2:
+			case PCI_DEVICE_ID_INTEL_ICH6_2:
 				p += sprintf(p, "PIIX4 Ultra 100 ");
 				break;
 			case PCI_DEVICE_ID_INTEL_82372FB_1:
@@ -290,6 +292,8 @@ static u8 piix_ratemask (ide_drive_t *dr
 		case PCI_DEVICE_ID_INTEL_82801DB_10:
 		case PCI_DEVICE_ID_INTEL_82801DB_11:
 		case PCI_DEVICE_ID_INTEL_82801EB_11:
+		case PCI_DEVICE_ID_INTEL_ESB_2:
+		case PCI_DEVICE_ID_INTEL_ICH6_2:
 			mode = 3;
 			break;
 		/* UDMA 66 capable */
@@ -680,6 +684,8 @@ static unsigned int __devinit init_chips
 		case PCI_DEVICE_ID_INTEL_82801DB_11:
 		case PCI_DEVICE_ID_INTEL_82801EB_11:
 		case PCI_DEVICE_ID_INTEL_82801E_11:
+		case PCI_DEVICE_ID_INTEL_ESB_2:
+		case PCI_DEVICE_ID_INTEL_ICH6_2:
 		{
 			unsigned int extra = 0;
 			pci_read_config_dword(dev, 0x54, &extra);
@@ -875,6 +881,8 @@ static struct pci_device_id piix_pci_tbl
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
  	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20},
 	{ 0, },
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/piix.h linux-2.4.26-pre6/drivers/ide/pci/piix.h
--- linux-2.4.25/drivers/ide/pci/piix.h	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/pci/piix.h	2004-03-25 00:22:12.000000000 +0000
@@ -305,6 +305,34 @@ static ide_pci_device_t piix_pci_info[] 
 		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
 		.bootable	= ON_BOARD,
 		.extra		= 0,
+	},{	/* 19 */
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_ESB_2,
+		.name		= "ICH5",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
+	},{	/* 20 */
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_ICH6_2,
+		.name		= "ICH6",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
 		.vendor		= 0,
 		.device		= 0,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/siimage.c linux-2.4.26-pre6/drivers/ide/pci/siimage.c
--- linux-2.4.25/drivers/ide/pci/siimage.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/pci/siimage.c	2004-03-25 00:21:31.000000000 +0000
@@ -62,6 +62,7 @@ static int pdev_is_sata(struct pci_dev *
 			return 0;
 	}
 	BUG();
+	return 0;
 }
  
 /**
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/raid/Makefile linux-2.4.26-pre6/drivers/ide/raid/Makefile
--- linux-2.4.25/drivers/ide/raid/Makefile	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/raid/Makefile	2004-03-25 00:21:16.000000000 +0000
@@ -12,6 +12,7 @@ export-objs := ataraid.o
 obj-$(CONFIG_BLK_DEV_ATARAID)		+= ataraid.o
 obj-$(CONFIG_BLK_DEV_ATARAID_PDC)	+= pdcraid.o
 obj-$(CONFIG_BLK_DEV_ATARAID_HPT)	+= hptraid.o
+obj-$(CONFIG_BLK_DEV_ATARAID_MEDLEY)	+= medley.o
 obj-$(CONFIG_BLK_DEV_ATARAID_SII)	+= silraid.o
 
 EXTRA_CFLAGS	:= -I../
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/raid/medley.c linux-2.4.26-pre6/drivers/ide/raid/medley.c
--- linux-2.4.25/drivers/ide/raid/medley.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ide/raid/medley.c	2004-03-25 00:17:25.000000000 +0000
@@ -0,0 +1,752 @@
+/*
+ * MEDLEY SOFTWARE RAID DRIVER (Silicon Image 3112 and others)
+ *
+ * Copyright (C) 2003 Thomas Horsten <thomas@horsten.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ * Copyright (C) 2003 Thomas Horsten <thomas@horsten.com>
+ * All Rights Reserved.
+ *
+ * This driver uses the ATA RAID driver framework and is based on
+ * code from Arjan van de Ven's silraid.c and hptraid.c.
+ *
+ * It is a driver for the Medley software RAID, which is used by
+ * some IDE controllers, including the Silicon Image 3112 SATA
+ * controller found onboard many modern motherboards, and the
+ * CMD680 stand-alone PCI RAID controller.
+ *
+ * The author has only tested this on the Silicon Image SiI3112.
+ * If you have any luck using more than 2 drives, and/or more
+ * than one RAID set, and/or any other chip than the SiI3112,
+ * please let me know by sending me mail at the above address.
+ *
+ * Currently, only striped mode is supported for these RAIDs.
+ *
+ * You are welcome to contact me if you have any questions or
+ * suggestions for improvement.
+ *
+ * Change history:
+ *
+ * 20040310 - thomas@horsten.com
+ *   Removed C99 style variable declarations that confused gcc-2.x
+ *   Fixed a bug where more than one RAID set would not be detected correctly
+ *   General cleanup for submission to kernel
+ *
+ * 20031012 - thomas@horsten.com
+ *   Added support for BLKRRPART ioctl to re-read partition table
+ *
+ * 20030801 - thomas@horsten.com
+ *   First test release
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/blkdev.h>
+#include <linux/blkpg.h>
+#include <linux/genhd.h>
+#include <linux/ioctl.h>
+
+#include <linux/ide.h>
+#include <asm/uaccess.h>
+
+#include "ataraid.h"
+
+/*
+ * These options can be tuned if the need should occur.
+ *
+ * Even better, this driver could be changed to allocate the structures
+ * dynamically.
+ */
+#define MAX_DRIVES_PER_SET 8
+#define MAX_MEDLEY_ARRAYS 4
+
+/*
+ * Set to 1 only if you are debugging the driver, or if it doesn't work
+ * the way you expect and you want to to report it.
+ *
+ * This will produce lots of kernel messages, some of which might
+ * help me figure out what is going wrong).
+ */
+#define DEBUGGING_MEDLEY 0
+
+#if DEBUGGING_MEDLEY
+#define dprintk(fmt, args...) printk(fmt, ##args)
+#else
+#define dprintk(fmt, args...)
+#endif
+
+/*
+ * Medley RAID metadata structure.
+ *
+ * The metadata structure is based on the ATA drive ID from the drive itself,
+ * with the RAID information in the vendor specific regions.
+ *
+ * We do not use all the fields, since we only support Striped Sets.
+ */
+struct medley_metadata {
+	u8  driveid0[46];
+	u8  ascii_version[8];
+	u8  driveid1[52];
+	u32 total_sectors_low;
+	u32 total_sectors_high;
+	u16 reserved0;
+	u8  driveid2[142];
+	u16 product_id;
+	u16 vendor_id;
+	u16 minor_ver;
+	u16 major_ver;
+	u16 creation_timestamp[3];
+	u16 chunk_size;
+	u16 reserved1;
+	u8  drive_number;
+	u8  raid_type;
+	u8  drives_per_striped_set;
+	u8  striped_set_number;
+	u8  drives_per_mirrored_set;
+	u8  mirrored_set_number;
+	u32 rebuild_ptr_low;
+	u32 rebuild_ptr_high;
+	u32 incarnation_no;
+	u8  member_status;
+	u8  mirrored_set_state;
+	u8  reported_device_location;
+	u8  member_location;
+	u8  auto_rebuild;
+	u8  reserved3[17];
+	u16 checksum;
+};
+
+/*
+ * This struct holds the information about a Medley array
+ */
+struct medley_array {
+	u8       drives;
+	u16      chunk_size;
+	u32      sectors_per_row;
+	u8       chunk_size_log;
+	u16      present;
+	u16      timestamp[3];
+	u32      sectors;
+	int      registered;
+	atomic_t valid;
+	int      access;
+
+	kdev_t   members[MAX_DRIVES_PER_SET];
+	struct   block_device *bdev[MAX_DRIVES_PER_SET];
+};
+
+static struct medley_array raid[MAX_MEDLEY_ARRAYS];
+
+/*
+ * Here we keep the offset of the ATARAID device ID's compared to our
+ * own (this will normally be 0, unless another ATARAID driver has
+ * registered some arrays before us).
+ */
+static int medley_devid_offset = 0;
+
+/*
+ * This holds the number of detected arrays.
+ */
+static int medley_arrays = 0;
+
+/*
+ * Wait queue for opening device (used when re-reading partition table)
+ */
+static DECLARE_WAIT_QUEUE_HEAD(medley_wait_open);
+
+/*
+ * The interface functions used by the ataraid framework.
+ */
+static int medley_open(struct inode *inode, struct file *filp);
+static int medley_release(struct inode *inode, struct file *filp);
+static int medley_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg);
+static int medley_make_request(request_queue_t * q, int rw,
+			       struct buffer_head *bh);
+
+static struct raid_device_operations medley_ops = {
+	open:         medley_open,
+	release:      medley_release,
+	ioctl:        medley_ioctl,
+	make_request: medley_make_request
+};
+
+/*
+ * This is the list of devices to probe.
+ */
+static const kdev_t probelist[] = {
+	MKDEV(IDE0_MAJOR, 0),
+	MKDEV(IDE0_MAJOR, 64),
+	MKDEV(IDE1_MAJOR, 0),
+	MKDEV(IDE1_MAJOR, 64),
+	MKDEV(IDE2_MAJOR, 0),
+	MKDEV(IDE2_MAJOR, 64),
+	MKDEV(IDE3_MAJOR, 0),
+	MKDEV(IDE3_MAJOR, 64),
+	MKDEV(IDE4_MAJOR, 0),
+	MKDEV(IDE4_MAJOR, 64),
+	MKDEV(IDE5_MAJOR, 0),
+	MKDEV(IDE5_MAJOR, 64),
+	MKDEV(IDE6_MAJOR, 0),
+	MKDEV(IDE6_MAJOR, 64),
+	MKDEV(0, 0)
+};
+
+/*
+ * Handler for ioctl calls to the virtual device
+ */
+static int medley_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	unsigned int minor;
+	unsigned long sectors;
+	int devminor = (inode->i_rdev >> SHIFT) & MAJOR_MASK;
+	int device = devminor - medley_devid_offset;
+	int partition;
+
+	dprintk("medley_ioctl\n");
+
+	minor = MINOR(inode->i_rdev) >> SHIFT;
+
+	switch (cmd) {
+
+	case BLKGETSIZE:	/* Return device size */
+		if (!arg)
+			return -EINVAL;
+		sectors =
+		    ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects;
+		dprintk("medley_ioctl: BLKGETSIZE\n");
+		if (MINOR(inode->i_rdev) & 15)
+			return put_user(sectors, (unsigned long *) arg);
+		return put_user(raid[minor - medley_devid_offset].sectors,
+				(unsigned long *) arg);
+		break;
+
+	case HDIO_GETGEO: {
+			struct hd_geometry *loc =
+			    (struct hd_geometry *) arg;
+			unsigned short bios_cyl = (unsigned short)
+			    (raid[minor].sectors / 255 / 63);	/* truncate */
+
+			dprintk("medley_ioctl: HDIO_GETGEO\n");
+			if (!loc)
+				return -EINVAL;
+			if (put_user(255, (byte *) & loc->heads))
+				return -EFAULT;
+			if (put_user(63, (byte *) & loc->sectors))
+				return -EFAULT;
+			if (put_user
+			    (bios_cyl, (unsigned short *) &loc->cylinders))
+				return -EFAULT;
+			if (put_user
+			    ((unsigned) ataraid_gendisk.
+			     part[MINOR(inode->i_rdev)].start_sect,
+			     (unsigned long *) &loc->start))
+				return -EFAULT;
+			return 0;
+		}
+
+	case HDIO_GETGEO_BIG: {
+			struct hd_big_geometry *loc =
+			    (struct hd_big_geometry *) arg;
+
+			dprintk("medley_ioctl: HDIO_GETGEO_BIG\n");
+			if (!loc)
+				return -EINVAL;
+			if (put_user(255, (byte *) & loc->heads))
+				return -EFAULT;
+			if (put_user(63, (byte *) & loc->sectors))
+				return -EFAULT;
+			if (put_user
+			    (raid[minor - medley_devid_offset].sectors /
+			     255 / 63, (unsigned int *) &loc->cylinders))
+				return -EFAULT;
+			if (put_user
+			    ((unsigned) ataraid_gendisk.
+			     part[MINOR(inode->i_rdev)].start_sect,
+			     (unsigned long *) &loc->start))
+				return -EFAULT;
+			return 0;
+		}
+
+	case BLKROSET:
+	case BLKROGET:
+	case BLKSSZGET:
+		dprintk("medley_ioctl: BLK*\n");
+		return blk_ioctl(inode->i_rdev, cmd, arg);
+
+	case BLKRRPART:	/* Re-read partition tables */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
+		if (minor != 0)
+			return -EINVAL;
+		if (atomic_read(&(raid[device].valid)) == 0)
+			return -EINVAL;
+
+		atomic_set(&(raid[device].valid), 0);
+		if (raid[device].access != 1) {
+			atomic_set(&(raid[device].valid), 1);
+			return -EBUSY;
+		}
+
+		for (partition = 15; partition >= 0; partition--) {
+			invalidate_device(MKDEV(ATARAID_MAJOR,
+						partition + devminor), 1);
+			ataraid_gendisk.part[partition +
+					     devminor].start_sect = 0;
+			ataraid_gendisk.part[partition +
+					     devminor].nr_sects = 0;
+		}
+		ataraid_register_disk(device, raid[device].sectors);
+		atomic_set(&(raid[device].valid), 1);
+		wake_up(&medley_wait_open);
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Handler to map a request to the real device.
+ * If the request cannot be made because it spans multiple disks,
+ * we return -1, otherwise we modify the request and return 1.
+ */
+static int medley_make_request(request_queue_t * q, int rw,
+			       struct buffer_head *bh)
+{
+	u8 disk;
+	u32 rsect = bh->b_rsector;
+	int device =
+	    ((bh->b_rdev >> SHIFT) & MAJOR_MASK) - medley_devid_offset;
+	struct medley_array *r = raid + device;
+
+	/* Add the partition offset */
+	rsect = rsect + ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect;
+
+	dprintk("medley_make_request, rsect=%ul\n", rsect);
+
+	/* Detect if the request crosses a chunk barrier */
+	if (r->chunk_size_log) {
+		if (((rsect & (r->chunk_size - 1)) +
+		     (bh->b_size / 512)) > (1 << r->chunk_size_log)) {
+			return -1;
+		}
+	} else {
+		if ((rsect / r->chunk_size) !=
+		    ((rsect + (bh->b_size / 512) - 1) / r->chunk_size)) {
+			return -1;
+		}
+	}
+
+	/*
+	 * Medley arrays are simple enough, since the smallest disk decides the
+	 * number of sectors used per disk. So there is no need for the cutoff
+	 * magic found in other drivers like hptraid.
+	 */
+	if (r->chunk_size_log) {
+		/* We save some expensive operations (1 div, 1 mul, 1 mod),
+		 * if the chunk size is a power of 2, which is true in most
+		 * cases (at least with my version of the RAID BIOS).
+		 */
+		disk = (rsect >> r->chunk_size_log) % r->drives;
+		rsect = ((rsect / r->sectors_per_row) <<
+			 r->chunk_size_log) + (rsect & (r->chunk_size -
+							1));
+	} else {
+		disk = (rsect / r->chunk_size) % r->drives;
+		rsect = rsect / r->sectors_per_row * r->chunk_size +
+		    rsect % r->chunk_size;
+	}
+
+	dprintk("medley_make_request :-), disk=%d, rsect=%ul\n", disk,
+		rsect);
+	bh->b_rdev = r->members[disk];
+	bh->b_rsector = rsect;
+	return 1;
+}
+
+/*
+ * Find out which array a drive belongs to, and add it to that array.
+ * If it is not a member of a detected array, add a new array for it.
+ */
+void medley_add_raiddrive(kdev_t dev, struct medley_metadata *md)
+{
+	int c;
+
+	dprintk("Candidate drive %02x:%02x - drive %d of %d, stride %d, "
+		"sectors %ul (%d MB)\n",
+		MAJOR(dev), MINOR(dev), md->drive_number,
+		md->drives_per_striped_set, md->chunk_size,
+		md->total_sectors_low,
+		md->total_sectors_low / 1024 / 1024 / 2);
+
+	for (c = 0; c < medley_arrays; c++) {
+		if ((raid[c].timestamp[0] == md->creation_timestamp[0]) &&
+		    (raid[c].timestamp[1] == md->creation_timestamp[1]) &&
+		    (raid[c].timestamp[2] == md->creation_timestamp[2]) &&
+		    (raid[c].drives == md->drives_per_striped_set) &&
+		    (raid[c].chunk_size == md->chunk_size) &&
+		    ((raid[c].present & (1 << md->drive_number)) == 0)) {
+			dprintk("Existing array %d\n", c);
+			raid[c].present |= (1 << md->drive_number);
+			raid[c].members[md->drive_number] = dev;
+			break;
+		}
+	}
+	if (c == medley_arrays) {
+		dprintk("New array %d\n", medley_arrays);
+		if (medley_arrays == MAX_MEDLEY_ARRAYS) {
+			printk(KERN_ERR "Medley RAID: "
+			       "Too many RAID sets detected - you can change "
+			       "the max in the driver.\n");
+		} else {
+			raid[c].timestamp[0] = md->creation_timestamp[0];
+			raid[c].timestamp[1] = md->creation_timestamp[1];
+			raid[c].timestamp[2] = md->creation_timestamp[2];
+			raid[c].drives = md->drives_per_striped_set;
+			raid[c].chunk_size = md->chunk_size;
+			raid[c].sectors_per_row = md->chunk_size *
+			    md->drives_per_striped_set;
+
+			/* Speedup if chunk size is a power of 2 */
+			if (((raid[c].chunk_size - 1) &
+			     (raid[c].chunk_size)) == 0) {
+				raid[c].chunk_size_log =
+				    ffs(raid[c].chunk_size) - 1;
+			} else {
+				raid[c].chunk_size_log = 0;
+			}
+			raid[c].present = (1 << md->drive_number);
+			raid[c].members[md->drive_number] = dev;
+			if (md->major_ver == 1) {
+				raid[c].sectors = ((u32 *) (md))[27];
+			} else {
+				raid[c].sectors = md->total_sectors_low;
+			}
+			medley_arrays++;
+		}
+	}
+}
+
+/*
+ * Read the Medley metadata from a drive.
+ * Returns the bh if it was found, otherwise NULL.
+ */
+struct buffer_head *medley_get_metadata(kdev_t dev)
+{
+	struct buffer_head *bh = NULL;
+	struct pci_dev *pcidev;
+	u32 lba;
+	int pos;
+	struct medley_metadata *md;
+
+	ide_drive_t *drvinfo = ide_info_ptr(dev, 0);
+	if ((drvinfo == NULL) || drvinfo->capacity < 1) {
+		return NULL;
+	}
+
+	dprintk("Probing %02x:%02x\n", MAJOR(dev), MINOR(dev));
+
+	/* If this drive is not on a PCI controller, it is not Medley RAID.
+	 * Medley matches the PCI device ID with the metadata to check if
+	 * it is valid. Unfortunately it is the only reliable way to identify
+	 * the superblock */
+	pcidev = drvinfo->hwif ? drvinfo->hwif->pci_dev : NULL;
+	if (!pcidev) {
+		return NULL;
+	}
+
+	/*
+	 * 4 copies of the metadata exist, in the following 4 sectors:
+	 * last, last-0x200, last-0x400, last-0x600.
+	 *
+	 * We must try each of these in order, until we find the metadata.
+	 * FIXME: This does not take into account drives with 48/64-bit LBA
+	 * addressing, even though the Medley RAID version 2 supports these.
+	 */
+	lba = drvinfo->capacity - 1;
+	for (pos = 0; pos < 4; pos++, lba -= 0x200) {
+		bh = bread(dev, lba, 512);
+		if (!bh) {
+			printk(KERN_ERR "Medley RAID (%02x:%02x): "
+			       "Error reading metadata (lba=%d)\n",
+			       MAJOR(dev), MINOR(dev), lba);
+			break;
+		}
+
+		/* A valid Medley RAID has the PCI vendor/device ID of its
+		 * IDE controller, and the correct checksum. */
+		md = (void *) (bh->b_data);
+
+		if (pcidev->vendor == md->vendor_id &&
+		    pcidev->device == md->product_id) {
+			u16 checksum = 0;
+			u16 *p = (void *) (bh->b_data);
+			int c;
+			for (c = 0; c < 160; c++) {
+				checksum += *p++;
+			}
+			dprintk
+			    ("Probing %02x:%02x csum=%d, major_ver=%d\n",
+			     MAJOR(dev), MINOR(dev), checksum,
+			     md->major_ver);
+			if (((checksum == 0xffff) && (md->major_ver == 1))
+			    || (checksum == 0)) {
+				dprintk("Probing %02x:%02x VALID\n",
+					MAJOR(dev), MINOR(dev));
+				break;
+			}
+		}
+		/* Was not a valid superblock */
+		if (bh) {
+			brelse(bh);
+			bh = NULL;
+		}
+	}
+	return bh;
+}
+
+/*
+ * Determine if this drive belongs to a Medley array.
+ */
+static void medley_probe_drive(int major, int minor)
+{
+	struct buffer_head *bh;
+	kdev_t dev = MKDEV(major, minor);
+	struct medley_metadata *md;
+
+	bh = medley_get_metadata(dev);
+	if (!bh)
+		return;
+
+	md = (void *) (bh->b_data);
+
+	if (md->raid_type != 0x0) {
+		printk(KERN_INFO "Medley RAID (%02x:%02x): "
+		       "Sorry, this driver currently only supports "
+		       "striped sets (RAID level 0).\n", major, minor);
+	} else if (md->major_ver == 2 && md->total_sectors_high != 0) {
+		printk(KERN_ERR "Medley RAID (%02x:%02x):"
+		       "Sorry, the driver only supports 32 bit LBA disks "
+		       "(disk too big).\n", major, minor);
+	} else if (md->major_ver > 0 && md->major_ver > 2) {
+		printk(KERN_INFO "Medley RAID (%02x:%02x): "
+		       "Unsupported version (%d.%d) - this driver supports "
+		       "Medley version 1.x and 2.x\n",
+		       major, minor, md->major_ver, md->minor_ver);
+	} else if (md->drives_per_striped_set > MAX_DRIVES_PER_SET) {
+		printk(KERN_ERR "Medley RAID (%02x:%02x): "
+		       "Striped set too large (%d drives) - please report "
+		       "this (and change max in driver).\n",
+		       major, minor, md->drives_per_striped_set);
+	} else if ((md->drive_number > md->drives_per_striped_set) ||
+		   (md->drives_per_striped_set < 1) ||
+		   (md->chunk_size < 1)) {
+		printk(KERN_ERR "Medley RAID (%02x:%02x): "
+		       "Metadata appears to be corrupt.\n", major, minor);
+	} else {
+		/* We have a good candidate, put it in the correct array */
+		medley_add_raiddrive(dev, md);
+	}
+
+	if (bh) {
+		brelse(bh);
+	}
+}
+
+
+/*
+ * Taken from hptraid.c, this is called to prevent the device
+ * from disappearing from under us and also nullifies the (incorrect)
+ * partitions of the underlying disk.
+ */
+struct block_device *get_device_lock(kdev_t member)
+{
+	struct block_device *bdev = bdget(member);
+	struct gendisk *gd;
+	int minor = MINOR(member);
+	int j;
+
+	if (bdev
+	    && blkdev_get(bdev, FMODE_READ | FMODE_WRITE, 0,
+			  BDEV_RAW) == 0) {
+		/*
+		 * This is supposed to prevent others from
+		 * stealing our underlying disks. Now blank
+		 * the /proc/partitions table for the wrong
+		 * partition table, so that scripts don't
+		 * accidentally mount it and crash the kernel
+		 */
+		/* XXX: the 0 is an utter hack  --hch */
+		gd = get_gendisk(MKDEV(MAJOR(member), 0));
+		if (gd != NULL) {
+			if (gd->major == MAJOR(member)) {
+				for (j = 1 + (minor << gd->minor_shift);
+				     j < ((minor + 1) << gd->minor_shift);
+				     j++)
+					gd->part[j].nr_sects = 0;
+			}
+		}
+	}
+	return bdev;
+}
+
+/*
+ * Initialise the driver.
+ */
+static __init int medley_init(void)
+{
+	int c, d;
+
+	memset(raid, 0, MAX_MEDLEY_ARRAYS * sizeof(struct medley_array));
+
+	/* Probe each of the drives on our list */
+	for (c = 0; probelist[c] != MKDEV(0, 0); c++) {
+		medley_probe_drive(MAJOR(probelist[c]),
+				   MINOR(probelist[c]));
+	}
+
+	/* Check if the detected sets are complete */
+	for (c = 0; c < medley_arrays; c++) {
+		if (raid[c].present != (1 << raid[c].drives) - 1) {
+			printk(KERN_ERR "Medley RAID: "
+			       "Incomplete RAID set deleted - disks:");
+			for (d = 0; c < raid[c].drives; c++) {
+				if (raid[c].present & (1 << d)) {
+					printk(" %02x:%02x",
+					       MAJOR(raid[c].members[d]),
+					       MINOR(raid[c].members[d]));
+				}
+			}
+			printk("\n");
+			if (c + 1 < medley_arrays) {
+				memmove(raid + c + 1, raid + c,
+					(medley_arrays - c -
+					 1) * sizeof(struct medley_array));
+			}
+			medley_arrays--;
+		}
+	}
+
+	/* Register any remaining array(s) */
+	for (c = 0; c < medley_arrays; c++) {
+		int device = ataraid_get_device(&medley_ops);
+		if (device < 0) {
+			printk(KERN_ERR "Medley RAID: "
+			       "Could not get ATARAID device.\n");
+			break;
+		}
+		if (c == 0) {
+			/* First array, compute offset to our device ID's */
+			medley_devid_offset = device;
+			dprintk("Medley_devid_offset: %d\n",
+				medley_devid_offset);
+		} else if (device - medley_devid_offset != c) {
+			printk(KERN_ERR "Medley RAID: "
+			       "ATARAID gave us an illegal device ID.\n");
+			ataraid_release_device(device);
+			break;
+		}
+
+		printk(KERN_INFO "Medley RAID: "
+		       "Striped set %d consists of %d disks, total %dMiB "
+		       "- disks:",
+		       c, raid[c].drives,
+		       raid[c].sectors / 1024 / 1024 / 2);
+		for (d = 0; d < raid[c].drives; d++) {
+			printk(" %02x:%02x", MAJOR(raid[c].members[d]),
+			       MINOR(raid[c].members[d]));
+			raid[c].bdev[d] = get_device_lock(raid[c].members[d]);
+		}
+		printk("\n");
+		raid[c].registered = 1;
+		atomic_set(&(raid[c].valid), 1);
+		ataraid_register_disk(c, raid[c].sectors);
+	}
+
+	if (medley_arrays > 0) {
+		printk(KERN_INFO "Medley RAID: %d active RAID set%s\n",
+		       medley_arrays, medley_arrays == 1 ? "" : "s");
+		return 0;
+	}
+
+	printk(KERN_INFO "Medley RAID: No usable RAID sets found\n");
+	return -ENODEV;
+}
+
+/*
+ * Remove the arrays and clean up.
+ */
+static void __exit medley_exit(void)
+{
+	int device, d;
+	for (device = 0; device < medley_arrays; device++) {
+		for (d = 0; d < raid[device].drives; d++) {
+			if (raid[device].bdev[d]) {
+				blkdev_put(raid[device].bdev[d], BDEV_RAW);
+				raid[device].bdev[d] = NULL;
+			}
+		}
+		if (raid[device].registered) {
+			ataraid_release_device(device +
+					       medley_devid_offset);
+			raid[device].registered = 0;
+		}
+	}
+}
+
+/*
+ * Called to open the virtual device
+ */
+static int medley_open(struct inode *inode, struct file *filp)
+{
+	int device = ((inode->i_rdev >> SHIFT) & MAJOR_MASK) -
+	    medley_devid_offset;
+	dprintk("medley_open\n");
+
+	if (device < medley_arrays) {
+		while (!atomic_read(&(raid[device].valid)))
+			sleep_on(&medley_wait_open);
+		raid[device].access++;
+		MOD_INC_USE_COUNT;
+		return (0);
+	}
+	return -ENODEV;
+}
+
+/*
+ * Called to release the handle on the virtual device
+ */
+static int medley_release(struct inode *inode, struct file *filp)
+{
+	int device = ((inode->i_rdev >> SHIFT) & MAJOR_MASK) -
+	    medley_devid_offset;
+	dprintk("medley_release\n");
+	raid[device].access--;
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+module_init(medley_init);
+module_exit(medley_exit);
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ieee1394/dma.c linux-2.4.26-pre6/drivers/ieee1394/dma.c
--- linux-2.4.25/drivers/ieee1394/dma.c	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ieee1394/dma.c	2004-03-25 00:19:03.000000000 +0000
@@ -86,7 +86,7 @@ int dma_region_alloc(struct dma_region *
 	memset(dma->kvirt, 0, n_pages * PAGE_SIZE);
 
 	/* allocate scatter/gather list */
-	dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL);
+	dma->sglist = vmalloc(dma->n_pages * sizeof(struct scatterlist));
 	if (!dma->sglist) {
 		printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n");
 		goto err;
@@ -130,7 +130,7 @@ void dma_region_free(struct dma_region *
 	}
 
 	if (dma->sglist) {
-		kfree(dma->sglist);
+		vfree(dma->sglist);
 		dma->sglist = NULL;
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ieee1394/video1394.c linux-2.4.26-pre6/drivers/ieee1394/video1394.c
--- linux-2.4.25/drivers/ieee1394/video1394.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/ieee1394/video1394.c	2004-03-25 00:17:52.000000000 +0000
@@ -216,6 +216,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, 
 	d->frame_size = buf_size;
 	d->buf_size = PAGE_ALIGN(buf_size);
 	d->last_buffer = -1;
+	INIT_LIST_HEAD(&d->link);
 	init_waitqueue_head(&d->waitq);
 
 	/* Init the regions for easy cleanup */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/input/input.c linux-2.4.26-pre6/drivers/input/input.c
--- linux-2.4.25/drivers/input/input.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.26-pre6/drivers/input/input.c	2004-03-25 00:20:14.000000000 +0000
@@ -422,7 +422,7 @@ void input_unregister_minor(devfs_handle
 static int __init input_init(void)
 {
 	if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
-		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
+		printk(KERN_ERR "input: unable to register char major %d\n", INPUT_MAJOR);
 		return -EBUSY;
 	}
 	input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/isdn/avmb1/capidrv.c linux-2.4.26-pre6/drivers/isdn/avmb1/capidrv.c
--- linux-2.4.25/drivers/isdn/avmb1/capidrv.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.26-pre6/drivers/isdn/avmb1/capidrv.c	2004-03-25 00:19:30.000000000 +0000
@@ -523,13 +523,25 @@ static int capidrv_del_ack(struct capidr
 
 static void send_message(capidrv_contr * card, _cmsg * cmsg)
 {
-	struct sk_buff *skb;
-	size_t len;
+	struct sk_buff	*skb;
+	size_t		len;
+	u16		err;
+
 	capi_cmsg2message(cmsg, cmsg->buf);
 	len = CAPIMSG_LEN(cmsg->buf);
 	skb = alloc_skb(len, GFP_ATOMIC);
+	if(!skb) {
+		printk(KERN_ERR "no skb len(%d) memory\n", len);
+		return;
+	}
 	memcpy(skb_put(skb, len), cmsg->buf, len);
-	(*capifuncs->capi_put_message) (global.appid, skb);
+	err = (*capifuncs->capi_put_message) (global.appid, skb);
+	if (err) {
+		printk(KERN_WARNING "%s: capi_put_message error: %04x\n",
+			__FUNCTION__, err);
+		kfree_skb(skb);
+		return;
+	}
 	global.nsentctlpkt++;
 }
 
@@ -2188,10 +2200,10 @@ static int capidrv_delcontr(__u16 contr)
 			free_ncci(card, card->bchans[card->nbchan-1].nccip);
 		if (card->bchans[card->nbchan-1].plcip)
 			free_plci(card, card->bchans[card->nbchan-1].plcip);
-		if (card->plci_list)
-			printk(KERN_ERR "capidrv: bug in free_plci()\n");
 		card->nbchan--;
 	}
+	if (card->plci_list)
+		printk(KERN_ERR "capidrv: bug in free_plci()\n");
 	kfree(card->bchans);
 	card->bchans = 0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/isdn/avmb1/kcapi.c linux-2.4.26-pre6/drivers/isdn/avmb1/kcapi.c
--- linux-2.4.25/drivers/isdn/avmb1/kcapi.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.26-pre6/drivers/isdn/avmb1/kcapi.c	2004-03-25 00:21:27.000000000 +0000
@@ -546,7 +546,13 @@ static int notify_push(unsigned int cmd,
 static void notify_up(__u32 contr)
 {
 	struct capi_interface_user *p;
+	__u16 appl;
 
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		if (!VALID_APPLID(appl)) continue;
+		if (APPL(appl)->releasing) continue;
+		CARD(contr)->driver->register_appl(CARD(contr), appl, &APPL(appl)->rparam);
+	}
         printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
 	spin_lock(&capi_users_lock);
 	for (p = capi_users; p; p = p->next) {
@@ -714,12 +720,16 @@ static void controllercb_appl_released(s
 			nextpp = &(*pp)->next;
 		}
 	}
-	APPL(appl)->releasing--;
-	if (APPL(appl)->releasing <= 0) {
-		APPL(appl)->signal = 0;
-		APPL_MARK_FREE(appl);
-		printk(KERN_INFO "kcapi: appl %d down\n", appl);
-	}
+	if (APPL(appl)->releasing) { /* only release if the application was marked for release */
+		printk(KERN_DEBUG "kcapi: appl %d releasing(%d)\n", appl, APPL(appl)->releasing);
+		APPL(appl)->releasing--;
+		if (APPL(appl)->releasing <= 0) {
+			APPL(appl)->signal = 0;
+			APPL_MARK_FREE(appl);
+			printk(KERN_INFO "kcapi: appl %d down\n", appl);
+		}
+	} else
+		printk(KERN_WARNING "kcapi: appl %d card%d released without request\n", appl, card->cnr);
 }
 /*
  * ncci management
@@ -872,16 +882,7 @@ error:
 
 static void controllercb_ready(struct capi_ctr * card)
 {
-	__u16 appl;
-
 	card->cardstate = CARD_RUNNING;
-
-	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
-		if (!VALID_APPLID(appl)) continue;
-		if (APPL(appl)->releasing) continue;
-		card->driver->register_appl(card, appl, &APPL(appl)->rparam);
-	}
-
         printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
 		CARDNR(card), card->name);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/isdn/hisax/isurf.c linux-2.4.26-pre6/drivers/isdn/hisax/isurf.c
--- linux-2.4.25/drivers/isdn/hisax/isurf.c	2002-11-28 23:53:13.000000000 +0000
+++ linux-2.4.26-pre6/drivers/isdn/hisax/isurf.c	2004-03-25 00:20:12.000000000 +0000
@@ -235,8 +235,18 @@ setup_isurf(struct IsdnCard *card)
 				pd->prepare(pd);
 				pd->deactivate(pd);
 				pd->activate(pd);
+				/* The ISA-PnP logic apparently
+				 * expects upper limit address to be
+				 * set. Since the isa-pnp module
+				 * doesn't do this, so we have to make
+				 * up for it.
+				 */
+				isapnp_cfg_begin(pd->bus->number, pd->devfn);
+				isapnp_write_word(ISAPNP_CFG_MEM+3, 
+					pd->resource[8].end >> 8);
+				isapnp_cfg_end();
 				cs->hw.isurf.reset = pd->resource[0].start;
-				cs->hw.isurf.phymem = pd->resource[1].start;
+				cs->hw.isurf.phymem = pd->resource[8].start;
 				cs->irq = pd->irq_resource[0].start;
 				if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
 					printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/md/lvm-snap.c linux-2.4.26-pre6/drivers/md/lvm-snap.c
--- linux-2.4.25/drivers/md/lvm-snap.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/md/lvm-snap.c	2004-03-25 00:21:08.000000000 +0000
@@ -554,17 +554,15 @@ int lvm_snapshot_alloc_hash_table(lv_t *
 
 int lvm_snapshot_alloc(lv_t * lv_snap)
 {
-	int ret, max_sectors;
+	int ret;
 
 	/* allocate kiovec to do chunk io */
 	ret = alloc_kiovec(1, &lv_snap->lv_iobuf);
 	if (ret)
 		goto out;
 
-	max_sectors = KIO_MAX_SECTORS << (PAGE_SHIFT - 9);
-
-	ret =
-	    lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors);
+	ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf,
+					     KIO_MAX_SECTORS);
 	if (ret)
 		goto out_free_kiovec;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/media/video/Config.in linux-2.4.26-pre6/drivers/media/video/Config.in
--- linux-2.4.25/drivers/media/video/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/media/video/Config.in	2004-03-25 00:20:13.000000000 +0000
@@ -49,7 +49,7 @@ dep_tristate '  Iomega Buz support' CONF
 dep_tristate '  Miro DC10(+) support' CONFIG_VIDEO_ZORAN_DC10 $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
 dep_tristate '  Linux Media Labs LML33 support' CONFIG_VIDEO_ZORAN_LML33 $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
 dep_tristate '  Zoran ZR36120/36125 Video For Linux' CONFIG_VIDEO_ZR36120 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HIGHMEM64G" != "y" ]; then
   dep_tristate '  Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
 fi
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/media/video/meye.c linux-2.4.26-pre6/drivers/media/video/meye.c
--- linux-2.4.25/drivers/media/video/meye.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/media/video/meye.c	2004-03-25 00:20:26.000000000 +0000
@@ -188,23 +188,31 @@ void dma_free_coherent(struct pci_dev *d
         free_pages((unsigned long)vaddr, get_order(size));
 }
 
-/* return a page table pointing to N pages of locked memory */
+/*
+ * return a page table pointing to N pages of locked memory
+ *
+ * NOTE: The meye device expects dma_addr_t size to be 32 bits
+ * (the toc must be exactly 1024 entries each of them being 4 bytes
+ * in size, the whole result being 4096 bytes). We're using here
+ * dma_addr_t for correctness but the compilation of this driver is
+ * disabled for HIGHMEM64G=y, where sizeof(dma_addr_t) != 4
+ */
 static int ptable_alloc(void) {
-	u32 *pt;
+	dma_addr_t *pt;
 	int i;
 
 	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
 
-	meye.mchip_ptable[MCHIP_NB_PAGES] = dma_alloc_coherent(meye.mchip_dev, 
-							       PAGE_SIZE, 
-							       &meye.mchip_dmahandle,
-							       GFP_KERNEL);
-	if (!meye.mchip_ptable[MCHIP_NB_PAGES]) {
+	meye.mchip_ptable_toc = dma_alloc_coherent(meye.mchip_dev, 
+						   PAGE_SIZE, 
+						   &meye.mchip_dmahandle,
+						   GFP_KERNEL);
+	if (!meye.mchip_ptable_toc) {
 		meye.mchip_dmahandle = 0;
 		return -1;
 	}
 
-	pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
+	pt = meye.mchip_ptable_toc;
 	for (i = 0; i < MCHIP_NB_PAGES; i++) {
 		meye.mchip_ptable[i] = dma_alloc_coherent(meye.mchip_dev, 
 							  PAGE_SIZE,
@@ -212,13 +220,18 @@ static int ptable_alloc(void) {
 							  GFP_KERNEL);
 		if (!meye.mchip_ptable[i]) {
 			int j;
-			pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
+			pt = meye.mchip_ptable_toc;
 			for (j = 0; j < i; ++j) {
 				dma_free_coherent(meye.mchip_dev,
 						  PAGE_SIZE,
 						  meye.mchip_ptable[j], *pt);
 				pt++;
 			}
+			dma_free_coherent(meye.mchip_dev,
+					  PAGE_SIZE,
+					  meye.mchip_ptable_toc,
+					  meye.mchip_dmahandle);
+			meye.mchip_ptable_toc = 0;
 			meye.mchip_dmahandle = 0;
 			return -1;
 		}
@@ -228,10 +241,10 @@ static int ptable_alloc(void) {
 }
 
 static void ptable_free(void) {
-	u32 *pt;
+	dma_addr_t *pt;
 	int i;
 
-	pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
+	pt = meye.mchip_ptable_toc;
 	for (i = 0; i < MCHIP_NB_PAGES; i++) {
 		if (meye.mchip_ptable[i])
 			dma_free_coherent(meye.mchip_dev, 
@@ -240,13 +253,14 @@ static void ptable_free(void) {
 		pt++;
 	}
 
-	if (meye.mchip_ptable[MCHIP_NB_PAGES])
+	if (meye.mchip_ptable_toc)
 		dma_free_coherent(meye.mchip_dev, 
 				  PAGE_SIZE, 
-				  meye.mchip_ptable[MCHIP_NB_PAGES],
+				  meye.mchip_ptable_toc,
 				  meye.mchip_dmahandle);
 
 	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
+	meye.mchip_ptable_toc = 0;
 	meye.mchip_dmahandle = 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/media/video/meye.h linux-2.4.26-pre6/drivers/media/video/meye.h
--- linux-2.4.25/drivers/media/video/meye.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/media/video/meye.h	2004-03-25 00:20:11.000000000 +0000
@@ -31,7 +31,7 @@
 #define _MEYE_PRIV_H_
 
 #define MEYE_DRIVER_MAJORVERSION	1
-#define MEYE_DRIVER_MINORVERSION	8
+#define MEYE_DRIVER_MINORVERSION	9
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -298,7 +298,8 @@ struct meye {
 	u8 mchip_fnum;			/* current mchip frame number */
 
 	unsigned char *mchip_mmregs;	/* mchip: memory mapped registers */
-	u8 *mchip_ptable[MCHIP_NB_PAGES+1];/* mchip: ptable + ptable toc */
+	u8 *mchip_ptable[MCHIP_NB_PAGES];/* mchip: ptable */
+	dma_addr_t *mchip_ptable_toc;	/* mchip: ptable toc */
 	dma_addr_t mchip_dmahandle;	/* mchip: dma handle to ptable toc */
 
 	unsigned char *grab_fbuffer;	/* capture framebuffer */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/8139too.c linux-2.4.26-pre6/drivers/net/8139too.c
--- linux-2.4.25/drivers/net/8139too.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/8139too.c	2004-03-25 00:16:47.000000000 +0000
@@ -255,6 +255,10 @@ static struct pci_device_id rtl8139_pci_
 	{0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 
 #ifdef CONFIG_SH_SECUREEDGE5410
 	/* Bogus 8139 silicon reports 8129 without external PROM :-( */
@@ -953,12 +957,11 @@ static int __devinit rtl8139_init_one (s
 	if (i < 0)
 		return i;
 
+	assert (dev != NULL);
 	tp = dev->priv;
+	assert (tp != NULL);
 	ioaddr = tp->mmio_addr;
-
 	assert (ioaddr != NULL);
-	assert (dev != NULL);
-	assert (tp != NULL);
 
 	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
 	for (i = 0; i < 3; i++)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/Config.in linux-2.4.26-pre6/drivers/net/Config.in
--- linux-2.4.25/drivers/net/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/Config.in	2004-03-25 00:20:34.000000000 +0000
@@ -198,6 +198,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; the
       dep_tristate '    Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
       dep_tristate '    National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
       dep_tristate '    PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
+      dep_tristate '    nForce Ethernet support (EXPERIMENTAL)' CONFIG_FORCEDETH $CONFIG_PCI $CONFIG_EXPERIMENTAL
       dep_tristate '    Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
       dep_tristate '    Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
       dep_tristate '    RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_8139CP $CONFIG_PCI $CONFIG_EXPERIMENTAL
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/Makefile linux-2.4.26-pre6/drivers/net/Makefile
--- linux-2.4.25/drivers/net/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/Makefile	2004-03-25 00:18:37.000000000 +0000
@@ -154,6 +154,7 @@ obj-$(CONFIG_LNE390) += lne390.o 8390.o
 obj-$(CONFIG_NE3210) += ne3210.o 8390.o
 obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o
 obj-$(CONFIG_B44) += b44.o
+obj-$(CONFIG_FORCEDETH) += forcedeth.o
 
 obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bond_3ad.c linux-2.4.26-pre6/drivers/net/bonding/bond_3ad.c
--- linux-2.4.25/drivers/net/bonding/bond_3ad.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/bonding/bond_3ad.c	2004-03-25 00:21:50.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * 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
@@ -47,8 +47,13 @@
  *	- Send LACPDU as highest priority packet to further fix the above
  *	  problem on very high Tx traffic load where packets may get dropped
  *	  by the slave.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -119,6 +124,7 @@
 
 static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
 static u16 ad_ticks_per_sec;
+static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
 // ================= 3AD api to bonding and kernel code ==================
 static u16 __get_link_speed(struct port *port);
@@ -196,13 +202,11 @@ static inline struct bonding *__get_bond
  */
 static inline struct port *__get_first_port(struct bonding *bond)
 {
-	struct slave *slave = bond->next;
-
-	if (slave == (struct slave *)bond) {
+	if (bond->slave_cnt == 0) {
 		return NULL;
 	}
 
-	return &(SLAVE_AD_INFO(slave).port);
+	return &(SLAVE_AD_INFO(bond->first_slave).port);
 }
 
 /**
@@ -218,7 +222,7 @@ static inline struct port *__get_next_po
 	struct slave *slave = port->slave;
 
 	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->next)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave)) {
 		return NULL;
 	}
 
@@ -236,12 +240,12 @@ static inline struct aggregator *__get_f
 {
 	struct bonding *bond = __get_bond_by_port(port);
 
-	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (bond->next == (struct slave *)bond)) {
+	// If there's no bond for this port, or bond has no slaves
+	if ((bond == NULL) || (bond->slave_cnt == 0)) {
 		return NULL;
 	}
 
-	return &(SLAVE_AD_INFO(bond->next).aggregator);
+	return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
 }
 
 /**
@@ -257,7 +261,7 @@ static inline struct aggregator *__get_n
 	struct bonding *bond = bond_get_bond_by_slave(slave);
 
 	// If there's no bond for this aggregator, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->next)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave)) {
 		return NULL;
 	}
 
@@ -392,7 +396,7 @@ static u16 __get_link_speed(struct port 
 		}
 	}
 
-	BOND_PRINT_DBG(("Port %d Received link speed %d update from adapter", port->actor_port_number, speed));
+	dprintk("Port %d Received link speed %d update from adapter\n", port->actor_port_number, speed);
 	return speed;
 }
 
@@ -418,12 +422,12 @@ static u8 __get_duplex(struct port *port
 		switch (slave->duplex) {
 		case DUPLEX_FULL:
 			retval=0x1;
-			BOND_PRINT_DBG(("Port %d Received status full duplex update from adapter", port->actor_port_number));
+			dprintk("Port %d Received status full duplex update from adapter\n", port->actor_port_number);
 			break;
 		case DUPLEX_HALF:
 		default:
 			retval=0x0;
-			BOND_PRINT_DBG(("Port %d Received status NOT full duplex update from adapter", port->actor_port_number));
+			dprintk("Port %d Received status NOT full duplex update from adapter\n", port->actor_port_number);
 			break;
 		}
 	}
@@ -1059,7 +1063,7 @@ static void ad_mux_machine(struct port *
 
 	// check if the state machine was changed
 	if (port->sm_mux_state != last_state) {
-		BOND_PRINT_DBG(("Mux Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_mux_state));
+		dprintk("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state);
 		switch (port->sm_mux_state) {
 		case AD_MUX_DETACHED:
 			__detach_bond_from_agg(port);
@@ -1158,7 +1162,7 @@ static void ad_rx_machine(struct lacpdu 
 
 	// check if the State machine was changed or new lacpdu arrived
 	if ((port->sm_rx_state != last_state) || (lacpdu)) {
-		BOND_PRINT_DBG(("Rx Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_rx_state));
+		dprintk("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_rx_state);
 		switch (port->sm_rx_state) {
 		case AD_RX_INITIALIZE:
 			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
@@ -1204,7 +1208,7 @@ static void ad_rx_machine(struct lacpdu 
 			// detect loopback situation
 			if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
 				// INFO_RECEIVED_LOOPBACK_FRAMES
-				printk(KERN_ERR "bonding: An illegal loopback occurred on adapter (%s)\n",
+				printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n",
 						port->slave->dev->name);
 				printk(KERN_ERR "Check the configuration to verify that all Adapters "
 						"are connected to 802.3ad compliant switch ports\n");
@@ -1245,7 +1249,7 @@ static void ad_tx_machine(struct port *p
 			__update_lacpdu_from_port(port);
 			// send the lacpdu
 			if (ad_lacpdu_send(port) >= 0) {
-				BOND_PRINT_DBG(("Sent LACPDU on port %d", port->actor_port_number));
+				dprintk("Sent LACPDU on port %d\n", port->actor_port_number);
 				// mark ntt as false, so it will not be sent again until demanded
 				port->ntt = 0;
 			}
@@ -1318,7 +1322,7 @@ static void ad_periodic_machine(struct p
 
 	// check if the state machine was changed
 	if (port->sm_periodic_state != last_state) {
-		BOND_PRINT_DBG(("Periodic Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_periodic_state));
+		dprintk("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_periodic_state);
 		switch (port->sm_periodic_state) {
 		case AD_NO_PERIODIC:
 			port->sm_periodic_timer_counter = 0;	   // zero timer
@@ -1375,7 +1379,7 @@ static void ad_port_selection_logic(stru
 				port->next_port_in_aggregator=NULL;
 				port->actor_port_aggregator_identifier=0;
 
-				BOND_PRINT_DBG(("Port %d left LAG %d", port->actor_port_number, temp_aggregator->aggregator_identifier));
+				dprintk("Port %d left LAG %d\n", port->actor_port_number, temp_aggregator->aggregator_identifier);
 				// if the aggregator is empty, clear its parameters, and set it ready to be attached
 				if (!temp_aggregator->lag_ports) {
 					ad_clear_agg(temp_aggregator);
@@ -1384,7 +1388,7 @@ static void ad_port_selection_logic(stru
 			}
 		}
 		if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
-			printk(KERN_WARNING "bonding: Warning: Port %d (on %s) was "
+			printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was "
 			       "related to aggregator %d but was not on its port list\n",
 			       port->actor_port_number, port->slave->dev->name,
 			       port->aggregator->aggregator_identifier);
@@ -1417,7 +1421,7 @@ static void ad_port_selection_logic(stru
 			port->next_port_in_aggregator=aggregator->lag_ports;
 			port->aggregator->num_of_ports++;
 			aggregator->lag_ports=port;
-			BOND_PRINT_DBG(("Port %d joined LAG %d(existing LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+			dprintk("Port %d joined LAG %d(existing LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
@@ -1454,9 +1458,9 @@ static void ad_port_selection_logic(stru
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
 
-			BOND_PRINT_DBG(("Port %d joined LAG %d(new LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+			dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		} else {
-			printk(KERN_ERR "bonding: Port %d (on %s) did not find a suitable aggregator\n",
+			printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",
 			       port->actor_port_number, port->slave->dev->name);
 		}
 	}
@@ -1580,30 +1584,30 @@ static void ad_agg_selection_logic(struc
 		    aggregator;
 		    aggregator = __get_next_agg(aggregator)) {
 
-			BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+			dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
 					aggregator->aggregator_identifier, aggregator->num_of_ports,
 					aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key,
-					aggregator->is_individual, aggregator->is_active));
+					aggregator->is_individual, aggregator->is_active);
 		}
 
 		// check if any partner replys
 		if (best_aggregator->is_individual) {
-			printk(KERN_WARNING "bonding: Warning: No 802.3ad response from the link partner "
+			printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner "
 					"for any adapters in the bond\n");
 		}
 
 		// check if there are more than one aggregator
 		if (num_of_aggs > 1) {
-			BOND_PRINT_DBG(("Warning: More than one Link Aggregation Group was "
-					"found in the bond. Only one group will function in the bond"));
+			dprintk("Warning: More than one Link Aggregation Group was "
+				"found in the bond. Only one group will function in the bond\n");
 		}
 
 		best_aggregator->is_active = 1;
-		BOND_PRINT_DBG(("LAG %d choosed as the active LAG", best_aggregator->aggregator_identifier));
-		BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+		dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier);
+		dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
 				best_aggregator->aggregator_identifier, best_aggregator->num_of_ports,
 				best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key,
-				best_aggregator->is_individual, best_aggregator->is_active));
+				best_aggregator->is_individual, best_aggregator->is_active);
 
 		// disable the ports that were related to the former active_aggregator
 		if (last_active_aggregator) {
@@ -1644,7 +1648,7 @@ static void ad_clear_agg(struct aggregat
 		aggregator->lag_ports = NULL;
 		aggregator->is_active = 0;
 		aggregator->num_of_ports = 0;
-		BOND_PRINT_DBG(("LAG %d was cleared", aggregator->aggregator_identifier));
+		dprintk("LAG %d was cleared\n", aggregator->aggregator_identifier);
 	}
 }
 
@@ -1729,7 +1733,7 @@ static void ad_initialize_port(struct po
 static void ad_enable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator->is_active) {
-		BOND_PRINT_DBG(("Enabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		dprintk("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		__enable_port(port);
 	}
 }
@@ -1742,7 +1746,7 @@ static void ad_enable_collecting_distrib
 static void ad_disable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
-		BOND_PRINT_DBG(("Disabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		dprintk("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		__disable_port(port);
 	}
 }
@@ -1780,7 +1784,7 @@ static void ad_marker_info_send(struct p
 
 	// send the marker information
 	if (ad_marker_send(port, &marker) >= 0) {
-		BOND_PRINT_DBG(("Sent Marker Information on port %d", port->actor_port_number));
+		dprintk("Sent Marker Information on port %d\n", port->actor_port_number);
 	}
 }
 #endif
@@ -1803,7 +1807,7 @@ static void ad_marker_info_received(stru
 	// send the marker response
 
 	if (ad_marker_send(port, &marker) >= 0) {
-		BOND_PRINT_DBG(("Sent Marker Response on port %d", port->actor_port_number));
+		dprintk("Sent Marker Response on port %d\n", port->actor_port_number);
 	}
 }
 
@@ -1890,13 +1894,13 @@ static u16 aggregator_identifier;
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
 {                         
 	// check that the bond is not initialized yet
-	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->device->dev_addr))) {
+	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->dev->dev_addr))) {
 
 		aggregator_identifier = 0;
 
 		BOND_AD_INFO(bond).lacp_fast = lacp_fast;
 		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
-		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->device->dev_addr);
+		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
 
 		// initialize how many times this module is called in one second(should be about every 100ms)
 		ad_ticks_per_sec = tick_resolution;
@@ -1921,7 +1925,7 @@ int bond_3ad_bind_slave(struct slave *sl
 	struct aggregator *aggregator;
 
 	if (bond == NULL) {
-		printk(KERN_CRIT "The slave %s is not attached to its bond\n", slave->dev->name);
+		printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name);
 		return -1;
 	}
 
@@ -1964,7 +1968,7 @@ int bond_3ad_bind_slave(struct slave *sl
 
 		ad_initialize_agg(aggregator);
 
-		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->device->dev_addr);
+		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
 		aggregator->aggregator_identifier = (++aggregator_identifier);
 		aggregator->slave = slave;
 		aggregator->is_active = 0;
@@ -1996,11 +2000,11 @@ void bond_3ad_unbind_slave(struct slave 
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name);
 		return;
 	}
 
-	BOND_PRINT_DBG(("Unbinding Link Aggregation Group %d", aggregator->aggregator_identifier));
+	dprintk("Unbinding Link Aggregation Group %d\n", aggregator->aggregator_identifier);
 
 	/* Tell the partner that this port is not suitable for aggregation */
 	port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -2024,10 +2028,10 @@ void bond_3ad_unbind_slave(struct slave 
 			// if new aggregator found, copy the aggregator's parameters
 			// and connect the related lag_ports to the new aggregator
 			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
-				BOND_PRINT_DBG(("Some port(s) related to LAG %d - replaceing with LAG %d", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier));
+				dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
 
 				if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
-					printk(KERN_INFO "bonding: Removing an active aggregator\n");
+					printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n");
 					// select new active aggregator
 					 select_new_active_agg = 1;
 				}
@@ -2057,7 +2061,7 @@ void bond_3ad_unbind_slave(struct slave 
 					ad_agg_selection_logic(__get_first_agg(port));
 				}
 			} else {
-				printk(KERN_WARNING "bonding: Warning: unbinding aggregator, "
+				printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, "
 				       "and could not find a new aggregator for its ports\n");
 			}
 		} else { // in case that the only port related to this aggregator is the one we want to remove
@@ -2072,7 +2076,7 @@ void bond_3ad_unbind_slave(struct slave 
 		}
 	}
 
-	BOND_PRINT_DBG(("Unbinding port %d", port->actor_port_number));
+	dprintk("Unbinding port %d\n", port->actor_port_number);
 	// find the aggregator that this port is connected to
 	temp_aggregator = __get_first_agg(port);
 	for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
@@ -2123,13 +2127,13 @@ void bond_3ad_state_machine_handler(stru
 
 	read_lock(&bond->lock);
 
-	//check if there are any slaves
-	if (bond->next == (struct slave *)bond) {
-		goto end;
+	if (bond->kill_timers) {
+		goto out;
 	}
 
-	if ((bond->device->flags & IFF_UP) != IFF_UP) {
-		goto end;
+	//check if there are any slaves
+	if (bond->slave_cnt == 0) {
+		goto re_arm;
 	}
 
 	// check if agg_select_timer timer after initialize is timed out
@@ -2137,8 +2141,8 @@ void bond_3ad_state_machine_handler(stru
 		// select the active aggregator for the bond
 		if ((port = __get_first_port(bond))) {
 			if (!port->slave) {
-				printk(KERN_WARNING "bonding: Warning: bond's first port is uninitialized\n");
-				goto end;
+				printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n");
+				goto re_arm;
 			}
 
 			aggregator = __get_first_agg(port);
@@ -2149,8 +2153,8 @@ void bond_3ad_state_machine_handler(stru
 	// for each port run the state machines
 	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
 		if (!port->slave) {
-			printk(KERN_WARNING "bonding: Warning: Found an uninitialized port\n");
-			goto end;
+			printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n");
+			goto re_arm;
 		}
 
 		ad_rx_machine(NULL, port);
@@ -2165,14 +2169,10 @@ void bond_3ad_state_machine_handler(stru
 		}
 	}
 
-end:
+re_arm:
+	mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + ad_delta_in_ticks);
+out:
 	read_unlock(&bond->lock);
-
-
-	if ((bond->device->flags & IFF_UP) == IFF_UP) {
-		/* re-arm the timer */
-		mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + (AD_TIMER_INTERVAL * HZ / 1000));
-	}
 }
 
 /**
@@ -2194,14 +2194,14 @@ void bond_3ad_rx_indication(struct lacpd
 		port = &(SLAVE_AD_INFO(slave).port);
 
 		if (!port->slave) {
-			printk(KERN_WARNING "bonding: Warning: port of slave %s is uninitialized\n", slave->dev->name);
+			printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name);
 			return;
 		}
 
 		switch (lacpdu->subtype) {
 		case AD_TYPE_LACPDU:
 			__ntohs_lacpdu(lacpdu);
-			BOND_PRINT_DBG(("Received LACPDU on port %d", port->actor_port_number));
+			dprintk("Received LACPDU on port %d\n", port->actor_port_number);
 			ad_rx_machine(lacpdu, port);
 			break;
 
@@ -2210,17 +2210,17 @@ void bond_3ad_rx_indication(struct lacpd
 
 			switch (((struct marker *)lacpdu)->tlv_type) {
 			case AD_MARKER_INFORMATION_SUBTYPE:
-				BOND_PRINT_DBG(("Received Marker Information on port %d", port->actor_port_number));
+				dprintk("Received Marker Information on port %d\n", port->actor_port_number);
 				ad_marker_info_received((struct marker *)lacpdu, port);
 				break;
 
 			case AD_MARKER_RESPONSE_SUBTYPE:
-				BOND_PRINT_DBG(("Received Marker Response on port %d", port->actor_port_number));
+				dprintk("Received Marker Response on port %d\n", port->actor_port_number);
 				ad_marker_response_received((struct marker *)lacpdu, port);
 				break;
 
 			default:
-				BOND_PRINT_DBG(("Received an unknown Marker subtype on slot %d", port->actor_port_number));
+				dprintk("Received an unknown Marker subtype on slot %d\n", port->actor_port_number);
 			}
 		}
 	}
@@ -2240,14 +2240,14 @@ void bond_3ad_adapter_speed_changed(stru
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Warning: speed changed for uninitialized port on %s\n",
+		printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n",
 		       slave->dev->name);
 		return;
 	}
 
 	port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
 	port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
-	BOND_PRINT_DBG(("Port %d changed speed", port->actor_port_number));
+	dprintk("Port %d changed speed\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
 	port->sm_vars |= AD_PORT_BEGIN;
@@ -2267,14 +2267,14 @@ void bond_3ad_adapter_duplex_changed(str
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Warning: duplex changed for uninitialized port on %s\n",
+		printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n",
 		       slave->dev->name);
 		return;
 	}
 
 	port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
 	port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
-	BOND_PRINT_DBG(("Port %d changed duplex", port->actor_port_number));
+	dprintk("Port %d changed duplex\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
 	port->sm_vars |= AD_PORT_BEGIN;
@@ -2295,10 +2295,8 @@ void bond_3ad_handle_link_change(struct 
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-#ifdef BONDING_DEBUG
-		printk(KERN_WARNING "bonding: Warning: link status changed for uninitialized port on %s\n",
-		       slave->dev->name);
-#endif
+		printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n",
+			slave->dev->name);
 		return;
 	}
 
@@ -2356,41 +2354,28 @@ int bond_3ad_get_active_agg_info(struct 
 
 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 {
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
+	struct slave *slave, *start_at;
+	struct bonding *bond = dev->priv;
 	struct ethhdr *data = (struct ethhdr *)skb->data;
 	int slave_agg_no;
 	int slaves_in_agg;
 	int agg_id;
+	int i;
 	struct ad_info ad_info;
+	int res = 1;
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	if (bond == NULL) {
-		printk(KERN_CRIT "bonding: Error: bond is NULL on device %s\n", dev->name);
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
+	/* make sure that the slaves list will
+	 * not change during tx
+	 */
 	read_lock(&bond->lock);
-	slave = bond->prev;
 
-	/* check if bond is empty */
-	if ((slave == (struct slave *) bond) || (bond->slave_cnt == 0)) {
-		printk(KERN_DEBUG "ERROR: bond is empty\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		goto out;
 	}
 
 	slaves_in_agg = ad_info.ports;
@@ -2399,21 +2384,12 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
 		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		goto out;
 	}
 
-	/* we're at the root, get the first slave */
-	if ((slave == NULL) || (slave->dev == NULL)) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
-	}
+	slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg;
 
-	slave_agg_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % slaves_in_agg;
-	while (slave != (slave_t *)bond) {
+	bond_for_each_slave(bond, slave, i) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg && (agg->aggregator_identifier == agg_id)) {
@@ -2422,61 +2398,41 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 				break;
 			}
 		}
-
-		slave = slave->prev;
-		if (slave == NULL) {
-			printk(KERN_ERR "bonding: Error: slave is NULL\n");
-			dev_kfree_skb(skb);
-			read_unlock(&bond->lock);
-			return 0;
-		}
 	}
 
-	if (slave == (slave_t *)bond) {
-		printk(KERN_ERR "bonding: Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (slave_agg_no >= 0) {
+		printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+		goto out;
 	}
 
 	start_at = slave;
 
-	do {
+	bond_for_each_slave_from(bond, slave, i, start_at) {
 		int slave_agg_id = 0;
-		struct aggregator *agg;
-
-		if (slave == NULL) {
-			printk(KERN_ERR "bonding: Error: slave is NULL\n");
-			dev_kfree_skb(skb);
-			read_unlock(&bond->lock);
-			return 0;
-		}
-
-		agg = SLAVE_AD_INFO(slave).port.aggregator;
+		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg) {
 			slave_agg_id = agg->aggregator_identifier;
 		}
 
-		if (SLAVE_IS_OK(slave) && 
-		    agg && (slave_agg_id == agg_id)) {
-			skb->dev = slave->dev;			
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-			read_unlock(&bond->lock);
-			return 0;
+		if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
-	} while ((slave = slave->next) != start_at);
+	}
 
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
 }
 
 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
 {
-	struct bonding *bond = (struct bonding *)dev->priv;
+	struct bonding *bond = dev->priv;
 	struct slave *slave = NULL;
 	int ret = NET_RX_DROP;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bond_3ad.h linux-2.4.26-pre6/drivers/net/bonding/bond_3ad.h
--- linux-2.4.25/drivers/net/bonding/bond_3ad.h	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/bonding/bond_3ad.h	2004-03-25 00:19:26.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * 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
@@ -28,6 +28,9 @@
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Renamed bond_3ad_link_status_changed() to
  *	  bond_3ad_handle_link_change() for compatibility with TLB.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef __BOND_3AD_H__
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bond_alb.c linux-2.4.26-pre6/drivers/net/bonding/bond_alb.c
--- linux-2.4.25/drivers/net/bonding/bond_alb.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/bonding/bond_alb.c	2004-03-25 00:18:52.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * 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
@@ -28,8 +28,19 @@
  * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Add capability to tag self generated packets in ALB/TLB modes.
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -42,6 +53,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_bonding.h>
+#include <linux/if_vlan.h>
 #include <net/ipx.h>
 #include <net/arp.h>
 #include <asm/byteorder.h>
@@ -50,11 +62,11 @@
 
 
 #define ALB_TIMER_TICKS_PER_SEC	    10	/* should be a divisor of HZ */
-#define BOND_TLB_REBALANCE_INTERVAL 10	/* in seconds, periodic re-balancing
-					 * used for division - never set
+#define BOND_TLB_REBALANCE_INTERVAL 10	/* In seconds, periodic re-balancing.
+					 * Used for division - never set
 					 * to zero !!!
 					 */
-#define BOND_ALB_LP_INTERVAL	    1	/* in seconds periodic send of
+#define BOND_ALB_LP_INTERVAL	    1	/* In seconds, periodic send of
 					 * learning packets to the switch
 					 */
 
@@ -66,12 +78,12 @@
 
 #define TLB_HASH_TABLE_SIZE 256	/* The size of the clients hash table.
 				 * Note that this value MUST NOT be smaller
-				 * because the key hash table BYTE wide !
+				 * because the key hash table is BYTE wide !
 				 */
 
 
 #define TLB_NULL_INDEX		0xffffffff
-#define MAX_LP_RETRY		3
+#define MAX_LP_BURST		3
 
 /* rlb defs */
 #define RLB_HASH_TABLE_SIZE	256
@@ -86,12 +98,15 @@
  */
 #define RLB_PROMISC_TIMEOUT	10*ALB_TIMER_TICKS_PER_SEC
 
+static const u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+static const int alb_delta_in_ticks = HZ / ALB_TIMER_TICKS_PER_SEC;
+
 #pragma pack(1)
 struct learning_pkt {
 	u8 mac_dst[ETH_ALEN];
 	u8 mac_src[ETH_ALEN];
 	u16 type;
-	u8 padding[ETH_ZLEN - (2*ETH_ALEN + 2)];
+	u8 padding[ETH_ZLEN - ETH_HLEN];
 };
 
 struct arp_pkt {
@@ -110,13 +125,12 @@ struct arp_pkt {
 /* Forward declaration */
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
 
-static inline u8
-_simple_hash(u8 *hash_start, int hash_size)
+static inline u8 _simple_hash(u8 *hash_start, int hash_size)
 {
 	int i;
 	u8 hash = 0;
 
-	for (i=0; i<hash_size; i++) {
+	for (i = 0; i < hash_size; i++) {
 		hash ^= hash_start[i];
 	}
 
@@ -125,193 +139,151 @@ _simple_hash(u8 *hash_start, int hash_si
 
 /*********************** tlb specific functions ***************************/
 
-static inline void
-_lock_tx_hashtbl(struct bonding *bond)
+static inline void _lock_tx_hashtbl(struct bonding *bond)
 {
 	spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
 }
 
-static inline void
-_unlock_tx_hashtbl(struct bonding *bond)
+static inline void _unlock_tx_hashtbl(struct bonding *bond)
 {
 	spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
 }
 
 /* Caller must hold tx_hashtbl lock */
-static inline void
-tlb_init_table_entry(struct bonding *bond, u8 index, u8 save_load)
+static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
 {
-	struct tlb_client_info *entry;
-
-	if (BOND_ALB_INFO(bond).tx_hashtbl == NULL) {
-		return;
-	}
-
-	entry = &(BOND_ALB_INFO(bond).tx_hashtbl[index]);
-	/* at end of cycle, save the load that was transmitted to the client
-	 * during the cycle, and set the tx_bytes counter to 0 for counting
-	 * the load during the next cycle
-	 */
 	if (save_load) {
 		entry->load_history = 1 + entry->tx_bytes /
-			BOND_TLB_REBALANCE_INTERVAL;
+				      BOND_TLB_REBALANCE_INTERVAL;
 		entry->tx_bytes = 0;
 	}
+
 	entry->tx_slave = NULL;
 	entry->next = TLB_NULL_INDEX;
 	entry->prev = TLB_NULL_INDEX;
 }
 
-static inline void
-tlb_init_slave(struct slave *slave)
+static inline void tlb_init_slave(struct slave *slave)
 {
-	struct tlb_slave_info *slave_info = &(SLAVE_TLB_INFO(slave));
-
-	slave_info->load = 0;
-	slave_info->head = TLB_NULL_INDEX;
+	SLAVE_TLB_INFO(slave).load = 0;
+	SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX;
 }
 
 /* Caller must hold bond lock for read */
-static inline void
-tlb_clear_slave(struct bonding *bond, struct slave *slave, u8 save_load)
+static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_load)
 {
-	struct tlb_client_info *tx_hash_table = NULL;
-	u32 index, next_index;
+	struct tlb_client_info *tx_hash_table;
+	u32 index;
 
-	/* clear slave from tx_hashtbl */
 	_lock_tx_hashtbl(bond);
+
+	/* clear slave from tx_hashtbl */
 	tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl;
 
-	if (tx_hash_table) {
-		index = SLAVE_TLB_INFO(slave).head;
-		while (index != TLB_NULL_INDEX) {
-			next_index = tx_hash_table[index].next;
-			tlb_init_table_entry(bond, index, save_load);
-			index = next_index;
-		}
+	index = SLAVE_TLB_INFO(slave).head;
+	while (index != TLB_NULL_INDEX) {
+		u32 next_index = tx_hash_table[index].next;
+		tlb_init_table_entry(&tx_hash_table[index], save_load);
+		index = next_index;
 	}
+
 	_unlock_tx_hashtbl(bond);
 
 	tlb_init_slave(slave);
 }
 
 /* Must be called before starting the monitor timer */
-static int
-tlb_initialize(struct bonding *bond)
+static int tlb_initialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
 	int i;
-	size_t size;
-
-#if(TLB_HASH_TABLE_SIZE != 256)
-	/* Key to the hash table is byte wide. Check the size! */
-	#error Hash Table size is wrong.
-#endif
 
 	spin_lock_init(&(bond_info->tx_hashtbl_lock));
 
 	_lock_tx_hashtbl(bond);
-	if (bond_info->tx_hashtbl != NULL) {
-		printk (KERN_ERR "%s: TLB hash table is not NULL\n",
-			bond->device->name);
-		_unlock_tx_hashtbl(bond);
-		return -1;
-	}
 
-	size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
 	bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL);
-	if (bond_info->tx_hashtbl == NULL) {
-		printk (KERN_ERR "%s: Failed to allocate TLB hash table\n",
-			bond->device->name);
+	if (!bond_info->tx_hashtbl) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: %s: Failed to allocate TLB hash table\n",
+		       bond->dev->name);
 		_unlock_tx_hashtbl(bond);
 		return -1;
 	}
 
 	memset(bond_info->tx_hashtbl, 0, size);
-	for (i=0; i<TLB_HASH_TABLE_SIZE; i++) {
-		tlb_init_table_entry(bond, i, 1);
+
+	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
+		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
 	}
+
 	_unlock_tx_hashtbl(bond);
 
 	return 0;
 }
 
 /* Must be called only after all slaves have been released */
-static void
-tlb_deinitialize(struct bonding *bond)
+static void tlb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
 	_lock_tx_hashtbl(bond);
-	if (bond_info->tx_hashtbl == NULL) {
-		_unlock_tx_hashtbl(bond);
-		return;
-	}
+
 	kfree(bond_info->tx_hashtbl);
 	bond_info->tx_hashtbl = NULL;
+
 	_unlock_tx_hashtbl(bond);
 }
 
 /* Caller must hold bond lock for read */
-static struct slave*
-tlb_get_least_loaded_slave(struct bonding *bond)
+static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
 {
-	struct slave *slave;
-	struct slave *least_loaded;
-	s64 curr_gap, max_gap;
+	struct slave *slave, *least_loaded;
+	s64 max_gap;
+	int i, found = 0;
 
 	/* Find the first enabled slave */
-	slave = bond_get_first_slave(bond);
-	while (slave) {
+	bond_for_each_slave(bond, slave, i) {
 		if (SLAVE_IS_OK(slave)) {
+			found = 1;
 			break;
 		}
-		slave = bond_get_next_slave(bond, slave);
 	}
 
-	if (!slave) {
+	if (!found) {
 		return NULL;
 	}
 
 	least_loaded = slave;
-	max_gap = (s64)(slave->speed * 1000000) -
-			(s64)(SLAVE_TLB_INFO(slave).load * 8);
+	max_gap = (s64)(slave->speed << 20) - /* Convert to Megabit per sec */
+			(s64)(SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */
 
 	/* Find the slave with the largest gap */
-	slave = bond_get_next_slave(bond, slave);
-	while (slave) {
+	bond_for_each_slave_from(bond, slave, i, least_loaded) {
 		if (SLAVE_IS_OK(slave)) {
-			curr_gap = (s64)(slave->speed * 1000000) -
-					(s64)(SLAVE_TLB_INFO(slave).load * 8);
-			if (max_gap < curr_gap) {
+			s64 gap = (s64)(slave->speed << 20) -
+					(s64)(SLAVE_TLB_INFO(slave).load << 3);
+			if (max_gap < gap) {
 				least_loaded = slave;
-				max_gap = curr_gap;
+				max_gap = gap;
 			}
 		}
-		slave = bond_get_next_slave(bond, slave);
 	}
 
 	return least_loaded;
 }
 
 /* Caller must hold bond lock for read */
-struct slave*
-tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
+struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct tlb_client_info *hash_table = NULL;
-	struct slave *assigned_slave = NULL;
+	struct tlb_client_info *hash_table;
+	struct slave *assigned_slave;
 
 	_lock_tx_hashtbl(bond);
 
 	hash_table = bond_info->tx_hashtbl;
-	if (hash_table == NULL) {
-		printk (KERN_ERR "%s: TLB hash table is NULL\n",
-			bond->device->name);
-		_unlock_tx_hashtbl(bond);
-		return NULL;
-	}
-
 	assigned_slave = hash_table[hash_index].tx_slave;
 	if (!assigned_slave) {
 		assigned_slave = tlb_get_least_loaded_slave(bond);
@@ -345,14 +317,12 @@ tlb_choose_channel(struct bonding *bond,
 }
 
 /*********************** rlb specific functions ***************************/
-static inline void
-_lock_rx_hashtbl(struct bonding *bond)
+static inline void _lock_rx_hashtbl(struct bonding *bond)
 {
 	spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 }
 
-static inline void
-_unlock_rx_hashtbl(struct bonding *bond)
+static inline void _unlock_rx_hashtbl(struct bonding *bond)
 {
 	spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 }
@@ -360,26 +330,20 @@ _unlock_rx_hashtbl(struct bonding *bond)
 /* when an ARP REPLY is received from a client update its info
  * in the rx_hashtbl
  */
-static void
-rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
+static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
 {
-	u32 hash_index;
-	struct rlb_client_info *client_info = NULL;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct rlb_client_info *client_info;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-	hash_index = _simple_hash((u8*)&(arp->ip_src), 4);
+	hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 	if ((client_info->assigned) &&
 	    (client_info->ip_src == arp->ip_dst) &&
 	    (client_info->ip_dst == arp->ip_src)) {
-
 		/* update the clients MAC address */
 		memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
 		client_info->ntt = 1;
@@ -389,66 +353,60 @@ rlb_update_entry_from_arp(struct bonding
 	_unlock_rx_hashtbl(bond);
 }
 
-static int
-rlb_arp_recv(struct sk_buff *skb,
-	     struct net_device *dev,
-	     struct packet_type* ptype)
+static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype)
 {
-	struct bonding *bond = (struct bonding *)dev->priv;
-	int ret = NET_RX_DROP;
+	struct bonding *bond = bond_dev->priv;
 	struct arp_pkt *arp = (struct arp_pkt *)skb->data;
+	int res = NET_RX_DROP;
 
-	if (!(dev->flags & IFF_MASTER)) {
+	if (!(bond_dev->flags & IFF_MASTER)) {
 		goto out;
 	}
 
 	if (!arp) {
-		printk(KERN_ERR "Packet has no ARP data\n");
+		dprintk("Packet has no ARP data\n");
 		goto out;
 	}
 
 	if (skb->len < sizeof(struct arp_pkt)) {
-		printk(KERN_ERR "Packet is too small to be an ARP\n");
+		dprintk("Packet is too small to be an ARP\n");
 		goto out;
 	}
 
 	if (arp->op_code == htons(ARPOP_REPLY)) {
 		/* update rx hash table for this ARP */
 		rlb_update_entry_from_arp(bond, arp);
-		BOND_PRINT_DBG(("Server received an ARP Reply from client"));
+		dprintk("Server received an ARP Reply from client\n");
 	}
 
-	ret = NET_RX_SUCCESS;
+	res = NET_RX_SUCCESS;
 
 out:
 	dev_kfree_skb(skb);
 
-	return ret;
+	return res;
 }
 
 /* Caller must hold bond lock for read */
-static struct slave*
-rlb_next_rx_slave(struct bonding *bond)
+static struct slave *rlb_next_rx_slave(struct bonding *bond)
 {
-	struct slave *rx_slave = NULL, *slave = NULL;
-	unsigned int i = 0;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct slave *rx_slave, *slave, *start_at;
+	int i = 0;
 
-	slave = bond_info->next_rx_slave;
-	if (slave == NULL) {
-		slave = bond->next;
+	if (bond_info->next_rx_slave) {
+		start_at = bond_info->next_rx_slave;
+	} else {
+		start_at = bond->first_slave;
 	}
 
-	/* this loop uses the circular linked list property of the
-	 * slave's list to go through all slaves
-	 */
-	for (i = 0; i < bond->slave_cnt; i++, slave = slave->next) {
+	rx_slave = NULL;
 
+	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (SLAVE_IS_OK(slave)) {
 			if (!rx_slave) {
 				rx_slave = slave;
-			}
-			else if (slave->speed > rx_slave->speed) {
+			} else if (slave->speed > rx_slave->speed) {
 				rx_slave = slave;
 			}
 		}
@@ -464,48 +422,41 @@ rlb_next_rx_slave(struct bonding *bond)
 /* teach the switch the mac of a disabled slave
  * on the primary for fault tolerance
  *
- * Caller must hold bond->ptrlock for write or bond lock for write
+ * Caller must hold bond->curr_slave_lock for write or bond lock for write
  */
-static void
-rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
+static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
 {
-	if (!bond->current_slave) {
+	if (!bond->curr_active_slave) {
 		return;
 	}
+
 	if (!bond->alb_info.primary_is_promisc) {
 		bond->alb_info.primary_is_promisc = 1;
-		dev_set_promiscuity(bond->current_slave->dev, 1);
+		dev_set_promiscuity(bond->curr_active_slave->dev, 1);
 	}
+
 	bond->alb_info.rlb_promisc_timeout_counter = 0;
 
-	alb_send_learning_packets(bond->current_slave, addr);
+	alb_send_learning_packets(bond->curr_active_slave, addr);
 }
 
 /* slave being removed should not be active at this point
  *
  * Caller must hold bond lock for read
  */
-static void
-rlb_clear_slave(struct bonding *bond, struct slave *slave)
+static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
 {
-	struct rlb_client_info *rx_hash_table = NULL;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct rlb_client_info *rx_hash_table;
 	u32 index, next_index;
 
 	/* clear slave from rx_hashtbl */
 	_lock_rx_hashtbl(bond);
-	rx_hash_table = bond_info->rx_hashtbl;
-
-	if (rx_hash_table == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
 
+	rx_hash_table = bond_info->rx_hashtbl;
 	index = bond_info->rx_hashtbl_head;
 	for (; index != RLB_NULL_INDEX; index = next_index) {
 		next_index = rx_hash_table[index].next;
-
 		if (rx_hash_table[index].slave == slave) {
 			struct slave *assigned_slave = rlb_next_rx_slave(bond);
 
@@ -533,48 +484,63 @@ rlb_clear_slave(struct bonding *bond, st
 
 	_unlock_rx_hashtbl(bond);
 
-	write_lock(&bond->ptrlock);
-	if (slave != bond->current_slave) {
+	write_lock(&bond->curr_slave_lock);
+
+	if (slave != bond->curr_active_slave) {
 		rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
 	}
-	write_unlock(&bond->ptrlock);
+
+	write_unlock(&bond->curr_slave_lock);
 }
 
-static void
-rlb_update_client(struct rlb_client_info *client_info)
+static void rlb_update_client(struct rlb_client_info *client_info)
 {
-	int i = 0;
+	int i;
 
-	if (client_info->slave == NULL) {
+	if (!client_info->slave) {
 		return;
 	}
 
-	for (i=0; i<RLB_ARP_BURST_SIZE; i++) {
-		arp_send(ARPOP_REPLY, ETH_P_ARP,
-			 client_info->ip_dst,
-			 client_info->slave->dev,
-			 client_info->ip_src,
-			 client_info->mac_dst,
-			 client_info->slave->dev->dev_addr,
-			 client_info->mac_dst);
+	for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
+		struct sk_buff *skb;
+
+		skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
+				 client_info->ip_dst,
+				 client_info->slave->dev,
+				 client_info->ip_src,
+				 client_info->mac_dst,
+				 client_info->slave->dev->dev_addr,
+				 client_info->mac_dst);
+		if (!skb) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: failed to create an ARP packet\n");
+			continue;
+		}
+
+		skb->dev = client_info->slave->dev;
+
+		if (client_info->tag) {
+			skb = vlan_put_tag(skb, client_info->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
+		arp_xmit(skb);
 	}
 }
 
 /* sends ARP REPLIES that update the clients that need updating */
-static void
-rlb_update_rx_clients(struct bonding *bond)
+static void rlb_update_rx_clients(struct bonding *bond)
 {
-	u32 hash_index;
-	struct rlb_client_info *client_info = NULL;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct rlb_client_info *client_info;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -595,22 +561,15 @@ rlb_update_rx_clients(struct bonding *bo
 }
 
 /* The slave was assigned a new mac address - update the clients */
-static void
-rlb_req_update_slave_clients(struct bonding *bond, struct slave *slave)
+static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *slave)
 {
-	u32 hash_index;
-	u8 ntt = 0;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
-	struct rlb_client_info* client_info = NULL;
+	struct rlb_client_info *client_info;
+	int ntt = 0;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -633,37 +592,31 @@ rlb_req_update_slave_clients(struct bond
 }
 
 /* mark all clients using src_ip to be updated */
-static void
-rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
+static void rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
 {
-	u32 hash_index;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
-	struct rlb_client_info *client_info = NULL;
+	struct rlb_client_info *client_info;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 		if (!client_info->slave) {
-			printk(KERN_ERR "Bonding: Error: found a client with no"
-			       " channel in the client's hash table\n");
+			printk(KERN_ERR DRV_NAME
+			       ": Error: found a client with no channel in "
+			       "the client's hash table\n");
 			continue;
 		}
 		/*update all clients using this src_ip, that are not assigned
-		 * to the team's address (current_slave) and have a known
+		 * to the team's address (curr_active_slave) and have a known
 		 * unicast mac address.
 		 */
 		if ((client_info->ip_src == src_ip) &&
 		    memcmp(client_info->slave->dev->dev_addr,
-			   bond->device->dev_addr, ETH_ALEN) &&
+			   bond->dev->dev_addr, ETH_ALEN) &&
 		    memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
 			client_info->ntt = 1;
 			bond_info->rx_ntt = 1;
@@ -674,30 +627,23 @@ rlb_req_update_subnet_clients(struct bon
 }
 
 /* Caller must hold both bond and ptr locks for read */
-struct slave*
-rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp)
+struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct rlb_client_info *client_info = NULL;
+	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
+	struct slave *assigned_slave;
+	struct rlb_client_info *client_info;
 	u32 hash_index = 0;
-	struct slave *assigned_slave = NULL;
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return NULL;
-	}
-
-	hash_index = _simple_hash((u8 *)&arp->ip_dst, 4);
+	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_src));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
-	if (client_info->assigned == 1) {
+	if (client_info->assigned) {
 		if ((client_info->ip_src == arp->ip_src) &&
 		    (client_info->ip_dst == arp->ip_dst)) {
 			/* the entry is already assigned to this client */
-
 			if (memcmp(arp->mac_dst, mac_bcast, ETH_ALEN)) {
 				/* update mac address from arp */
 				memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
@@ -710,12 +656,12 @@ rlb_choose_channel(struct bonding *bond,
 			}
 		} else {
 			/* the entry is already assigned to some other client,
-			 * move the old client to primary (current_slave) so
+			 * move the old client to primary (curr_active_slave) so
 			 * that the new client can be assigned to this entry.
 			 */
-			if (bond->current_slave &&
-			    client_info->slave != bond->current_slave) {
-				client_info->slave = bond->current_slave;
+			if (bond->curr_active_slave &&
+			    client_info->slave != bond->curr_active_slave) {
+				client_info->slave = bond->curr_active_slave;
 				rlb_update_client(client_info);
 			}
 		}
@@ -736,11 +682,19 @@ rlb_choose_channel(struct bonding *bond,
 		if (memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
 			client_info->ntt = 1;
 			bond->alb_info.rx_ntt = 1;
-		}
-		else {
+		} else {
 			client_info->ntt = 0;
 		}
 
+		if (!list_empty(&bond->vlan_list)) {
+			unsigned short vlan_id;
+			int res = vlan_get_tag(skb, &vlan_id);
+			if (!res) {
+				client_info->tag = 1;
+				client_info->vlan_id = vlan_id;
+			}
+		}
+
 		if (!client_info->assigned) {
 			u32 prev_tbl_head = bond_info->rx_hashtbl_head;
 			bond_info->rx_hashtbl_head = hash_index;
@@ -760,10 +714,9 @@ rlb_choose_channel(struct bonding *bond,
 
 /* chooses (and returns) transmit channel for arp reply
  * does not choose channel for other arp types since they are
- * sent on the current_slave
+ * sent on the curr_active_slave
  */
-static struct slave*
-rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
+static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
 {
 	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
 	struct slave *tx_slave = NULL;
@@ -772,19 +725,18 @@ rlb_arp_xmit(struct sk_buff *skb, struct
 		/* the arp must be sent on the selected
 		* rx channel
 		*/
-		tx_slave = rlb_choose_channel(bond, arp);
+		tx_slave = rlb_choose_channel(skb, bond);
 		if (tx_slave) {
 			memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
 		}
-		BOND_PRINT_DBG(("Server sent ARP Reply packet"));
+		dprintk("Server sent ARP Reply packet\n");
 	} else if (arp->op_code == __constant_htons(ARPOP_REQUEST)) {
-
 		/* Create an entry in the rx_hashtbl for this client as a
 		 * place holder.
 		 * When the arp reply is received the entry will be updated
 		 * with the correct unicast address of the client.
 		 */
-		rlb_choose_channel(bond, arp);
+		rlb_choose_channel(skb, bond);
 
 		/* The ARP relpy packets must be delayed so that
 		 * they can cancel out the influence of the ARP request.
@@ -797,34 +749,29 @@ rlb_arp_xmit(struct sk_buff *skb, struct
 		 * updated with their assigned mac.
 		 */
 		rlb_req_update_subnet_clients(bond, arp->ip_src);
-		BOND_PRINT_DBG(("Server sent ARP Request packet"));
+		dprintk("Server sent ARP Request packet\n");
 	}
 
 	return tx_slave;
 }
 
 /* Caller must hold bond lock for read */
-static void
-rlb_rebalance(struct bonding *bond)
+static void rlb_rebalance(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct slave *assigned_slave = NULL;
+	struct slave *assigned_slave;
+	struct rlb_client_info *client_info;
+	int ntt;
 	u32 hash_index;
-	struct rlb_client_info *client_info = NULL;
-	u8 ntt = 0;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
+	ntt = 0;
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 		assigned_slave = rlb_next_rx_slave(bond);
-		if (assigned_slave && (client_info->slave != assigned_slave)){
+		if (assigned_slave && (client_info->slave != assigned_slave)) {
 			client_info->slave = assigned_slave;
 			client_info->ntt = 1;
 			ntt = 1;
@@ -839,97 +786,119 @@ rlb_rebalance(struct bonding *bond)
 }
 
 /* Caller must hold rx_hashtbl lock */
-static inline void
-rlb_init_table_entry(struct rlb_client_info *entry)
+static void rlb_init_table_entry(struct rlb_client_info *entry)
 {
+	memset(entry, 0, sizeof(struct rlb_client_info));
 	entry->next = RLB_NULL_INDEX;
 	entry->prev = RLB_NULL_INDEX;
-	entry->assigned = 0;
-	entry->ntt = 0;
 }
 
-static int
-rlb_initialize(struct bonding *bond)
+static int rlb_initialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type);
+	int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
 	int i;
-	size_t size;
 
 	spin_lock_init(&(bond_info->rx_hashtbl_lock));
 
 	_lock_rx_hashtbl(bond);
-	if (bond_info->rx_hashtbl != NULL) {
-		printk (KERN_ERR "%s: RLB hash table is not NULL\n",
-			bond->device->name);
-		_unlock_rx_hashtbl(bond);
-		return -1;
-	}
 
-	size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
 	bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL);
-	if (bond_info->rx_hashtbl == NULL) {
-		printk (KERN_ERR "%s: Failed to allocate"
-			" RLB hash table\n", bond->device->name);
+	if (!bond_info->rx_hashtbl) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: %s: Failed to allocate RLB hash table\n",
+		       bond->dev->name);
 		_unlock_rx_hashtbl(bond);
 		return -1;
 	}
 
 	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
 
-	for (i=0; i<RLB_HASH_TABLE_SIZE; i++) {
+	for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
 		rlb_init_table_entry(bond_info->rx_hashtbl + i);
 	}
-	_unlock_rx_hashtbl(bond);
 
-	/* register to receive ARPs */
+	_unlock_rx_hashtbl(bond);
 
 	/*initialize packet type*/
 	pk_type->type = __constant_htons(ETH_P_ARP);
-	pk_type->dev = bond->device;
+	pk_type->dev = bond->dev;
 	pk_type->func = rlb_arp_recv;
 	pk_type->data = (void*)1;  /* understand shared skbs */
 
+	/* register to receive ARPs */
 	dev_add_pack(pk_type);
 
 	return 0;
 }
 
-static void
-rlb_deinitialize(struct bonding *bond)
+static void rlb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
 	dev_remove_pack(&(bond_info->rlb_pkt_type));
 
 	_lock_rx_hashtbl(bond);
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
+
 	kfree(bond_info->rx_hashtbl);
 	bond_info->rx_hashtbl = NULL;
+	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+
+	_unlock_rx_hashtbl(bond);
+}
+
+static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u32 curr_index;
+
+	_lock_rx_hashtbl(bond);
+
+	curr_index = bond_info->rx_hashtbl_head;
+	while (curr_index != RLB_NULL_INDEX) {
+		struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
+		u32 next_index = bond_info->rx_hashtbl[curr_index].next;
+		u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
+
+		if (curr->tag && (curr->vlan_id == vlan_id)) {
+			if (curr_index == bond_info->rx_hashtbl_head) {
+				bond_info->rx_hashtbl_head = next_index;
+			}
+			if (prev_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[prev_index].next = next_index;
+			}
+			if (next_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[next_index].prev = prev_index;
+			}
+
+			rlb_init_table_entry(curr);
+		}
+
+		curr_index = next_index;
+	}
+
 	_unlock_rx_hashtbl(bond);
 }
 
 /*********************** tlb/rlb shared functions *********************/
 
-static void
-alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
+static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 {
-	struct sk_buff *skb = NULL;
+	struct bonding *bond = bond_get_bond_by_slave(slave);
 	struct learning_pkt pkt;
-	char *data = NULL;
+	int size = sizeof(struct learning_pkt);
 	int i;
-	unsigned int size = sizeof(struct learning_pkt);
 
 	memset(&pkt, 0, size);
 	memcpy(pkt.mac_dst, mac_addr, ETH_ALEN);
 	memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
 	pkt.type = __constant_htons(ETH_P_LOOP);
 
-	for (i=0; i < MAX_LP_RETRY; i++) {
-		skb = NULL;
+	for (i = 0; i < MAX_LP_BURST; i++) {
+		struct sk_buff *skb;
+		char *data;
+
 		skb = dev_alloc_skb(size);
 		if (!skb) {
 			return;
@@ -937,28 +906,46 @@ alb_send_learning_packets(struct slave *
 
 		data = skb_put(skb, size);
 		memcpy(data, &pkt, size);
+
 		skb->mac.raw = data;
 		skb->nh.raw = data + ETH_HLEN;
 		skb->protocol = pkt.type;
 		skb->priority = TC_PRIO_CONTROL;
 		skb->dev = slave->dev;
+
+		if (!list_empty(&bond->vlan_list)) {
+			struct vlan_entry *vlan;
+
+			vlan = bond_next_vlan(bond,
+					      bond->alb_info.current_alb_vlan);
+
+			bond->alb_info.current_alb_vlan = vlan;
+			if (!vlan) {
+				kfree_skb(skb);
+				continue;
+			}
+
+			skb = vlan_put_tag(skb, vlan->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
 		dev_queue_xmit(skb);
 	}
-
 }
 
 /* hw is a boolean parameter that determines whether we should try and
  * set the hw address of the device as well as the hw address of the
  * net_device
  */
-static int
-alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
 {
-	struct net_device *dev = NULL;
+	struct net_device *dev = slave->dev;
 	struct sockaddr s_addr;
 
-	dev = slave->dev;
-
 	if (!hw) {
 		memcpy(dev->dev_addr, addr, dev->addr_len);
 		return 0;
@@ -969,26 +956,23 @@ alb_set_slave_mac_addr(struct slave *sla
 	memcpy(s_addr.sa_data, addr, dev->addr_len);
 	s_addr.sa_family = dev->type;
 	if (dev->set_mac_address(dev, &s_addr)) {
-		printk(KERN_DEBUG "bonding: Error: alb_set_slave_mac_addr:"
-				  " dev->set_mac_address of dev %s failed!"
-				  " ALB mode requires that the base driver"
-				  " support setting the hw address also when"
-				  " the network device's interface is open\n",
-				  dev->name);
+		printk(KERN_ERR DRV_NAME
+		       ": Error: dev->set_mac_address of dev %s failed! ALB "
+		       "mode requires that the base driver support setting "
+		       "the hw address also when the network device's "
+		       "interface is open\n",
+		       dev->name);
 		return -EOPNOTSUPP;
 	}
 	return 0;
 }
 
-/* Caller must hold bond lock for write or ptrlock for write*/
-static void
-alb_swap_mac_addr(struct bonding *bond,
-		  struct slave *slave1,
-		  struct slave *slave2)
+/* Caller must hold bond lock for write or curr_slave_lock for write*/
+static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2)
 {
-	u8 tmp_mac_addr[ETH_ALEN];
 	struct slave *disabled_slave = NULL;
-	u8 slaves_state_differ;
+	u8 tmp_mac_addr[ETH_ALEN];
+	int slaves_state_differ;
 
 	slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
 
@@ -1005,8 +989,7 @@ alb_swap_mac_addr(struct bonding *bond,
 			 */
 			rlb_req_update_slave_clients(bond, slave1);
 		}
-	}
-	else {
+	} else {
 		disabled_slave = slave1;
 	}
 
@@ -1018,15 +1001,14 @@ alb_swap_mac_addr(struct bonding *bond,
 			 */
 			rlb_req_update_slave_clients(bond, slave2);
 		}
-	}
-	else {
+	} else {
 		disabled_slave = slave2;
 	}
 
 	if (bond->alb_info.rlb_enabled && slaves_state_differ) {
-			/* A disabled slave was assigned an active mac addr */
-			rlb_teach_disabled_mac_on_primary(bond,
-				disabled_slave->dev->dev_addr);
+		/* A disabled slave was assigned an active mac addr */
+		rlb_teach_disabled_mac_on_primary(bond,
+						  disabled_slave->dev->dev_addr);
 	}
 }
 
@@ -1044,10 +1026,8 @@ alb_swap_mac_addr(struct bonding *bond,
  *
  * Caller must hold bond lock
  */
-static void
-alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave)
+static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave)
 {
-	struct slave *tmp_slave;
 	int perm_curr_diff;
 	int perm_bond_diff;
 
@@ -1055,20 +1035,23 @@ alb_change_hw_addr_on_detach(struct bond
 				slave->dev->dev_addr,
 				ETH_ALEN);
 	perm_bond_diff = memcmp(slave->perm_hwaddr,
-				bond->device->dev_addr,
+				bond->dev->dev_addr,
 				ETH_ALEN);
+
 	if (perm_curr_diff && perm_bond_diff) {
-		tmp_slave = bond_get_first_slave(bond);
-		while (tmp_slave) {
+		struct slave *tmp_slave;
+		int i, found = 0;
+
+		bond_for_each_slave(bond, tmp_slave, i) {
 			if (!memcmp(slave->perm_hwaddr,
-				   tmp_slave->dev->dev_addr,
-				   ETH_ALEN)) {
+				    tmp_slave->dev->dev_addr,
+				    ETH_ALEN)) {
+				found = 1;
 				break;
 			}
-			tmp_slave = bond_get_next_slave(bond, tmp_slave);
 		}
 
-		if (tmp_slave) {
+		if (found) {
 			alb_swap_mac_addr(bond, slave, tmp_slave);
 		}
 	}
@@ -1099,10 +1082,11 @@ alb_change_hw_addr_on_detach(struct bond
  * caller must hold the bond lock for write since the mac addresses are compared
  * and may be swapped.
  */
-static int
-alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
+static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
 {
-	struct slave *tmp_slave1, *tmp_slave2;
+	struct slave *tmp_slave1, *tmp_slave2, *free_mac_slave;
+	struct slave *has_bond_addr = bond->curr_active_slave;
+	int i, j, found = 0;
 
 	if (bond->slave_cnt == 0) {
 		/* this is the first slave */
@@ -1113,65 +1097,78 @@ alb_handle_addr_collision_on_attach(stru
 	 * check uniqueness of slave's mac address against the other
 	 * slaves in the bond.
 	 */
-	if (memcmp(slave->perm_hwaddr, bond->device->dev_addr, ETH_ALEN)) {
-		tmp_slave1 = bond_get_first_slave(bond);
-		for (; tmp_slave1; tmp_slave1 = bond_get_next_slave(bond, tmp_slave1)) {
+	if (memcmp(slave->perm_hwaddr, bond->dev->dev_addr, ETH_ALEN)) {
+		bond_for_each_slave(bond, tmp_slave1, i) {
 			if (!memcmp(tmp_slave1->dev->dev_addr, slave->dev->dev_addr,
 				    ETH_ALEN)) {
+				found = 1;
 				break;
 			}
 		}
-		if (tmp_slave1) {
+
+		if (found) {
 			/* a slave was found that is using the mac address
 			 * of the new slave
 			 */
-			printk(KERN_ERR "bonding: Warning: the hw address "
-			       "of slave %s is not unique - cannot enslave it!"
-			       , slave->dev->name);
+			printk(KERN_ERR DRV_NAME
+			       ": Error: the hw address of slave %s is not "
+			       "unique - cannot enslave it!",
+			       slave->dev->name);
 			return -EINVAL;
 		}
+
 		return 0;
 	}
 
-	/* the slave's address is equal to the address of the bond
-	 * search for a spare address in the bond for this slave.
+	/* The slave's address is equal to the address of the bond.
+	 * Search for a spare address in the bond for this slave.
 	 */
-	tmp_slave1 = bond_get_first_slave(bond);
-	for (; tmp_slave1; tmp_slave1 = bond_get_next_slave(bond, tmp_slave1)) {
-
-		tmp_slave2 = bond_get_first_slave(bond);
-		for (; tmp_slave2; tmp_slave2 = bond_get_next_slave(bond, tmp_slave2)) {
+	free_mac_slave = NULL;
 
+	bond_for_each_slave(bond, tmp_slave1, i) {
+		found = 0;
+		bond_for_each_slave(bond, tmp_slave2, j) {
 			if (!memcmp(tmp_slave1->perm_hwaddr,
 				    tmp_slave2->dev->dev_addr,
 				    ETH_ALEN)) {
-
+				found = 1;
 				break;
 			}
 		}
 
-		if (!tmp_slave2) {
+		if (!found) {
 			/* no slave has tmp_slave1's perm addr
 			 * as its curr addr
 			 */
+			free_mac_slave = tmp_slave1;
 			break;
 		}
+
+		if (!has_bond_addr) {
+			if (!memcmp(tmp_slave1->dev->dev_addr,
+				    bond->dev->dev_addr,
+				    ETH_ALEN)) {
+
+				has_bond_addr = tmp_slave1;
+			}
+		}
 	}
 
-	if (tmp_slave1) {
-		alb_set_slave_mac_addr(slave, tmp_slave1->perm_hwaddr,
+	if (free_mac_slave) {
+		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
 				       bond->alb_info.rlb_enabled);
 
-		printk(KERN_WARNING "bonding: Warning: the hw address "
-		       "of slave %s is in use by the bond; "
-		       "giving it the hw address of %s\n",
-		       slave->dev->name, tmp_slave1->dev->name);
-	} else {
-		printk(KERN_CRIT "bonding: Error: the hw address "
-		       "of slave %s is in use by the bond; "
-		       "couldn't find a slave with a free hw "
-		       "address to give it (this should not have "
-		       "happened)\n", slave->dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: the hw address of slave %s is in use by "
+		       "the bond; giving it the hw address of %s\n",
+		       slave->dev->name, free_mac_slave->dev->name);
+
+	} else if (has_bond_addr) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: the hw address of slave %s is in use by the "
+		       "bond; couldn't find a slave with a free hw address to "
+		       "give it (this should not have happened)\n",
+		       slave->dev->name);
 		return -EFAULT;
 	}
 
@@ -1189,37 +1186,36 @@ alb_handle_addr_collision_on_attach(stru
  *
  * For each slave, this function sets the interface to the new address and then
  * changes its dev_addr field to its previous value.
- * 
+ *
  * Unwinding assumes bond's mac address has not yet changed.
  */
-static inline int
-alb_set_mac_address(struct bonding *bond, void *addr)
+static int alb_set_mac_address(struct bonding *bond, void *addr)
 {
 	struct sockaddr sa;
-	struct slave *slave;
+	struct slave *slave, *stop_at;
 	char tmp_addr[ETH_ALEN];
-	int error;
+	int res;
+	int i;
 
 	if (bond->alb_info.rlb_enabled) {
 		return 0;
 	}
 
-	slave = bond_get_first_slave(bond);
-	for (; slave; slave = bond_get_next_slave(bond, slave)) {
+	bond_for_each_slave(bond, slave, i) {
 		if (slave->dev->set_mac_address == NULL) {
-			error = -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
 			goto unwind;
 		}
 
 		/* save net_device's current hw address */
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 
-		error = slave->dev->set_mac_address(slave->dev, addr);
+		res = slave->dev->set_mac_address(slave->dev, addr);
 
 		/* restore net_device's hw address */
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
 
-		if (error) {
+		if (res) {
 			goto unwind;
 		}
 	}
@@ -1227,22 +1223,23 @@ alb_set_mac_address(struct bonding *bond
 	return 0;
 
 unwind:
-	memcpy(sa.sa_data, bond->device->dev_addr, bond->device->addr_len);
-	sa.sa_family = bond->device->type;
-	slave = bond_get_first_slave(bond);
-	for (; slave; slave = bond_get_next_slave(bond, slave)) {
+	memcpy(sa.sa_data, bond->dev->dev_addr, bond->dev->addr_len);
+	sa.sa_family = bond->dev->type;
+
+	/* unwind from head to the slave that failed */
+	stop_at = slave;
+	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 		slave->dev->set_mac_address(slave->dev, &sa);
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
 	}
 
-	return error;
+	return res;
 }
 
 /************************ exported alb funcions ************************/
 
-int
-bond_alb_initialize(struct bonding *bond, int rlb_enabled)
+int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
 {
 	int res;
 
@@ -1264,8 +1261,7 @@ bond_alb_initialize(struct bonding *bond
 	return 0;
 }
 
-void
-bond_alb_deinitialize(struct bonding *bond)
+void bond_alb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
@@ -1276,49 +1272,39 @@ bond_alb_deinitialize(struct bonding *bo
 	}
 }
 
-int
-bond_alb_xmit(struct sk_buff *skb, struct net_device *dev)
+int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 {
-	struct bonding *bond = (struct bonding *) dev->priv;
-	struct ethhdr *eth_data = (struct ethhdr *)skb->data;
+	struct bonding *bond = bond_dev->priv;
+	struct ethhdr *eth_data = (struct ethhdr *)skb->mac.raw = skb->data;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct slave *tx_slave = NULL;
-	char do_tx_balance = 1;
+	static u32 ip_bcast = 0xffffffff;
 	int hash_size = 0;
+	int do_tx_balance = 1;
 	u32 hash_index = 0;
 	u8 *hash_start = NULL;
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
-
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
+	int res = 1;
 
-	/* make sure that the current_slave and the slaves list do
+	/* make sure that the curr_active_slave and the slaves list do
 	 * not change during tx
 	 */
 	read_lock(&bond->lock);
+	read_lock(&bond->curr_slave_lock);
 
-	if (bond->slave_cnt == 0) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
 	}
 
-	read_lock(&bond->ptrlock);
-
 	switch (ntohs(skb->protocol)) {
 	case ETH_P_IP:
 		if ((memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) ||
-		    (skb->nh.iph->daddr == 0xffffffff)) {
+		    (skb->nh.iph->daddr == ip_bcast)) {
 			do_tx_balance = 0;
 			break;
 		}
 		hash_start = (char*)&(skb->nh.iph->daddr);
-		hash_size = 4;
+		hash_size = sizeof(skb->nh.iph->daddr);
 		break;
-
 	case ETH_P_IPV6:
 		if (memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) {
 			do_tx_balance = 0;
@@ -1326,9 +1312,8 @@ bond_alb_xmit(struct sk_buff *skb, struc
 		}
 
 		hash_start = (char*)&(skb->nh.ipv6h->daddr);
-		hash_size = 16;
+		hash_size = sizeof(skb->nh.ipv6h->daddr);
 		break;
-
 	case ETH_P_IPX:
 		if (skb->nh.ipxh->ipx_checksum !=
 		    __constant_htons(IPX_NO_CHECKSUM)) {
@@ -1337,8 +1322,7 @@ bond_alb_xmit(struct sk_buff *skb, struc
 			break;
 		}
 
-		if (skb->nh.ipxh->ipx_type !=
-		    __constant_htons(IPX_TYPE_NCP)) {
+		if (skb->nh.ipxh->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
@@ -1350,14 +1334,12 @@ bond_alb_xmit(struct sk_buff *skb, struc
 		hash_start = (char*)eth_data->h_dest;
 		hash_size = ETH_ALEN;
 		break;
-
 	case ETH_P_ARP:
 		do_tx_balance = 0;
 		if (bond_info->rlb_enabled) {
 			tx_slave = rlb_arp_xmit(skb, bond);
 		}
 		break;
-
 	default:
 		do_tx_balance = 0;
 		break;
@@ -1370,43 +1352,50 @@ bond_alb_xmit(struct sk_buff *skb, struc
 
 	if (!tx_slave) {
 		/* unbalanced or unassigned, send through primary */
-		tx_slave = bond->current_slave;
+		tx_slave = bond->curr_active_slave;
 		bond_info->unbalanced_load += skb->len;
 	}
 
 	if (tx_slave && SLAVE_IS_OK(tx_slave)) {
-		skb->dev = tx_slave->dev;
-		if (tx_slave != bond->current_slave) {
+		if (tx_slave != bond->curr_active_slave) {
 			memcpy(eth_data->h_source,
-				tx_slave->dev->dev_addr,
-				ETH_ALEN);
+			       tx_slave->dev->dev_addr,
+			       ETH_ALEN);
 		}
-		dev_queue_xmit(skb);
+
+		res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
 	} else {
-		/* no suitable interface, frame not sent */
 		if (tx_slave) {
 			tlb_clear_slave(bond, tx_slave, 0);
 		}
-		dev_kfree_skb(skb);
 	}
 
-	read_unlock(&bond->ptrlock);
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
+	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
 }
 
-void
-bond_alb_monitor(struct bonding *bond)
+void bond_alb_monitor(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct slave *slave = NULL;
+	struct slave *slave;
+	int i;
 
 	read_lock(&bond->lock);
 
-	if ((bond->slave_cnt == 0) || !(bond->device->flags & IFF_UP)) {
+	if (bond->kill_timers) {
+		goto out;
+	}
+
+	if (bond->slave_cnt == 0) {
 		bond_info->tx_rebalance_counter = 0;
 		bond_info->lp_counter = 0;
-		goto out;
+		goto re_arm;
 	}
 
 	bond_info->tx_rebalance_counter++;
@@ -1414,51 +1403,53 @@ bond_alb_monitor(struct bonding *bond)
 
 	/* send learning packets */
 	if (bond_info->lp_counter >= BOND_ALB_LP_TICKS) {
-		/* change of current_slave involves swapping of mac addresses.
+		/* change of curr_active_slave involves swapping of mac addresses.
 		 * in order to avoid this swapping from happening while
-		 * sending the learning packets, the ptrlock must be held for
+		 * sending the learning packets, the curr_slave_lock must be held for
 		 * read.
 		 */
-		read_lock(&bond->ptrlock);
-		slave = bond_get_first_slave(bond);
-		while (slave) {
+		read_lock(&bond->curr_slave_lock);
+
+		bond_for_each_slave(bond, slave, i) {
 			alb_send_learning_packets(slave,slave->dev->dev_addr);
-			slave = bond_get_next_slave(bond, slave);
 		}
-		read_unlock(&bond->ptrlock);
+
+		read_unlock(&bond->curr_slave_lock);
 
 		bond_info->lp_counter = 0;
 	}
 
 	/* rebalance tx traffic */
 	if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) {
-		read_lock(&bond->ptrlock);
-		slave = bond_get_first_slave(bond);
-		while (slave) {
+
+		read_lock(&bond->curr_slave_lock);
+
+		bond_for_each_slave(bond, slave, i) {
 			tlb_clear_slave(bond, slave, 1);
-			if (slave == bond->current_slave) {
+			if (slave == bond->curr_active_slave) {
 				SLAVE_TLB_INFO(slave).load =
 					bond_info->unbalanced_load /
 						BOND_TLB_REBALANCE_INTERVAL;
 				bond_info->unbalanced_load = 0;
 			}
-			slave = bond_get_next_slave(bond, slave);
 		}
-		read_unlock(&bond->ptrlock);
+
+		read_unlock(&bond->curr_slave_lock);
+
 		bond_info->tx_rebalance_counter = 0;
 	}
 
 	/* handle rlb stuff */
 	if (bond_info->rlb_enabled) {
 		/* the following code changes the promiscuity of the
-		 * the current_slave. It needs to be locked with a
+		 * the curr_active_slave. It needs to be locked with a
 		 * write lock to protect from other code that also
 		 * sets the promiscuity.
 		 */
-		write_lock(&bond->ptrlock);
+		write_lock(&bond->curr_slave_lock);
+
 		if (bond_info->primary_is_promisc &&
-		    (++bond_info->rlb_promisc_timeout_counter >=
-			RLB_PROMISC_TIMEOUT)) {
+		    (++bond_info->rlb_promisc_timeout_counter >= RLB_PROMISC_TIMEOUT)) {
 
 			bond_info->rlb_promisc_timeout_counter = 0;
 
@@ -1466,12 +1457,13 @@ bond_alb_monitor(struct bonding *bond)
 			 * because a slave was disabled then
 			 * it can now leave promiscuous mode.
 			 */
-			dev_set_promiscuity(bond->current_slave->dev, -1);
+			dev_set_promiscuity(bond->curr_active_slave->dev, -1);
 			bond_info->primary_is_promisc = 0;
 		}
-		write_unlock(&bond->ptrlock);
 
-		if (bond_info->rlb_rebalance == 1) {
+		write_unlock(&bond->curr_slave_lock);
+
+		if (bond_info->rlb_rebalance) {
 			bond_info->rlb_rebalance = 0;
 			rlb_rebalance(bond);
 		}
@@ -1491,28 +1483,23 @@ bond_alb_monitor(struct bonding *bond)
 		}
 	}
 
+re_arm:
+	mod_timer(&(bond_info->alb_timer), jiffies + alb_delta_in_ticks);
 out:
 	read_unlock(&bond->lock);
-
-	if (bond->device->flags & IFF_UP) {
-		/* re-arm the timer */
-		mod_timer(&(bond_info->alb_timer),
-			jiffies + (HZ/ALB_TIMER_TICKS_PER_SEC));
-	}
 }
 
-/* assumption: called before the slave is attched to the bond
+/* assumption: called before the slave is attached to the bond
  * and not locked by the bond lock
  */
-int
-bond_alb_init_slave(struct bonding *bond, struct slave *slave)
+int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
 {
-	int err = 0;
+	int res;
 
-	err = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
+	res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
 				     bond->alb_info.rlb_enabled);
-	if (err) {
-		return err;
+	if (res) {
+		return res;
 	}
 
 	/* caller must hold the bond lock for write since the mac addresses
@@ -1520,12 +1507,12 @@ bond_alb_init_slave(struct bonding *bond
 	 */
 	write_lock_bh(&bond->lock);
 
-	err = alb_handle_addr_collision_on_attach(bond, slave);
+	res = alb_handle_addr_collision_on_attach(bond, slave);
 
 	write_unlock_bh(&bond->lock);
 
-	if (err) {
-		return err;
+	if (res) {
+		return res;
 	}
 
 	tlb_init_slave(slave);
@@ -1541,8 +1528,7 @@ bond_alb_init_slave(struct bonding *bond
 }
 
 /* Caller must hold bond lock for write */
-void
-bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
+void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
 {
 	if (bond->slave_cnt > 1) {
 		alb_change_hw_addr_on_detach(bond, slave);
@@ -1557,9 +1543,7 @@ bond_alb_deinit_slave(struct bonding *bo
 }
 
 /* Caller must hold bond lock for read */
-void
-bond_alb_handle_link_change(struct bonding *bond, struct slave *slave,
-			    char link)
+void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
@@ -1583,112 +1567,126 @@ bond_alb_handle_link_change(struct bondi
 }
 
 /**
- * bond_alb_assign_current_slave - assign new current_slave
+ * bond_alb_handle_active_change - assign new curr_active_slave
  * @bond: our bonding struct
  * @new_slave: new slave to assign
  *
- * Set the bond->current_slave to @new_slave and handle
+ * Set the bond->curr_active_slave to @new_slave and handle
  * mac address swapping and promiscuity changes as needed.
  *
- * Caller must hold bond ptrlock for write (or bond lock for write)
+ * Caller must hold bond curr_slave_lock for write (or bond lock for write)
  */
-void
-bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave)
+void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
 {
-	struct slave *swap_slave = bond->current_slave;
+	struct slave *swap_slave;
+	int i;
 
-	if (bond->current_slave == new_slave) {
+	if (bond->curr_active_slave == new_slave) {
 		return;
 	}
 
-	if (bond->current_slave && bond->alb_info.primary_is_promisc) {
-		dev_set_promiscuity(bond->current_slave->dev, -1);
+	if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) {
+		dev_set_promiscuity(bond->curr_active_slave->dev, -1);
 		bond->alb_info.primary_is_promisc = 0;
 		bond->alb_info.rlb_promisc_timeout_counter = 0;
 	}
 
-	bond->current_slave = new_slave;
+	swap_slave = bond->curr_active_slave;
+	bond->curr_active_slave = new_slave;
 
 	if (!new_slave || (bond->slave_cnt == 0)) {
 		return;
 	}
 
-	/* set the new current_slave to the bonds mac address
-	 * i.e. swap mac addresses of old current_slave and new current_slave
+	/* set the new curr_active_slave to the bonds mac address
+	 * i.e. swap mac addresses of old curr_active_slave and new curr_active_slave
 	 */
 	if (!swap_slave) {
+		struct slave *tmp_slave;
 		/* find slave that is holding the bond's mac address */
-		swap_slave = bond_get_first_slave(bond);
-		while (swap_slave) {
-			if (!memcmp(swap_slave->dev->dev_addr,
-				bond->device->dev_addr, ETH_ALEN)) {
+		bond_for_each_slave(bond, tmp_slave, i) {
+			if (!memcmp(tmp_slave->dev->dev_addr,
+				    bond->dev->dev_addr, ETH_ALEN)) {
+				swap_slave = tmp_slave;
 				break;
 			}
-			swap_slave = bond_get_next_slave(bond, swap_slave);
 		}
 	}
 
-	/* current_slave must be set before calling alb_swap_mac_addr */
+	/* curr_active_slave must be set before calling alb_swap_mac_addr */
 	if (swap_slave) {
 		/* swap mac address */
 		alb_swap_mac_addr(bond, swap_slave, new_slave);
 	} else {
 		/* set the new_slave to the bond mac address */
-		alb_set_slave_mac_addr(new_slave, bond->device->dev_addr,
+		alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
 				       bond->alb_info.rlb_enabled);
 		/* fasten bond mac on new current slave */
-		alb_send_learning_packets(new_slave, bond->device->dev_addr);
+		alb_send_learning_packets(new_slave, bond->dev->dev_addr);
 	}
 }
 
-int
-bond_alb_set_mac_address(struct net_device *dev, void *addr)
+int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
 {
-	struct bonding *bond = dev->priv;
+	struct bonding *bond = bond_dev->priv;
 	struct sockaddr *sa = addr;
-	struct slave *swap_slave = NULL;
-	int error = 0;
+	struct slave *slave, *swap_slave;
+	int res;
+	int i;
 
 	if (!is_valid_ether_addr(sa->sa_data)) {
 		return -EADDRNOTAVAIL;
 	}
 
-	error = alb_set_mac_address(bond, addr);
-	if (error) {
-		return error;
+	res = alb_set_mac_address(bond, addr);
+	if (res) {
+		return res;
 	}
 
-	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+	memcpy(bond_dev->dev_addr, sa->sa_data, bond_dev->addr_len);
 
-	/* If there is no current_slave there is nothing else to do.
+	/* If there is no curr_active_slave there is nothing else to do.
 	 * Otherwise we'll need to pass the new address to it and handle
 	 * duplications.
 	 */
-	if (bond->current_slave == NULL) {
+	if (!bond->curr_active_slave) {
 		return 0;
 	}
 
-	swap_slave = bond_get_first_slave(bond);
-	while (swap_slave) {
-		if (!memcmp(swap_slave->dev->dev_addr, dev->dev_addr, ETH_ALEN)) {
+	swap_slave = NULL;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (!memcmp(slave->dev->dev_addr, bond_dev->dev_addr, ETH_ALEN)) {
+			swap_slave = slave;
 			break;
 		}
-		swap_slave = bond_get_next_slave(bond, swap_slave);
 	}
 
 	if (swap_slave) {
-		alb_swap_mac_addr(bond, swap_slave, bond->current_slave);
+		alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
 	} else {
-		alb_set_slave_mac_addr(bond->current_slave, dev->dev_addr,
+		alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
 				       bond->alb_info.rlb_enabled);
 
-		alb_send_learning_packets(bond->current_slave, dev->dev_addr);
+		alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
 		if (bond->alb_info.rlb_enabled) {
 			/* inform clients mac address has changed */
-			rlb_req_update_slave_clients(bond, bond->current_slave);
+			rlb_req_update_slave_clients(bond, bond->curr_active_slave);
 		}
 	}
 
 	return 0;
 }
 
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	if (bond->alb_info.current_alb_vlan &&
+	    (bond->alb_info.current_alb_vlan->vlan_id == vlan_id)) {
+		bond->alb_info.current_alb_vlan = NULL;
+	}
+
+	if (bond->alb_info.rlb_enabled) {
+		rlb_clear_vlan(bond, vlan_id);
+	}
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bond_alb.h linux-2.4.26-pre6/drivers/net/bonding/bond_alb.h
--- linux-2.4.25/drivers/net/bonding/bond_alb.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/bonding/bond_alb.h	2004-03-25 00:20:27.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * 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
@@ -24,6 +24,9 @@
  * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef __BOND_ALB_H__
@@ -74,6 +77,8 @@ struct rlb_client_info {
 	u8  assigned;		/* checking whether this entry is assigned */
 	u8  ntt;		/* flag - need to transmit client info */
 	struct slave *slave;	/* the slave assigned to this client */
+	u8 tag;			/* flag - need to tag skb */
+	unsigned short vlan_id;	/* VLAN tag associated with IP address */
 };
 
 struct tlb_slave_info {
@@ -119,6 +124,7 @@ struct alb_bond_info {
 						 * rx traffic should be
 						 * rebalanced
 						 */
+	struct vlan_entry	*current_alb_vlan;
 };
 
 int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
@@ -126,10 +132,10 @@ void bond_alb_deinitialize(struct bondin
 int bond_alb_init_slave(struct bonding *bond, struct slave *slave);
 void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
 void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
-void bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave);
-int bond_alb_xmit(struct sk_buff *skb, struct net_device *dev);
+void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave);
+int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
 void bond_alb_monitor(struct bonding *bond);
-int bond_alb_set_mac_address(struct net_device *dev, void *addr);
-
+int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
 #endif /* __BOND_ALB_H__ */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bond_main.c linux-2.4.26-pre6/drivers/net/bonding/bond_main.c
--- linux-2.4.25/drivers/net/bonding/bond_main.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/bonding/bond_main.c	2004-03-25 00:19:08.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * originally based on the dummy device.
  *
- * Copyright 1999, Thomas Davis, tadavis@lbl.gov.  
+ * Copyright 1999, Thomas Davis, tadavis@lbl.gov.
  * Licensed under the GPL. Based on dummy.c, and eql.c devices.
  *
  * bonding.c: an Ethernet Bonding driver
@@ -15,9 +15,9 @@
  *
  * How it works:
  *    ifconfig bond0 ipaddress netmask up
- *      will setup a network device, with an ip address.  No mac address 
- *	will be assigned at this time.  The hw mac address will come from 
- *	the first slave bonded to the channel.  All slaves will then use 
+ *      will setup a network device, with an ip address.  No mac address
+ *	will be assigned at this time.  The hw mac address will come from
+ *	the first slave bonded to the channel.  All slaves will then use
  *	this hw mac address.
  *
  *    ifconfig bond0 down
@@ -26,7 +26,7 @@
  *    ifenslave bond0 eth0
  *	will attach eth0 to bond0 as a slave.  eth0 hw mac address will either
  *	a: be used as initial mac address
- *	b: if a hw mac address already is there, eth0's hw mac address 
+ *	b: if a hw mac address already is there, eth0's hw mac address
  *	   will then be set from bond0.
  *
  * v0.1 - first working version.
@@ -93,14 +93,14 @@
  *
  * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
  *     - Ported to 2.4 Kernel
- * 
+ *
  * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
  *     - When a device is detached from a bond, the slave device is no longer
  *       left thinking that is has a master.
  *
  * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
- *     - memset did not appropriately initialized the bond rw_locks. Used 
- *       rwlock_init to initialize to unlocked state to prevent deadlock when 
+ *     - memset did not appropriately initialized the bond rw_locks. Used
+ *       rwlock_init to initialize to unlocked state to prevent deadlock when
  *       first attempting a lock
  *     - Called SET_MODULE_OWNER for bond device
  *
@@ -119,7 +119,7 @@
  *
  * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
  *     - Added /proc support for getting bond and slave information.
- *       Information is in /proc/net/<bond device>/info. 
+ *       Information is in /proc/net/<bond device>/info.
  *     - Changed the locking when calling bond_close to prevent deadlock.
  *
  * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
@@ -144,8 +144,8 @@
  *       but only for an up link.
  *
  * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Add the device field to bonding_t.  Previously the net_device 
- *       corresponding to a bond wasn't available from the bonding_t 
+ *     - Add the device field to bonding_t.  Previously the net_device
+ *       corresponding to a bond wasn't available from the bonding_t
  *       structure.
  *
  * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
@@ -155,10 +155,10 @@
  *     - Various memory leak fixes
  *
  * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
- *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under 
- *       certain hotswap conditions.  
+ *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under
+ *       certain hotswap conditions.
  *       Note:  this same change may be required in bond_arp_monitor ???
- *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr 
+ *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr
  *     - Handle hot swap ethernet interface deregistration events to remove
  *       kernel oops following hot swap of enslaved interface
  *
@@ -222,23 +222,23 @@
  *     - fix deletion of multicast groups after unloading module
  *
  * 2002/11/06 - Kameshwara Rayaprolu <kameshwara.rao * wipro_com>
- *     - Changes to prevent panic from closing the device twice; if we close 
- *       the device in bond_release, we must set the original_flags to down 
+ *     - Changes to prevent panic from closing the device twice; if we close
+ *       the device in bond_release, we must set the original_flags to down
  *       so it won't be closed again by the network layer.
  *
  * 2002/11/07 - Tony Cureington <tony.cureington * hp_com>
  *     - Fix arp_target_hw_addr memory leak
- *     - Created activebackup_arp_monitor function to handle arp monitoring 
- *       in active backup mode - the bond_arp_monitor had several problems... 
- *       such as allowing slaves to tx arps sequentially without any delay 
+ *     - Created activebackup_arp_monitor function to handle arp monitoring
+ *       in active backup mode - the bond_arp_monitor had several problems...
+ *       such as allowing slaves to tx arps sequentially without any delay
  *       for a response
  *     - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote
  *       this function to just handle arp monitoring in load-balancing mode;
  *       it is a lot more compact now
- *     - Changes to ensure one and only one slave transmits in active-backup 
+ *     - Changes to ensure one and only one slave transmits in active-backup
  *       mode
- *     - Robustesize parameters; warn users about bad combinations of 
- *       parameters; also if miimon is specified and a network driver does 
+ *     - Robustesize parameters; warn users about bad combinations of
+ *       parameters; also if miimon is specified and a network driver does
  *       not support MII or ETHTOOL, inform the user of this
  *     - Changes to support link_failure_count when in arp monitoring mode
  *     - Fix up/down delay reported in /proc
@@ -248,7 +248,7 @@
  *
  * 2002/11/16 - Laurent Deniel <laurent.deniel at free.fr>
  *     - fix multicast handling in activebackup_arp_monitor
- *     - remove one unnecessary and confusing current_slave == slave test 
+ *     - remove one unnecessary and confusing curr_active_slave == slave test
  *	 in activebackup_arp_monitor
  *
  *  2002/11/17 - Laurent Deniel <laurent.deniel at free.fr>
@@ -267,7 +267,7 @@
  *	  One change: an invalid choice will cause module load failure,
  *	  rather than the previous behavior of just picking one.
  *	- Minor cleanups; got rid of dup ctype stuff, atoi function
- * 
+ *
  * 2003/02/07 - Jay Vosburgh <fubar at us dot ibm dot com>
  *	- Added use_carrier module parameter that causes miimon to
  *	  use netif_carrier_ok() test instead of MII/ETHTOOL ioctls.
@@ -330,7 +330,7 @@
  *	  new/old ifenslave and new/old bonding.
  *
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Fixed bug in bond_release_all(): save old value of current_slave
+ *	- Fixed bug in bond_release_all(): save old value of curr_active_slave
  *	  before setting it to NULL.
  *	- Changed driver versioning scheme to include version number instead
  *	  of release date (that is already in another field). There are 3
@@ -358,7 +358,7 @@
  *
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Added support for Transmit load balancing mode.
- *	- Concentrate all assignments of current_slave to a single point
+ *	- Concentrate all assignments of curr_active_slave to a single point
  *	  so specific modes can take actions when the primary adapter is
  *	  changed.
  *	- Take the updelay parameter into consideration during bond_enslave
@@ -426,8 +426,53 @@
  *	- Convert /proc to seq_file interface.
  *	  Change /proc/net/bondX/info to /proc/net/bonding/bondX.
  *	  Set version to 2.4.1.
+ *
+ * 2003/11/20 - Amir Noam <amir.noam at intel dot com>
+ *	- Fix /proc creation/destruction.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Massive cleanup - Set version to 2.5.0
+ *	  Code changes:
+ *	  o Consolidate format of prints and debug prints.
+ *	  o Remove bonding_t/slave_t typedefs and consolidate all casts.
+ *	  o Remove dead code and unnecessary checks.
+ *	  o Consolidate starting/stopping timers.
+ *	  o Consolidate handling of primary module param throughout the code.
+ *	  o Removed multicast module param support - all settings are done
+ *	    according to mode.
+ *	  o Slave list iteration - bond is no longer part of the list,
+ *	    added cyclic list iteration macros.
+ *	  o Consolidate error handling in all xmit functions.
+ *	  Style changes:
+ *	  o Consolidate function naming and declarations.
+ *	  o Consolidate function params and local variables names.
+ *	  o Consolidate return values.
+ *	  o Consolidate curly braces.
+ *	  o Consolidate conditionals format.
+ *	  o Change struct member names and types.
+ *	  o Chomp trailing spaces, remove empty lines, fix indentations.
+ *	  o Re-organize code according to context.
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *	- Fixed: Releasing the original active slave causes mac address
+ *		 duplication.
+ *	- Add support for slaves that use ethtool_ops.
+ *	  Set version to 2.5.3.
+ *
+ * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
+ *	- Save bonding parameters per bond instead of using the global values.
+ *	  Set version to 2.5.4.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Enhance VLAN support:
+ *	  * Add support for VLAN hardware acceleration capable slaves.
+ *	  * Add capability to tag self generated packets in ALB/TLB modes.
+ *	  Set version to 2.6.0.
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -452,7 +497,6 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 #include <linux/errno.h>
-
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
@@ -461,58 +505,72 @@
 #include <linux/rtnetlink.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-
-#include <linux/if_bonding.h>
 #include <linux/smp.h>
 #include <linux/if_ether.h>
 #include <net/arp.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/if_bonding.h>
 #include "bonding.h"
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.4.1"
-#define DRV_RELDATE	"September 15, 2003"
-#define DRV_NAME	"bonding"
-#define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
-
-static const char *version =
-DRV_NAME ".c:v" DRV_VERSION " (" DRV_RELDATE ")\n";
+/*---------------------------- Module parameters ----------------------------*/
 
 /* monitor all links that often (in milliseconds). <=0 disables monitoring */
-#ifndef BOND_LINK_MON_INTERV
 #define BOND_LINK_MON_INTERV	0
-#endif
-
-#ifndef BOND_LINK_ARP_INTERV
 #define BOND_LINK_ARP_INTERV	0
-#endif
 
-#ifndef MAX_ARP_IP_TARGETS
-#define MAX_ARP_IP_TARGETS 16
-#endif
+static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
+static int miimon	= BOND_LINK_MON_INTERV;
+static int updelay	= 0;
+static int downdelay	= 0;
+static int use_carrier	= 1;
+static char *mode	= NULL;
+static char *primary	= NULL;
+static char *lacp_rate	= NULL;
+static int arp_interval = BOND_LINK_ARP_INTERV;
+static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+
+MODULE_PARM(max_bonds, "i");
+MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
+MODULE_PARM(miimon, "i");
+MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
+MODULE_PARM(updelay, "i");
+MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
+MODULE_PARM(downdelay, "i");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+MODULE_PARM(use_carrier, "i");
+MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
+MODULE_PARM(mode, "s");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM(primary, "s");
+MODULE_PARM_DESC(primary, "Primary network device to use");
+MODULE_PARM(lacp_rate, "s");
+MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+MODULE_PARM(arp_interval, "i");
+MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
+MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(BOND_MAX_ARP_TARGETS) "s");
+MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 
-#define USES_PRIMARY(mode) \
-		(((mode) == BOND_MODE_ACTIVEBACKUP) || \
-		 ((mode) == BOND_MODE_TLB) || \
-		 ((mode) == BOND_MODE_ALB))
+/*----------------------------- Global variables ----------------------------*/
 
-struct bond_parm_tbl {
-	char *modename;
-	int mode;
-};
+static const char *version =
+	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
-static int arp_interval = BOND_LINK_ARP_INTERV;
-static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, };
-static u32 arp_target[MAX_ARP_IP_TARGETS] = { 0, } ;
-static int arp_ip_count = 0;
-static u32 my_ip = 0;
-char *arp_target_hw_addr = NULL;
+static LIST_HEAD(bond_dev_list);
 
-static char *primary= NULL;
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *bond_proc_dir = NULL;
+#endif
 
-static int app_abi_ver = 0;
+static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
+static int arp_ip_count	= 0;
+static u32 my_ip	= 0;
+static int bond_mode	= BOND_MODE_ROUNDROBIN;
+static int lacp_fast	= 0;
+static int app_abi_ver	= 0;
 static int orig_app_abi_ver = -1; /* This is used to save the first ABI version
 				   * we receive from the application. Once set,
 				   * it won't be changed, and the module will
@@ -521,14 +579,16 @@ static int orig_app_abi_ver = -1; /* Thi
 				   * another ABI version.
 				   */
 
-static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
-static int miimon	= BOND_LINK_MON_INTERV;
-static int use_carrier	= 1;
-static int bond_mode	= BOND_MODE_ROUNDROBIN;
-static int updelay	= 0;
-static int downdelay	= 0;
+struct bond_parm_tbl {
+	char *modename;
+	int mode;
+};
 
-static char *mode	= NULL;
+static struct bond_parm_tbl bond_lacp_tbl[] = {
+{	"slow",		AD_LACP_SLOW},
+{	"fast",		AD_LACP_FAST},
+{	NULL,		-1},
+};
 
 static struct bond_parm_tbl bond_mode_tbl[] = {
 {	"balance-rr",		BOND_MODE_ROUNDROBIN},
@@ -541,103 +601,15 @@ static struct bond_parm_tbl bond_mode_tb
 {	NULL,			-1},
 };
 
-static int multicast_mode	= BOND_MULTICAST_ALL;
-static char *multicast		= NULL;
-
-static struct bond_parm_tbl bond_mc_tbl[] = {
-{	"disabled",		BOND_MULTICAST_DISABLED},
-{	"active",		BOND_MULTICAST_ACTIVE},
-{	"all",			BOND_MULTICAST_ALL},
-{	NULL,			-1},
-};
-
-static int lacp_fast		= 0;
-static char *lacp_rate		= NULL;
-
-static struct bond_parm_tbl bond_lacp_tbl[] = {
-{	"slow",		AD_LACP_SLOW},
-{	"fast",		AD_LACP_FAST},
-{	NULL,		-1},
-};
-
-static LIST_HEAD(bond_dev_list);
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *bond_proc_dir = NULL;
-#endif
+/*-------------------------- Forward declarations ---------------------------*/
 
-MODULE_PARM(max_bonds, "i");
-MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
-MODULE_PARM(miimon, "i");
-MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
-MODULE_PARM(use_carrier, "i");
-MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
-MODULE_PARM(arp_interval, "i");
-MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
-MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s");
-MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
-MODULE_PARM(updelay, "i");
-MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
-MODULE_PARM(downdelay, "i");
-MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
-MODULE_PARM(primary, "s");
-MODULE_PARM_DESC(primary, "Primary network device to use");
-MODULE_PARM(multicast, "s");
-MODULE_PARM_DESC(multicast, "Mode for multicast support : 0 for none, 1 for active slave, 2 for all slaves (default)");
-MODULE_PARM(lacp_rate, "s");
-MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);
 
-static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev);
-static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev);
-static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *bond_get_stats(struct net_device *dev);
-static void bond_mii_monitor(struct net_device *dev);
-static void loadbalance_arp_monitor(struct net_device *dev);
-static void activebackup_arp_monitor(struct net_device *dev);
-static void bond_mc_list_destroy(struct bonding *bond);
-static void bond_mc_add(bonding_t *bond, void *addr, int alen);
-static void bond_mc_delete(bonding_t *bond, void *addr, int alen);
-static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst, int gpf_flag);
-static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2);
-static void bond_set_promiscuity(bonding_t *bond, int inc);
-static void bond_set_allmulti(bonding_t *bond, int inc);
-static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list);
-static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old);
-static int bond_enslave(struct net_device *master, struct net_device *slave);
-static int bond_release(struct net_device *master, struct net_device *slave);
-static int bond_release_all(struct net_device *master);
-static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
-static void change_active_interface(struct bonding *bond, struct slave *new);
-static void reselect_active_interface(struct bonding *bond);
-static struct slave *find_best_interface(struct bonding *bond);
-
-
-/* #define BONDING_DEBUG 1 */
-#ifdef BONDING_DEBUG
-#define dprintk(x...) printk(x...)
-#else /* BONDING_DEBUG */
-#define dprintk(x...) do {} while (0)
-#endif /* BONDING_DEBUG */
-
-/* several macros */
-
-static void arp_send_all(slave_t *slave)
-{	
-	int i; 
-
-	for (i = 0; (i<MAX_ARP_IP_TARGETS) && arp_target[i]; i++) { 
-		arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target[i], slave->dev, 
-			 my_ip, arp_target_hw_addr, slave->dev->dev_addr,
-			 arp_target_hw_addr); 
-	} 
-}
- 
+/*---------------------------- General routines -----------------------------*/
 
-static const char *
-bond_mode_name(void)
+static const char *bond_mode_name(int mode)
 {
-	switch (bond_mode) {
+	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
 		return "load balancing (round-robin)";
 	case BOND_MODE_ACTIVEBACKUP :
@@ -657,767 +629,1070 @@ bond_mode_name(void)
 	}
 }
 
-static const char *
-multicast_mode_name(void)
+/*---------------------------------- VLAN -----------------------------------*/
+
+/**
+ * bond_add_vlan - add a new vlan id on bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to add
+ *
+ * Returns -ENOMEM if allocation failed.
+ */
+static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
 {
-	switch(multicast_mode) {
-	case BOND_MULTICAST_DISABLED :
-		return "disabled";
-	case BOND_MULTICAST_ACTIVE :
-		return "active slave only";
-	case BOND_MULTICAST_ALL :
-		return "all slaves";
-	default :
-		return "unknown";
+	struct vlan_entry *vlan;
+
+	dprintk("bond: %s, vlan id %d\n",
+		(bond ? bond->dev->name: "None"), vlan_id);
+
+	vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL);
+	if (!vlan) {
+		return -ENOMEM;
 	}
-}
 
-void bond_set_slave_inactive_flags(slave_t *slave)
-{
-	slave->state = BOND_STATE_BACKUP;
-	slave->dev->flags |= IFF_NOARP;
-}
+	INIT_LIST_HEAD(&vlan->vlan_list);
+	vlan->vlan_id = vlan_id;
 
-void bond_set_slave_active_flags(slave_t *slave)
-{
-	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->flags &= ~IFF_NOARP;
+	write_lock_bh(&bond->lock);
+
+	list_add_tail(&vlan->vlan_list, &bond->vlan_list);
+
+	write_unlock_bh(&bond->lock);
+
+	dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name);
+
+	return 0;
 }
 
-/*
- * This function counts and verifies the the number of attached
- * slaves, checking the count against the expected value (given that incr
- * is either 1 or -1, for add or removal of a slave).  Only
- * bond_xmit_xor() uses the slave_cnt value, but this is still a good
- * consistency check.
+/**
+ * bond_del_vlan - delete a vlan id from bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to delete
+ *
+ * returns -ENODEV if @vlan_id was not found in @bond.
  */
-static inline void
-update_slave_cnt(bonding_t *bond, int incr)
+static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
 {
-	slave_t *slave = NULL;
-	int expect = bond->slave_cnt + incr;
+	struct vlan_entry *vlan, *next;
+	int res = -ENODEV;
 
-	bond->slave_cnt = 0;
-	for (slave = bond->prev; slave != (slave_t*)bond;
-	     slave = slave->prev) {
-		bond->slave_cnt++;
+	dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
+
+	write_lock_bh(&bond->lock);
+
+	list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) {
+		if (vlan->vlan_id == vlan_id) {
+			list_del(&vlan->vlan_list);
+
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
+				bond_alb_clear_vlan(bond, vlan_id);
+			}
+
+			dprintk("removed VLAN ID %d from bond %s\n", vlan_id,
+				bond->dev->name);
+
+			kfree(vlan);
+
+			if (list_empty(&bond->vlan_list) &&
+			    (bond->slave_cnt == 0)) {
+				/* Last VLAN removed and no slaves, so
+				 * restore block on adding VLANs. This will
+				 * be removed once new slaves that are not
+				 * VLAN challenged will be added.
+				 */
+				bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
+			}
+
+			res = 0;
+			goto out;
+		}
 	}
 
-	if (expect != bond->slave_cnt)
-		BUG();
+	dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id,
+		bond->dev->name);
+
+out:
+	write_unlock_bh(&bond->lock);
+	return res;
 }
 
-/* 
- * This function detaches the slave <slave> from the list <bond>.
- * WARNING: no check is made to verify if the slave effectively
- * belongs to <bond>. It returns <slave> in case it's needed.
- * Nothing is freed on return, structures are just unchained.
- * If the bond->current_slave pointer was pointing to <slave>,
- * it should be changed by the calling function.
+/**
+ * bond_has_challenged_slaves
+ * @bond: the bond we're working on
  *
- * bond->lock held for writing by caller.
+ * Searches the slave list. Returns 1 if a vlan challenged slave
+ * was found, 0 otherwise.
+ *
+ * Assumes bond->lock is held.
  */
-static slave_t *
-bond_detach_slave(bonding_t *bond, slave_t *slave)
+static int bond_has_challenged_slaves(struct bonding *bond)
 {
-	if ((bond == NULL) || (slave == NULL) ||
-	   ((void *)bond == (void *)slave)) {
-		printk(KERN_ERR
-			"bond_detach_slave(): trying to detach "
-			"slave %p from bond %p\n", bond, slave);
-		return slave;
-	}
-
-	if (bond->next == slave) {  /* is the slave at the head ? */
-		if (bond->prev == slave) {  /* is the slave alone ? */
-			bond->prev = bond->next = (slave_t *)bond;
-		} else { /* not alone */
-			bond->next        = slave->next;
-			slave->next->prev = (slave_t *)bond;
-			bond->prev->next  = slave->next;
-		}
-	} else {
-		slave->prev->next = slave->next;
-		if (bond->prev == slave) {  /* is this slave the last one ? */
-			bond->prev = slave->prev;
-		} else {
-			slave->next->prev = slave->prev;
+	struct slave *slave;
+	int i;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) {
+			dprintk("found VLAN challenged slave - %s\n",
+				slave->dev->name);
+			return 1;
 		}
 	}
 
-	update_slave_cnt(bond, -1);
-
-	return slave;
+	dprintk("no VLAN challenged slaves found\n");
+	return 0;
 }
 
-/*
- * This function attaches the slave <slave> to the list <bond>.
+/**
+ * bond_next_vlan - safely skip to the next item in the vlans list.
+ * @bond: the bond we're working on
+ * @curr: item we're advancing from
  *
- * bond->lock held for writing by caller.
+ * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL,
+ * or @curr->next otherwise (even if it is @curr itself again).
+ * 
+ * Caller must hold bond->lock
  */
-static void
-bond_attach_slave(struct bonding *bond, struct slave *new_slave)
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
 {
-	/* 
-	 * queue to the end of the slaves list, make the first element its
-	 * successor, the last one its predecessor, and make it the bond's
-	 * predecessor. 
-	 *
-	 * Just to clarify, so future bonding driver hackers don't go through
-	 * the same confusion stage I did trying to figure this out, the
-	 * slaves are stored in a double linked circular list, sortof.
-	 * In the ->next direction, the last slave points to the first slave,
-	 * bypassing bond; only the slaves are in the ->next direction.
-	 * In the ->prev direction, however, the first slave points to bond
-	 * and bond points to the last slave.
-	 *
-	 * It looks like a circle with a little bubble hanging off one side
-	 * in the ->prev direction only.
-	 *
-	 * When going through the list once, its best to start at bond->prev
-	 * and go in the ->prev direction, testing for bond.  Doing this
-	 * in the ->next direction doesn't work.  Trust me, I know this now.
-	 * :)  -mts 2002.03.14
-	 */
-	new_slave->prev       = bond->prev;
-	new_slave->prev->next = new_slave;
-	bond->prev            = new_slave;
-	new_slave->next       = bond->next;
+	struct vlan_entry *next, *last;
 
-	update_slave_cnt(bond, 1);
-}
+	if (list_empty(&bond->vlan_list)) {
+		return NULL;
+	}
 
+	if (!curr) {
+		next = list_entry(bond->vlan_list.next,
+				  struct vlan_entry, vlan_list);
+	} else {
+		last = list_entry(bond->vlan_list.prev,
+				  struct vlan_entry, vlan_list);
+		if (last == curr) {
+			next = list_entry(bond->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		} else {
+			next = list_entry(curr->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		}
+	}
 
-/*
- * Less bad way to call ioctl from within the kernel; this needs to be
- * done some other way to get the call out of interrupt context.
- * Needs "ioctl" variable to be supplied by calling context.
- */
-#define IOCTL(dev, arg, cmd) ({		\
-	int ret;			\
-	mm_segment_t fs = get_fs();	\
-	set_fs(get_ds());		\
-	ret = ioctl(dev, arg, cmd);	\
-	set_fs(fs);			\
-	ret; })
+	return next;
+}
 
-/*
- * Get link speed and duplex from the slave's base driver
- * using ethtool. If for some reason the call fails or the
- * values are invalid, fake speed and duplex to 100/Full
- * and return error.
+/**
+ * bond_dev_queue_xmit - Prepare skb for xmit.
+ * 
+ * @bond: bond device that got this skb for tx.
+ * @skb: hw accel VLAN tagged skb to transmit
+ * @slave_dev: slave that is supposed to xmit this skbuff
+ * 
+ * When the bond gets an skb to tarnsmit that is
+ * already hardware accelerated VLAN tagged, and it
+ * needs to relay this skb to a slave that is not
+ * hw accel capable, the skb needs to be "unaccelerated",
+ * i.e. strip the hwaccel tag and re-insert it as part
+ * of the payload.
+ * 
+ * Assumption - once a VLAN device is created over the bond device, all
+ * packets are going to be hardware accelerated VLAN tagged since the IP
+ * binding is done over the VLAN device
  */
-static int bond_update_speed_duplex(struct slave *slave)
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
 {
-	struct net_device *dev = slave->dev;
-	static int (* ioctl)(struct net_device *, struct ifreq *, int);
-	struct ifreq ifr;
-	struct ethtool_cmd etool;
+	unsigned short vlan_id;
+	int res;
 
-	ioctl = dev->do_ioctl;
-	if (ioctl) {
-		etool.cmd = ETHTOOL_GSET;
-		ifr.ifr_data = (char*)&etool;
-		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
-			slave->speed = etool.speed;
-			slave->duplex = etool.duplex;
-		} else {
-			goto err_out;
+	if (!list_empty(&bond->vlan_list) &&
+	    !(slave_dev->features & NETIF_F_HW_VLAN_TX)) {
+		res = vlan_get_tag(skb, &vlan_id);
+		if (res) {
+			return -EINVAL;
 		}
-	} else {
-		goto err_out;
-	}
 
-	switch (slave->speed) {
-		case SPEED_10:
-		case SPEED_100:
-		case SPEED_1000:
-			break;
-		default:
-			goto err_out;
+		skb->dev = slave_dev;
+		skb = vlan_put_tag(skb, vlan_id);
+		if (!skb) {
+			/* vlan_put_tag() frees the skb in case of error,
+			 * so return success here so the calling functions
+			 * won't attempt to free is again.
+			 */
+			return 0;
+		}
+	} else {
+		skb->dev = slave_dev;
 	}
 
-	switch (slave->duplex) {
-		case DUPLEX_FULL:
-		case DUPLEX_HALF:
-			break;
-		default:
-			goto err_out;
-	}
+	skb->priority = 1;
+	dev_queue_xmit(skb);
 
 	return 0;
-
-err_out:
-	/* Fake speed and duplex */
-	slave->speed = SPEED_100;
-	slave->duplex = DUPLEX_FULL;
-	return -1;
 }
 
-/* 
- * if <dev> supports MII link status reporting, check its link status.
- *
- * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
- * depening upon the setting of the use_carrier parameter.
- *
- * Return either BMSR_LSTATUS, meaning that the link is up (or we
- * can't tell and just pretend it is), or 0, meaning that the link is
- * down.
- *
- * If reporting is non-zero, instead of faking link up, return -1 if
- * both ETHTOOL and MII ioctls fail (meaning the device does not
- * support them).  If use_carrier is set, return whatever it says.
- * It'd be nice if there was a good way to tell if a driver supports
- * netif_carrier, but there really isn't.
+/*
+ * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
+ * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
+ * lock because:
+ * a. This operation is performed in IOCTL context,
+ * b. The operation is protected by the RTNL semaphore in the 8021q code,
+ * c. Holding a lock with BH disabled while directly calling a base driver
+ *    entry point is generally a BAD idea.
+ * 
+ * The design of synchronization/protection for this operation in the 8021q
+ * module is good for one or more VLAN devices over a single physical device
+ * and cannot be extended for a teaming solution like bonding, so there is a
+ * potential race condition here where a net device from the vlan group might
+ * be referenced (either by a base driver or the 8021q code) while it is being
+ * removed from the system. However, it turns out we're not making matters
+ * worse, and if it works for regular VLAN usage it will work here too.
+*/
+
+/**
+ * bond_vlan_rx_register - Propagates registration to slaves
+ * @bond_dev: bonding net device that got called
+ * @grp: vlan group being registered
  */
-static int
-bond_check_dev_link(struct net_device *dev, int reporting)
+static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp)
 {
-	static int (* ioctl)(struct net_device *, struct ifreq *, int);
-	struct ifreq ifr;
-	struct mii_ioctl_data *mii;
-	struct ethtool_value etool;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i;
 
-	if (use_carrier) {
-		return netif_carrier_ok(dev) ? BMSR_LSTATUS : 0;
+	bond->vlgrp = grp;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+		    slave_dev->vlan_rx_register) {
+			slave_dev->vlan_rx_register(slave_dev, grp);
+		}
 	}
+}
 
-	ioctl = dev->do_ioctl;
-	if (ioctl) {
-		/* TODO: set pointer to correct ioctl on a per team member */
-		/*       bases to make this more efficient. that is, once  */
-		/*       we determine the correct ioctl, we will always    */
-		/*       call it and not the others for that team          */
-		/*       member.                                           */
+/**
+ * bond_vlan_rx_add_vid - Propagates adding an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being added
+ */
+static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i, res;
 
-		/*
-		 * We cannot assume that SIOCGMIIPHY will also read a
-		 * register; not all network drivers (e.g., e100)
-		 * support that.
-		 */
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
 
-		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
-		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
-		if (IOCTL(dev, &ifr, SIOCGMIIPHY) == 0) {
-			mii->reg_num = MII_BMSR;
-			if (IOCTL(dev, &ifr, SIOCGMIIREG) == 0) {
-				return mii->val_out & BMSR_LSTATUS;
-			}
-		}
-
-		/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
-		/* for a period of time so we attempt to get link status   */
-		/* from it last if the above MII ioctls fail...            */
-	        etool.cmd = ETHTOOL_GLINK;
-	        ifr.ifr_data = (char*)&etool;
-		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
-			if (etool.data == 1) {
-				return BMSR_LSTATUS;
-			} else { 
-#ifdef BONDING_DEBUG
-				printk(KERN_INFO 
-					":: SIOCETHTOOL shows link down \n");
-#endif
-				return 0;
-			} 
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_add_vid) {
+			slave_dev->vlan_rx_add_vid(slave_dev, vid);
 		}
+	}
 
+	res = bond_add_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to add vlan id %d\n",
+		       bond_dev->name, vid);
 	}
- 
-	/*
-	 * If reporting, report that either there's no dev->do_ioctl,
-	 * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we
-	 * cannot report link status).  If not reporting, pretend
-	 * we're ok.
-	 */
-	return reporting ? -1 : BMSR_LSTATUS;
 }
 
-static u16 bond_check_mii_link(bonding_t *bond)
+/**
+ * bond_vlan_rx_kill_vid - Propagates deleting an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being removed
+ */
+static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
 {
-	int has_active_interface = 0;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	struct net_device *vlan_dev;
+	int i, res;
 
-	read_lock_bh(&bond->lock);
-	read_lock(&bond->ptrlock);
-	has_active_interface = (bond->current_slave != NULL);
-	read_unlock(&bond->ptrlock);
-	read_unlock_bh(&bond->lock);
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_kill_vid) {
+			/* Save and then restore vlan_dev in the grp array,
+			 * since the slave's driver might clear it.
+			 */
+			vlan_dev = bond->vlgrp->vlan_devices[vid];
+			slave_dev->vlan_rx_kill_vid(slave_dev, vid);
+			bond->vlgrp->vlan_devices[vid] = vlan_dev;
+		}
+	}
 
-	return (has_active_interface ? BMSR_LSTATUS : 0);
+	res = bond_del_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to remove vlan id %d\n",
+		       bond_dev->name, vid);
+	}
 }
 
-/* register to receive lacpdus on a bond */
-static void bond_register_lacpdu(struct bonding *bond)
+static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
 {
-	struct packet_type* pk_type = &(BOND_AD_INFO(bond).ad_pkt_type);
+	struct vlan_entry *vlan;
 
-	/* initialize packet type */
-	pk_type->type = PKT_TYPE_LACPDU;
-	pk_type->dev = bond->device;
-	pk_type->func = bond_3ad_lacpdu_recv;
-	pk_type->data = (void*)1;  /* understand shared skbs */
+	write_lock_bh(&bond->lock);
 
-	dev_add_pack(pk_type);
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, bond->vlgrp);
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_add_vid)) {
+		goto out;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
 }
 
-/* unregister to receive lacpdus on a bond */
-static void bond_unregister_lacpdu(struct bonding *bond)
+static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev)
 {
-	dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
+	struct vlan_entry *vlan;
+	struct net_device *vlan_dev;
+
+	write_lock_bh(&bond->lock);
+
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_kill_vid)) {
+		goto unreg;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		/* Save and then restore vlan_dev in the grp array,
+		 * since the slave's driver might clear it.
+		 */
+		vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+		slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
+		bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev;
+	}
+
+unreg:
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, NULL);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
 }
 
-static int bond_open(struct net_device *dev)
+/*------------------------------- Link status -------------------------------*/
+
+/*
+ * Get link speed and duplex from the slave's base driver
+ * using ethtool. If for some reason the call fails or the
+ * values are invalid, fake speed and duplex to 100/Full
+ * and return error.
+ */
+static int bond_update_speed_duplex(struct slave *slave)
 {
-	struct bonding *bond = (struct bonding *)(dev->priv);
-	struct timer_list *timer = &((struct bonding *)(dev->priv))->mii_timer;
-	struct timer_list *arp_timer = &((struct bonding *)(dev->priv))->arp_timer;
+	struct net_device *slave_dev = slave->dev;
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	struct ifreq ifr;
+	struct ethtool_cmd etool;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
+	/* Fake speed and duplex */
+	slave->speed = SPEED_100;
+	slave->duplex = DUPLEX_FULL;
 
-		/* bond_alb_initialize must be called before the timer
-		 * is started.
-		 */
-		if (bond_alb_initialize(bond, (bond_mode == BOND_MODE_ALB))) {
-			/* something went wrong - fail the open operation */
+	if (slave_dev->ethtool_ops) {
+		u32 res;
+
+		if (!slave_dev->ethtool_ops->get_settings) {
 			return -1;
 		}
 
-		init_timer(alb_timer);
-		alb_timer->expires  = jiffies + 1;
-		alb_timer->data     = (unsigned long)bond;
-		alb_timer->function = (void *)&bond_alb_monitor;
-		add_timer(alb_timer);
-	}
+		res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+		if (res < 0) {
+			return -1;
+		}
 
-	if (miimon > 0) {  /* link check interval, in milliseconds. */
-		init_timer(timer);
-		timer->expires  = jiffies + (miimon * HZ / 1000);
-		timer->data     = (unsigned long)dev;
-		timer->function = (void *)&bond_mii_monitor;
-		add_timer(timer);
+		goto verify;
 	}
 
-	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
-		init_timer(arp_timer);
-		arp_timer->expires  = jiffies + (arp_interval * HZ / 1000);
-		arp_timer->data     = (unsigned long)dev;
-		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-			arp_timer->function = (void *)&activebackup_arp_monitor;
-		} else {
-			arp_timer->function = (void *)&loadbalance_arp_monitor;
-		}
-		add_timer(arp_timer);
+	ioctl = slave_dev->do_ioctl;
+	strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+	etool.cmd = ETHTOOL_GSET;
+	ifr.ifr_data = (char*)&etool;
+	if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) {
+		return -1;
+	}
+
+verify:
+	switch (etool.speed) {
+	case SPEED_10:
+	case SPEED_100:
+	case SPEED_1000:
+		break;
+	default:
+		return -1;
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
-		init_timer(ad_timer);
-		ad_timer->expires  = jiffies + (AD_TIMER_INTERVAL * HZ / 1000);
-		ad_timer->data     = (unsigned long)bond;
-		ad_timer->function = (void *)&bond_3ad_state_machine_handler;
-		add_timer(ad_timer);
-
-		/* register to receive LACPDUs */
-		bond_register_lacpdu(bond);
+	switch (etool.duplex) {
+	case DUPLEX_FULL:
+	case DUPLEX_HALF:
+		break;
+	default:
+		return -1;
 	}
 
+	slave->speed = etool.speed;
+	slave->duplex = etool.duplex;
+
 	return 0;
 }
 
-static int bond_close(struct net_device *master)
+/*
+ * if <dev> supports MII link status reporting, check its link status.
+ *
+ * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
+ * depening upon the setting of the use_carrier parameter.
+ *
+ * Return either BMSR_LSTATUS, meaning that the link is up (or we
+ * can't tell and just pretend it is), or 0, meaning that the link is
+ * down.
+ *
+ * If reporting is non-zero, instead of faking link up, return -1 if
+ * both ETHTOOL and MII ioctls fail (meaning the device does not
+ * support them).  If use_carrier is set, return whatever it says.
+ * It'd be nice if there was a good way to tell if a driver supports
+ * netif_carrier, but there really isn't.
+ */
+static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
 {
-	bonding_t *bond = (struct bonding *) master->priv;
-
-	write_lock_bh(&bond->lock);
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	struct ifreq ifr;
+	struct mii_ioctl_data *mii;
+	struct ethtool_value etool;
 
-	if (miimon > 0) {  /* link check interval, in milliseconds. */
-		del_timer(&bond->mii_timer);
-	}
-	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
-		del_timer(&bond->arp_timer);
-                if (arp_target_hw_addr != NULL) {
-			kfree(arp_target_hw_addr); 
-			arp_target_hw_addr = NULL;
-		}
+	if (bond->params.use_carrier) {
+		return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
+	ioctl = slave_dev->do_ioctl;
+	if (ioctl) {
+		/* TODO: set pointer to correct ioctl on a per team member */
+		/*       bases to make this more efficient. that is, once  */
+		/*       we determine the correct ioctl, we will always    */
+		/*       call it and not the others for that team          */
+		/*       member.                                           */
 
-		/* Unregister the receive of LACPDUs */
-		bond_unregister_lacpdu(bond);
-	}
+		/*
+		 * We cannot assume that SIOCGMIIPHY will also read a
+		 * register; not all network drivers (e.g., e100)
+		 * support that.
+		 */
 
-	bond_mc_list_destroy (bond);
+		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
+		if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
+			mii->reg_num = MII_BMSR;
+			if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0) {
+				return (mii->val_out & BMSR_LSTATUS);
+			}
+		}
+	}
 
-	write_unlock_bh(&bond->lock);
+	/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
+	/* for a period of time so we attempt to get link status   */
+	/* from it last if the above MII ioctls fail...            */
+	if (slave_dev->ethtool_ops) {
+		if (slave_dev->ethtool_ops->get_link) {
+			u32 link;
 
-	/* Release the bonded slaves */
-	bond_release_all(master);
+			link = slave_dev->ethtool_ops->get_link(slave_dev);
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer));
+			return link ? BMSR_LSTATUS : 0;
+		}
+	}
 
-		bond_alb_deinitialize(bond);
+	if (ioctl) {
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+		etool.cmd = ETHTOOL_GLINK;
+		ifr.ifr_data = (char*)&etool;
+		if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
+			if (etool.data == 1) {
+				return BMSR_LSTATUS;
+			} else {
+				dprintk("SIOCETHTOOL shows link down\n");
+				return 0;
+			}
+		}
 	}
 
-	return 0;
+	/*
+	 * If reporting, report that either there's no dev->do_ioctl,
+	 * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we
+	 * cannot report link status).  If not reporting, pretend
+	 * we're ok.
+	 */
+	return (reporting ? -1 : BMSR_LSTATUS);
 }
 
-/* 
- * flush all members of flush->mc_list from device dev->mc_list
+/*----------------------------- Multicast list ------------------------------*/
+
+/*
+ * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
  */
-static void bond_mc_list_flush(struct net_device *dev, struct net_device *flush)
-{ 
-	struct dev_mc_list *dmi; 
- 
-	for (dmi = flush->mc_list; dmi != NULL; dmi = dmi->next) 
-		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+static inline int bond_is_dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
+{
+	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
+			dmi1->dmi_addrlen == dmi2->dmi_addrlen;
+}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		/* del lacpdu mc addr from mc list */
-		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+/*
+ * returns dmi entry if found, NULL otherwise
+ */
+static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list)
+{
+	struct dev_mc_list *idmi;
 
-		dev_mc_delete(dev, lacpdu_multicast, ETH_ALEN, 0);
+	for (idmi = mc_list; idmi; idmi = idmi->next) {
+		if (bond_is_dmi_same(dmi, idmi)) {
+			return idmi;
+		}
 	}
+
+	return NULL;
 }
 
 /*
- * Totally destroys the mc_list in bond
+ * Push the promiscuity flag down to appropriate slaves
  */
-static void bond_mc_list_destroy(struct bonding *bond)
+static void bond_set_promiscuity(struct bonding *bond, int inc)
 {
-	struct dev_mc_list *dmi;
+	if (USES_PRIMARY(bond->params.mode)) {
+		/* write lock already acquired */
+		if (bond->curr_active_slave) {
+			dev_set_promiscuity(bond->curr_active_slave->dev, inc);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
+			dev_set_promiscuity(slave->dev, inc);
+		}
+	}
+}
 
-	dmi = bond->mc_list; 
-	while (dmi) { 
-		bond->mc_list = dmi->next; 
-		kfree(dmi); 
-		dmi = bond->mc_list; 
+/*
+ * Push the allmulti flag down to all slaves
+ */
+static void bond_set_allmulti(struct bonding *bond, int inc)
+{
+	if (USES_PRIMARY(bond->params.mode)) {
+		/* write lock already acquired */
+		if (bond->curr_active_slave) {
+			dev_set_allmulti(bond->curr_active_slave->dev, inc);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
+			dev_set_allmulti(slave->dev, inc);
+		}
 	}
 }
 
 /*
- * Add a Multicast address to every slave in the bonding group
+ * Add a Multicast address to slaves
+ * according to mode
  */
-static void bond_mc_add(bonding_t *bond, void *addr, int alen)
-{ 
-	slave_t *slave;
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
+static void bond_mc_add(struct bonding *bond, void *addr, int alen)
+{
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_mc_add(bond->current_slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+		if (bond->curr_active_slave) {
+			dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
 			dev_mc_add(slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
+		}
 	}
-} 
+}
 
 /*
- * Remove a multicast address from every slave in the bonding group
+ * Remove a multicast address from slave
+ * according to mode
  */
-static void bond_mc_delete(bonding_t *bond, void *addr, int alen)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
+static void bond_mc_delete(struct bonding *bond, void *addr, int alen)
+{
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_mc_delete(bond->current_slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+		if (bond->curr_active_slave) {
+			dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
 			dev_mc_delete(slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
+		}
+	}
+}
+
+/*
+ * Totally destroys the mc_list in bond
+ */
+static void bond_mc_list_destroy(struct bonding *bond)
+{
+	struct dev_mc_list *dmi;
+
+	dmi = bond->mc_list;
+	while (dmi) {
+		bond->mc_list = dmi->next;
+		kfree(dmi);
+		dmi = bond->mc_list;
 	}
-} 
+}
 
 /*
  * Copy all the Multicast addresses from src to the bonding device dst
  */
-static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst,
- int gpf_flag)
+static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, int gpf_flag)
 {
 	struct dev_mc_list *dmi, *new_dmi;
 
-   	for (dmi = src; dmi != NULL; dmi = dmi->next) { 
+	for (dmi = mc_list; dmi; dmi = dmi->next) {
 		new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag);
 
-		if (new_dmi == NULL) {
-			return -ENOMEM; 
+		if (!new_dmi) {
+			/* FIXME: Potential memory leak !!! */
+			return -ENOMEM;
 		}
 
-		new_dmi->next = dst->mc_list; 
-		dst->mc_list = new_dmi;
-
-		new_dmi->dmi_addrlen = dmi->dmi_addrlen; 
-		memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); 
+		new_dmi->next = bond->mc_list;
+		bond->mc_list = new_dmi;
+		new_dmi->dmi_addrlen = dmi->dmi_addrlen;
+		memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen);
 		new_dmi->dmi_users = dmi->dmi_users;
-		new_dmi->dmi_gusers = dmi->dmi_gusers; 
-	} 
+		new_dmi->dmi_gusers = dmi->dmi_gusers;
+	}
+
 	return 0;
 }
 
 /*
- * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
- */
-static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
-{ 
-	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
-	 dmi1->dmi_addrlen == dmi2->dmi_addrlen;
-} 
-
-/*
- * Push the promiscuity flag down to appropriate slaves
+ * flush all members of flush->mc_list from device dev->mc_list
  */
-static void bond_set_promiscuity(bonding_t *bond, int inc)
-{ 
-	slave_t *slave; 
-
-	if (USES_PRIMARY(bond_mode)) {
-		if (bond->current_slave) {
-			dev_set_promiscuity(bond->current_slave->dev, inc);
-		}
+static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct dev_mc_list *dmi;
 
-	} else { 
-		for (slave = bond->prev; slave != (slave_t*)bond;
-		     slave = slave->prev) {
-			dev_set_promiscuity(slave->dev, inc);
-		}
+	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
+		dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
 	}
-} 
 
-/*
- * Push the allmulti flag down to all slaves
- */
-static void bond_set_allmulti(bonding_t *bond, int inc)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE : 
-		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_set_allmulti(bond->current_slave->dev, inc);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
-			dev_set_allmulti(slave->dev, inc);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		/* del lacpdu mc addr from mc list */
+		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+
+		dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0);
 	}
-} 
+}
+
+/*--------------------------- Active slave change ---------------------------*/
 
-/* 
- * returns dmi entry if found, NULL otherwise 
+/*
+ * Update the mc list and multicast-related flags for the new and
+ * old active slaves (if any) according to the multicast mode, and
+ * promiscuous flags unconditionally.
  */
-static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi,
- struct dev_mc_list *mc_list)
-{ 
-	struct dev_mc_list *idmi;
+static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active)
+{
+	struct dev_mc_list *dmi;
+
+	if (!USES_PRIMARY(bond->params.mode)) {
+		/* nothing to do -  mc list is already up-to-date on
+		 * all slaves
+		 */
+		return;
+	}
+
+	if (old_active) {
+		if (bond->dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(old_active->dev, -1);
+		}
 
-	for (idmi = mc_list; idmi != NULL; idmi = idmi->next) {
-		if (dmi_same(dmi, idmi)) {
-			return idmi; 
+		if (bond->dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(old_active->dev, -1);
+		}
+
+		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
+			dev_mc_delete(old_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
 		}
 	}
-	return NULL;
-} 
 
-static void set_multicast_list(struct net_device *master)
+	if (new_active) {
+		if (bond->dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(new_active->dev, 1);
+		}
+
+		if (bond->dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(new_active->dev, 1);
+		}
+
+		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
+			dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+		}
+	}
+}
+
+/**
+ * find_best_interface - select the best available slave to be the active one
+ * @bond: our bonding struct
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static struct slave *bond_find_best_slave(struct bonding *bond)
 {
-	bonding_t *bond = master->priv;
-	struct dev_mc_list *dmi;
+	struct slave *new_active, *old_active;
+	struct slave *bestslave = NULL;
+	int mintime = bond->params.updelay;
+	int i;
 
-	write_lock_bh(&bond->lock);
+	new_active = old_active = bond->curr_active_slave;
 
-	/*
-	 * Do promisc before checking multicast_mode
+	if (!new_active) { /* there were no active slaves left */
+		if (bond->slave_cnt > 0) {  /* found one slave */
+			new_active = bond->first_slave;
+		} else {
+			return NULL; /* still no slave, return NULL */
+		}
+	}
+
+	/* first try the primary link; if arping, a link must tx/rx traffic
+	 * before it can be considered the curr_active_slave - also, we would skip
+	 * slaves between the curr_active_slave and primary_slave that may be up
+	 * and able to arp
 	 */
-	if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
-		bond_set_promiscuity(bond, 1); 
+	if ((bond->primary_slave) &&
+	    (!bond->params.arp_interval) &&
+	    (IS_UP(bond->primary_slave->dev))) {
+		new_active = bond->primary_slave;
+	}
 
-	if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) ) 
-		bond_set_promiscuity(bond, -1); 
+	/* remember where to stop iterating over the slaves */
+	old_active = new_active;
 
-	if (multicast_mode == BOND_MULTICAST_DISABLED) {
-		bond->flags = master->flags;
-		write_unlock_bh(&bond->lock);
+	bond_for_each_slave_from(bond, new_active, i, old_active) {
+		if (IS_UP(new_active->dev)) {
+			if (new_active->link == BOND_LINK_UP) {
+				return new_active;
+			} else if (new_active->link == BOND_LINK_BACK) {
+				/* link up, but waiting for stabilization */
+				if (new_active->delay < mintime) {
+					mintime = new_active->delay;
+					bestslave = new_active;
+				}
+			}
+		}
+	}
+
+	return bestslave;
+}
+
+/**
+ * change_active_interface - change the active slave into the specified one
+ * @bond: our bonding struct
+ * @new: the new slave to make the active one
+ *
+ * Set the new slave to the bond's settings and unset them on the old
+ * curr_active_slave.
+ * Setting include flags, mc-list, promiscuity, allmulti, etc.
+ *
+ * If @new's link state is %BOND_LINK_BACK we'll set it to %BOND_LINK_UP,
+ * because it is apparently the best available slave we have, even though its
+ * updelay hasn't timed out yet.
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
+{
+	struct slave *old_active = bond->curr_active_slave;
+
+	if (old_active == new_active) {
 		return;
 	}
 
-	/* set allmulti flag to slaves */ 
-	if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) ) 
-		bond_set_allmulti(bond, 1); 
+	if (new_active) {
+		if (new_active->link == BOND_LINK_BACK) {
+			if (USES_PRIMARY(bond->params.mode)) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: making interface %s the new "
+				       "active one %d ms earlier.\n",
+				       bond->dev->name, new_active->dev->name,
+				       (bond->params.updelay - new_active->delay) * bond->params.miimon);
+			}
+
+			new_active->delay = 0;
+			new_active->link = BOND_LINK_UP;
+			new_active->jiffies = jiffies;
 
-	if ( !(master->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI) )
-		bond_set_allmulti(bond, -1); 
+			if (bond->params.mode == BOND_MODE_8023AD) {
+				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
+			}
 
-	bond->flags = master->flags; 
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
+				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
+			}
+		} else {
+			if (USES_PRIMARY(bond->params.mode)) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: making interface %s the new "
+				       "active one.\n",
+				       bond->dev->name, new_active->dev->name);
+			}
+		}
+	}
 
-	/* looking for addresses to add to slaves' mc list */ 
-	for (dmi = master->mc_list; dmi != NULL; dmi = dmi->next) { 
-		if (bond_mc_list_find_dmi(dmi, bond->mc_list) == NULL) 
-		 bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
-	} 
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+		if (old_active) {
+			bond_set_slave_inactive_flags(old_active);
+		}
 
-	/* looking for addresses to delete from slaves' list */ 
-	for (dmi = bond->mc_list; dmi != NULL; dmi = dmi->next) { 
-		if (bond_mc_list_find_dmi(dmi, master->mc_list) == NULL) 
-		 bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
+		if (new_active) {
+			bond_set_slave_active_flags(new_active);
+		}
 	}
 
+	if (USES_PRIMARY(bond->params.mode)) {
+		bond_mc_swap(bond, new_active, old_active);
+	}
 
-	/* save master's multicast list */ 
-	bond_mc_list_destroy (bond);
-	bond_mc_list_copy (master->mc_list, bond, GFP_ATOMIC);
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		bond_alb_handle_active_change(bond, new_active);
+	} else {
+		bond->curr_active_slave = new_active;
+	}
+}
 
-	write_unlock_bh(&bond->lock);
+/**
+ * bond_select_active_slave - select a new active slave, if needed
+ * @bond: our bonding struct
+ *
+ * This functions shoud be called when one of the following occurs:
+ * - The old curr_active_slave has been released or lost its link.
+ * - The primary_slave has got its link back.
+ * - A slave has got its link back and there's no old curr_active_slave.
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static void bond_select_active_slave(struct bonding *bond)
+{
+	struct slave *best_slave;
+
+	best_slave = bond_find_best_slave(bond);
+	if (best_slave != bond->curr_active_slave) {
+		bond_change_active_slave(bond, best_slave);
+	}
 }
 
+/*--------------------------- slave list handling ---------------------------*/
+
 /*
- * Update the mc list and multicast-related flags for the new and 
- * old active slaves (if any) according to the multicast mode, and
- * promiscuous flags unconditionally.
+ * This function attaches the slave to the end of list.
+ *
+ * bond->lock held for writing by caller.
  */
-static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old)
+static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
 {
-	struct dev_mc_list *dmi;
+	if (bond->first_slave == NULL) { /* attaching the first slave */
+		new_slave->next = new_slave;
+		new_slave->prev = new_slave;
+		bond->first_slave = new_slave;
+	} else {
+		new_slave->next = bond->first_slave;
+		new_slave->prev = bond->first_slave->prev;
+		new_slave->next->prev = new_slave;
+		new_slave->prev->next = new_slave;
+	}
 
-	if (USES_PRIMARY(bond_mode)) {
-		if (bond->device->flags & IFF_PROMISC) {
-			if (old)
-				dev_set_promiscuity(old->dev, -1);
-			if (new)
-				dev_set_promiscuity(new->dev, 1);
-		}
+	bond->slave_cnt++;
+}
+
+/*
+ * This function detaches the slave from the list.
+ * WARNING: no check is made to verify if the slave effectively
+ * belongs to <bond>.
+ * Nothing is freed on return, structures are just unchained.
+ * If any slave pointer in bond was pointing to <slave>,
+ * it should be changed by the calling function.
+ *
+ * bond->lock held for writing by caller.
+ */
+static void bond_detach_slave(struct bonding *bond, struct slave *slave)
+{
+	if (slave->next) {
+		slave->next->prev = slave->prev;
 	}
 
-	switch(multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :		
-		if (bond->device->flags & IFF_ALLMULTI) {
-			if (old)
-				dev_set_allmulti(old->dev, -1);
-			if (new)
-				dev_set_allmulti(new->dev, 1);
-		}
-		/* first remove all mc addresses from old slave if any,
-		   and _then_ add them to new active slave */
-		if (old) {
-			for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
-				dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		}
-		if (new) {
-			for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
-				dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+	if (slave->prev) {
+		slave->prev->next = slave->next;
+	}
+
+	if (bond->first_slave == slave) { /* slave is the first slave */
+		if (bond->slave_cnt > 1) { /* there are more slave */
+			bond->first_slave = slave->next;
+		} else {
+			bond->first_slave = NULL; /* slave was the last one */
 		}
-		break;
-	case BOND_MULTICAST_ALL :
-		/* nothing to do: mc list is already up-to-date on all slaves */
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
 	}
+
+	slave->next = NULL;
+	slave->prev = NULL;
+	bond->slave_cnt--;
+}
+
+/*---------------------------------- IOCTL ----------------------------------*/
+
+static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+{
+	dprintk("bond_dev=%p\n", bond_dev);
+	dprintk("slave_dev=%p\n", slave_dev);
+	dprintk("slave_dev->addr_len=%d\n", slave_dev->addr_len);
+	memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len);
+	return 0;
 }
 
 /* enslave device <slave> to bond device <master> */
-static int bond_enslave(struct net_device *master_dev, 
-                        struct net_device *slave_dev)
+static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 {
-	bonding_t *bond = NULL;
-	slave_t *new_slave = NULL;
-	unsigned long rflags = 0;
-	int err = 0;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *new_slave = NULL;
 	struct dev_mc_list *dmi;
-	struct in_ifaddr **ifap;
-	struct in_ifaddr *ifa;
-	int link_reporting;
 	struct sockaddr addr;
-
-	if (master_dev == NULL || slave_dev == NULL) {
-		return -ENODEV;
-	}
-	bond = (struct bonding *) master_dev->priv;
+	int link_reporting;
+	int old_features = bond_dev->features;
+	int res = 0;
 
 	if (slave_dev->do_ioctl == NULL) {
-		printk(KERN_DEBUG
-			"Warning : no link monitoring support for %s\n",
-			slave_dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning : no link monitoring support for %s\n",
+		       slave_dev->name);
 	}
 
-
 	/* bond must be initialized by bond_open() before enslaving */
-	if (!(master_dev->flags & IFF_UP)) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error, master_dev is not up\n");
-#endif
+	if (!(bond_dev->flags & IFF_UP)) {
+		dprintk("Error, master_dev is not up\n");
 		return -EPERM;
 	}
 
 	/* already enslaved */
-	if (master_dev->flags & IFF_SLAVE || slave_dev->flags & IFF_SLAVE) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error, Device was already enslaved\n");
-#endif
+	if (slave_dev->flags & IFF_SLAVE) {
+		dprintk("Error, Device was already enslaved\n");
 		return -EBUSY;
 	}
 
+	/* vlan challenged mutual exclusion */
+	/* no need to lock since we're protected by rtnl_lock */
+	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
+		dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (!list_empty(&bond->vlan_list)) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: cannot enslave VLAN "
+			       "challenged slave %s on VLAN enabled "
+			       "bond %s\n", slave_dev->name,
+			       bond_dev->name);
+			return -EPERM;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: enslaved VLAN challenged "
+			       "slave %s. Adding VLANs will be blocked as "
+			       "long as %s is part of bond %s\n",
+			       slave_dev->name, slave_dev->name,
+			       bond_dev->name);
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		}
+	} else {
+		dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (bond->slave_cnt == 0) {
+			/* First slave, and it is not VLAN challenged,
+			 * so remove the block of adding VLANs over the bond.
+			 */
+			bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
+		}
+	}
+
 	if (app_abi_ver >= 1) {
 		/* The application is using an ABI, which requires the
 		 * slave interface to be closed.
 		 */
 		if ((slave_dev->flags & IFF_UP)) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Error, slave_dev is up\n");
-#endif
-			return -EPERM;
+			printk(KERN_ERR DRV_NAME
+			       ": Error: %s is up\n",
+			       slave_dev->name);
+			res = -EPERM;
+			goto err_undo_flags;
 		}
 
 		if (slave_dev->set_mac_address == NULL) {
-			printk(KERN_CRIT
-			       "The slave device you specified does not support"
-			       " setting the MAC address.\n");
-			printk(KERN_CRIT
-			       "Your kernel likely does not support slave"
-			       " devices.\n");
+			printk(KERN_ERR DRV_NAME
+			       ": Error: The slave device you specified does "
+			       "not support setting the MAC address.\n");
+			printk(KERN_ERR
+			       "Your kernel likely does not support slave "
+			       "devices.\n");
 
-			return -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	} else {
 		/* The application is not using an ABI, which requires the
 		 * slave interface to be open.
 		 */
 		if (!(slave_dev->flags & IFF_UP)) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Error, slave_dev is not running\n");
-#endif
-			return -EINVAL;
+			printk(KERN_ERR DRV_NAME
+			       ": Error: %s is not running\n",
+			       slave_dev->name);
+			res = -EINVAL;
+			goto err_undo_flags;
 		}
 
-		if ((bond_mode == BOND_MODE_8023AD) ||
-		    (bond_mode == BOND_MODE_TLB) ||
-		    (bond_mode == BOND_MODE_ALB)) {
-			printk(KERN_ERR
-			       "bonding: Error: to use %s mode, you must "
-			       "upgrade ifenslave.\n", bond_mode_name());
-			return -EOPNOTSUPP;
+		if ((bond->params.mode == BOND_MODE_8023AD) ||
+		    (bond->params.mode == BOND_MODE_TLB)    ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: to use %s mode, you must upgrade "
+			       "ifenslave.\n",
+			       bond_mode_name(bond->params.mode));
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	}
 
-	if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
-		return -ENOMEM;
+	new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
+	if (!new_slave) {
+		res = -ENOMEM;
+		goto err_undo_flags;
 	}
-	memset(new_slave, 0, sizeof(slave_t));
+
+	memset(new_slave, 0, sizeof(struct slave));
 
 	/* save slave's original flags before calling
 	 * netdev_set_master and dev_open
@@ -1431,37 +1706,29 @@ static int bond_enslave(struct net_devic
 		 */
 		memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
 
-		if (bond->slave_cnt > 0) {
-			/* set slave to master's mac address
-			 * The application already set the master's
-			 * mac address to that of the first slave
-			 */
-			memcpy(addr.sa_data, master_dev->dev_addr, master_dev->addr_len);
-			addr.sa_family = slave_dev->type;
-			err = slave_dev->set_mac_address(slave_dev, &addr);
-			if (err) {
-#ifdef BONDING_DEBUG
-				printk(KERN_CRIT "Error %d calling set_mac_address\n", err);
-#endif
-				goto err_free;
-			}
+		/* set slave to master's mac address
+		 * The application already set the master's
+		 * mac address to that of the first slave
+		 */
+		memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
+		addr.sa_family = slave_dev->type;
+		res = slave_dev->set_mac_address(slave_dev, &addr);
+		if (res) {
+			dprintk("Error %d calling set_mac_address\n", res);
+			goto err_free;
 		}
 
 		/* open the slave since the application closed it */
-		err = dev_open(slave_dev);
-		if (err) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Openning slave %s failed\n", slave_dev->name);
-#endif
+		res = dev_open(slave_dev);
+		if (res) {
+			dprintk("Openning slave %s failed\n", slave_dev->name);
 			goto err_restore_mac;
 		}
 	}
 
-	err = netdev_set_master(slave_dev, master_dev);
-	if (err) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error %d calling netdev_set_master\n", err);
-#endif
+	res = netdev_set_master(slave_dev, bond_dev);
+	if (res) {
+		dprintk("Error %d calling netdev_set_master\n", res);
 		if (app_abi_ver < 1) {
 			goto err_free;
 		} else {
@@ -1471,56 +1738,59 @@ static int bond_enslave(struct net_devic
 
 	new_slave->dev = slave_dev;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		/* bond_alb_init_slave() must be called before all other stages since
 		 * it might fail and we do not want to have to undo everything
 		 */
-		err = bond_alb_init_slave(bond, new_slave);
-		if (err) {
+		res = bond_alb_init_slave(bond, new_slave);
+		if (res) {
 			goto err_unset_master;
 		}
 	}
 
-	/* set promiscuity level to new slave */ 
-	if (master_dev->flags & IFF_PROMISC) {
-		/* If the mode USES_PRIMARY, then the new slave gets the
-		 * master's promisc (and mc) settings only if it becomes the
-		 * current_slave, and that is taken care of later when calling
-		 * bond_change_active()
-		 */
-		if (!USES_PRIMARY(bond_mode)) {
-			dev_set_promiscuity(slave_dev, 1); 
+	/* If the mode USES_PRIMARY, then the new slave gets the
+	 * master's promisc (and mc) settings only if it becomes the
+	 * curr_active_slave, and that is taken care of later when calling
+	 * bond_change_active()
+	 */
+	if (!USES_PRIMARY(bond->params.mode)) {
+		/* set promiscuity level to new slave */
+		if (bond_dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(slave_dev, 1);
 		}
-	}
- 
-	if (multicast_mode == BOND_MULTICAST_ALL) {
+
 		/* set allmulti level to new slave */
-		if (master_dev->flags & IFF_ALLMULTI) 
-			dev_set_allmulti(slave_dev, 1); 
-		
-		/* upload master's mc_list to new slave */ 
-		for (dmi = master_dev->mc_list; dmi != NULL; dmi = dmi->next) 
+		if (bond_dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(slave_dev, 1);
+		}
+
+		/* upload master's mc_list to new slave */
+		for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
 			dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+		}
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* add lacpdu mc addr to mc list */
 		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
 		dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0);
 	}
 
+	bond_add_vlans_on_slave(bond, slave_dev);
+
 	write_lock_bh(&bond->lock);
-	
+
 	bond_attach_slave(bond, new_slave);
+
 	new_slave->delay = 0;
 	new_slave->link_failure_count = 0;
 
-	if (miimon > 0 && !use_carrier) {
-		link_reporting = bond_check_dev_link(slave_dev, 1);
+	if (bond->params.miimon && !bond->params.use_carrier) {
+		link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
-		if ((link_reporting == -1) && (arp_interval == 0)) {
+		if ((link_reporting == -1) && !bond->params.arp_interval) {
 			/*
 			 * miimon is set but a bonded network driver
 			 * does not support ETHTOOL/MII and
@@ -1529,157 +1799,136 @@ static int bond_enslave(struct net_devic
 			 * here (because netif_carrier is always
 			 * supported); thus, we don't need to change
 			 * the messages for netif_carrier.
-			 */ 
-			printk(KERN_ERR
-				"bond_enslave(): MII and ETHTOOL support not "
-				"available for interface %s, and "
-				"arp_interval/arp_ip_target module parameters "
-		       		"not specified, thus bonding will not detect "
-				"link failures! see bonding.txt for details.\n",
-		       		slave_dev->name);
+			 */
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: MII and ETHTOOL support not "
+			       "available for interface %s, and "
+			       "arp_interval/arp_ip_target module parameters "
+			       "not specified, thus bonding will not detect "
+			       "link failures! see bonding.txt for details.\n",
+			       slave_dev->name);
 		} else if (link_reporting == -1) {
-			/* unable  get link status using mii/ethtool */
-			printk(KERN_WARNING 
-			       "bond_enslave: can't get link status from "
+			/* unable get link status using mii/ethtool */
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: can't get link status from "
 			       "interface %s; the network driver associated "
-			       "with this interface does not support "
-			       "MII or ETHTOOL link status reporting, thus "
-			       "miimon has no effect on this interface.\n", 
+			       "with this interface does not support MII or "
+			       "ETHTOOL link status reporting, thus miimon "
+			       "has no effect on this interface.\n",
 			       slave_dev->name);
 		}
 	}
 
 	/* check for initial state */
-	if ((miimon <= 0) ||
-	    (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) {
-		if (updelay) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Initial state of slave_dev is "
-			       "BOND_LINK_BACK\n");
-#endif
+	if (!bond->params.miimon ||
+	    (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) {
+		if (bond->params.updelay) {
+			dprintk("Initial state of slave_dev is "
+				"BOND_LINK_BACK\n");
 			new_slave->link  = BOND_LINK_BACK;
-			new_slave->delay = updelay;
-		}
-		else {
-#ifdef BONDING_DEBUG
-			printk(KERN_DEBUG "Initial state of slave_dev is "
+			new_slave->delay = bond->params.updelay;
+		} else {
+			dprintk("Initial state of slave_dev is "
 				"BOND_LINK_UP\n");
-#endif
 			new_slave->link  = BOND_LINK_UP;
 		}
 		new_slave->jiffies = jiffies;
-	}
-	else {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Initial state of slave_dev is "
+	} else {
+		dprintk("Initial state of slave_dev is "
 			"BOND_LINK_DOWN\n");
-#endif
 		new_slave->link  = BOND_LINK_DOWN;
 	}
 
 	if (bond_update_speed_duplex(new_slave) &&
 	    (new_slave->link != BOND_LINK_DOWN)) {
-
-		printk(KERN_WARNING
-		       "bond_enslave(): failed to get speed/duplex from %s, "
-		       "speed forced to 100Mbps, duplex forced to Full.\n",
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: failed to get speed/duplex from %s, speed "
+		       "forced to 100Mbps, duplex forced to Full.\n",
 		       new_slave->dev->name);
-		if (bond_mode == BOND_MODE_8023AD) {
+
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			printk(KERN_WARNING
-			       "Operation of 802.3ad mode requires ETHTOOL support "
-			       "in base driver for proper aggregator selection.\n");
+			       "Operation of 802.3ad mode requires ETHTOOL "
+			       "support in base driver for proper aggregator "
+			       "selection.\n");
 		}
 	}
 
-	/* if we're in active-backup mode, we need one and only one active
-	 * interface. The backup interfaces will have their NOARP flag set
-	 * because we need them to be completely deaf and not to respond to
-	 * any ARP request on the network to avoid fooling a switch. Thus,
-	 * since we guarantee that current_slave always point to the last
-	 * usable interface, we just have to verify this interface's flag.
-	 */
-	if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-		if (((bond->current_slave == NULL)
-			|| (bond->current_slave->dev->flags & IFF_NOARP))
-			&& (new_slave->link != BOND_LINK_DOWN)) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "This is the first active slave\n");
-#endif
+	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
+		/* if there is a primary slave, remember it */
+		if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
+			bond->primary_slave = new_slave;
+		}
+	}
+
+	switch (bond->params.mode) {
+	case BOND_MODE_ACTIVEBACKUP:
+		/* if we're in active-backup mode, we need one and only one active
+		 * interface. The backup interfaces will have their NOARP flag set
+		 * because we need them to be completely deaf and not to respond to
+		 * any ARP request on the network to avoid fooling a switch. Thus,
+		 * since we guarantee that curr_active_slave always point to the last
+		 * usable interface, we just have to verify this interface's flag.
+		 */
+		if (((!bond->curr_active_slave) ||
+		     (bond->curr_active_slave->dev->flags & IFF_NOARP)) &&
+		    (new_slave->link != BOND_LINK_DOWN)) {
+			dprintk("This is the first active slave\n");
 			/* first slave or no active slave yet, and this link
 			   is OK, so make this interface the active one */
-			change_active_interface(bond, new_slave);
-		}
-		else {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "This is just a backup slave\n");
-#endif
+			bond_change_active_slave(bond, new_slave);
+		} else {
+			dprintk("This is just a backup slave\n");
 			bond_set_slave_inactive_flags(new_slave);
 		}
-		if (((struct in_device *)slave_dev->ip_ptr) != NULL) {
-			read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags);
-			ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list);
-			ifa = *ifap;
-			if (ifa != NULL)
-				my_ip = ifa->ifa_address;
-			read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags);
-		}
-
-		/* if there is a primary slave, remember it */
-		if (primary != NULL) {
-			if (strcmp(primary, new_slave->dev->name) == 0) {
-				bond->primary_slave = new_slave;
-			}
-		}
-	} else if (bond_mode == BOND_MODE_8023AD) {
+		break;
+	case BOND_MODE_8023AD:
 		/* in 802.3ad mode, the internal mechanism
 		 * will activate the slaves in the selected
 		 * aggregator
 		 */
 		bond_set_slave_inactive_flags(new_slave);
 		/* if this is the first slave */
-		if (new_slave == bond->next) {
+		if (bond->slave_cnt == 1) {
 			SLAVE_AD_INFO(new_slave).id = 1;
 			/* Initialize AD with the number of times that the AD timer is called in 1 second
 			 * can be called only after the mac address of the bond is set
 			 */
 			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
-					    lacp_fast);
+					    bond->params.lacp_fast);
 		} else {
 			SLAVE_AD_INFO(new_slave).id =
-			SLAVE_AD_INFO(new_slave->prev).id + 1;
+				SLAVE_AD_INFO(new_slave->prev).id + 1;
 		}
 
 		bond_3ad_bind_slave(new_slave);
-	} else if ((bond_mode == BOND_MODE_TLB) ||
-		   (bond_mode == BOND_MODE_ALB)) {
+		break;
+	case BOND_MODE_TLB:
+	case BOND_MODE_ALB:
 		new_slave->state = BOND_STATE_ACTIVE;
-		if ((bond->current_slave == NULL) && (new_slave->link != BOND_LINK_DOWN)) {
+		if ((!bond->curr_active_slave) &&
+		    (new_slave->link != BOND_LINK_DOWN)) {
 			/* first slave or no active slave yet, and this link
 			 * is OK, so make this interface the active one
 			 */
-			change_active_interface(bond, new_slave);
+			bond_change_active_slave(bond, new_slave);
 		}
+		break;
+	default:
+		dprintk("This slave is always active in trunk mode\n");
 
-		/* if there is a primary slave, remember it */
-		if (primary != NULL) {
-			if (strcmp(primary, new_slave->dev->name) == 0) {
-				bond->primary_slave = new_slave;
-			}
-		}
-	} else {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "This slave is always active in trunk mode\n");
-#endif
 		/* always active in trunk mode */
 		new_slave->state = BOND_STATE_ACTIVE;
 
-		/* In trunking mode there is little meaning to current_slave
+		/* In trunking mode there is little meaning to curr_active_slave
 		 * anyway (it holds no special properties of the bond device),
 		 * so we can change it without calling change_active_interface()
 		 */
-		if (bond->current_slave == NULL) 
-			bond->current_slave = new_slave;
-	}
+		if (!bond->curr_active_slave) {
+			bond->curr_active_slave = new_slave;
+		}
+		break;
+	} /* switch(bond_mode) */
 
 	write_unlock_bh(&bond->lock);
 
@@ -1693,38 +1942,34 @@ static int bond_enslave(struct net_devic
 		 */
 		int ndx = 0;
 
-		for (ndx = 0; ndx < slave_dev->addr_len; ndx++) {
-#ifdef BONDING_DEBUG
-			printk(KERN_DEBUG
-			       "Checking ndx=%d of master_dev->dev_addr\n", ndx);
-#endif
-			if (master_dev->dev_addr[ndx] != 0) {
-#ifdef BONDING_DEBUG
-				printk(KERN_DEBUG
-				       "Found non-zero byte at ndx=%d\n", ndx);
-#endif
+		for (ndx = 0; ndx < bond_dev->addr_len; ndx++) {
+			dprintk("Checking ndx=%d of bond_dev->dev_addr\n",
+				ndx);
+			if (bond_dev->dev_addr[ndx] != 0) {
+				dprintk("Found non-zero byte at ndx=%d\n",
+					ndx);
 				break;
 			}
 		}
-		if (ndx == slave_dev->addr_len) {
+
+		if (ndx == bond_dev->addr_len) {
 			/*
 			 * We got all the way through the address and it was
 			 * all 0's.
 			 */
-#ifdef BONDING_DEBUG
-			printk(KERN_DEBUG "%s doesn't have a MAC address yet.  ",
-			       master_dev->name);
-			printk(KERN_DEBUG "Going to give assign it from %s.\n",
-			       slave_dev->name);
-#endif
-			bond_sethwaddr(master_dev, slave_dev);
+			dprintk("%s doesn't have a MAC address yet.  \n",
+				bond_dev->name);
+			dprintk("Going to give assign it from %s.\n",
+				slave_dev->name);
+			bond_sethwaddr(bond_dev, slave_dev);
 		}
 	}
 
-	printk (KERN_INFO "%s: enslaving %s as a%s interface with a%s link.\n",
-		master_dev->name, slave_dev->name,
-		new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
-		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
+	printk(KERN_INFO DRV_NAME
+	       ": %s: enslaving %s as a%s interface with a%s link.\n",
+	       bond_dev->name, slave_dev->name,
+	       new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
+	       new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
 
 	/* enslave is successful */
 	return 0;
@@ -1743,435 +1988,235 @@ err_restore_mac:
 
 err_free:
 	kfree(new_slave);
-	return err;
+
+err_undo_flags:
+	bond_dev->features = old_features;
+
+	return res;
 }
 
-/* 
- * This function changes the active slave to slave <slave_dev>.
- * It returns -EINVAL in the following cases.
- *  - <slave_dev> is not found in the list.
- *  - There is not active slave now.
- *  - <slave_dev> is already active.
- *  - The link state of <slave_dev> is not BOND_LINK_UP.
- *  - <slave_dev> is not running.
- * In these cases, this fuction does nothing.
- * In the other cases, currnt_slave pointer is changed and 0 is returned.
+/*
+ * Try to release the slave device <slave> from the bond device <master>
+ * It is legal to access curr_active_slave without a lock because all the function
+ * is write-locked.
+ *
+ * The rules for slave state should be:
+ *   for Active/Backup:
+ *     Active stays on all backups go down
+ *   for Bonded connections:
+ *     The first up interface should be left on and all others downed.
  */
-static int bond_change_active(struct net_device *master_dev, struct net_device *slave_dev)
+static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 {
-	bonding_t *bond;
-	slave_t *slave;
-	slave_t *oldactive = NULL;
-	slave_t *newactive = NULL;
-	int ret = 0;
-
-	if (master_dev == NULL || slave_dev == NULL) {
-		return -ENODEV;
-	}
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave, *oldcurrent;
+	struct sockaddr addr;
+	int mac_addr_differ;
 
-	/* Verify that master_dev is indeed the master of slave_dev */
+	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
-	    (slave_dev->master != master_dev)) {
-
+	    (slave_dev->master != bond_dev)) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: %s: cannot release %s.\n",
+		       bond_dev->name, slave_dev->name);
 		return -EINVAL;
 	}
 
-	bond = (struct bonding *) master_dev->priv;
 	write_lock_bh(&bond->lock);
-	slave = (slave_t *)bond;
-	oldactive = bond->current_slave;
-
-	while ((slave = slave->prev) != (slave_t *)bond) {
-		if(slave_dev == slave->dev) {
-			newactive = slave;
-			break;
-		}
-	}
 
-	/*
-	 * Changing to the current active: do nothing; return success.
-	 */
-	if (newactive && (newactive == oldactive)) {
-		write_unlock_bh(&bond->lock);
-		return 0;
+	slave = bond_get_slave_by_dev(bond, slave_dev);
+	if (!slave) {
+		/* not a slave of this bond */
+		printk(KERN_INFO DRV_NAME
+		       ": %s: %s not enslaved\n",
+		       bond_dev->name, slave_dev->name);
+		return -EINVAL;
 	}
 
-	if ((newactive != NULL)&&
-	    (oldactive != NULL)&&
-	    (newactive->link == BOND_LINK_UP)&&
-	    IS_UP(newactive->dev)) {
-		change_active_interface(bond, newactive);
-	} else {
-		ret = -EINVAL;
+	mac_addr_differ = memcmp(bond_dev->dev_addr,
+				 slave->perm_hwaddr,
+				 ETH_ALEN);
+	if (!mac_addr_differ && (bond->slave_cnt > 1)) {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: the permanent HWaddr of %s "
+		       "- %02X:%02X:%02X:%02X:%02X:%02X - is "
+		       "still in use by %s. Set the HWaddr of "
+		       "%s to a different address to avoid "
+		       "conflicts.\n",
+		       slave_dev->name,
+		       slave->perm_hwaddr[0],
+		       slave->perm_hwaddr[1],
+		       slave->perm_hwaddr[2],
+		       slave->perm_hwaddr[3],
+		       slave->perm_hwaddr[4],
+		       slave->perm_hwaddr[5],
+		       bond_dev->name,
+		       slave_dev->name);
+	}
+
+	/* Inform AD package of unbinding of slave. */
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		/* must be called before the slave is
+		 * detached from the list
+		 */
+		bond_3ad_unbind_slave(slave);
 	}
-	write_unlock_bh(&bond->lock);
-	return ret;
-}
 
-/**
- * find_best_interface - select the best available slave to be the active one
- * @bond: our bonding struct
- *
- * Warning: Caller must hold ptrlock for writing.
- */
-static struct slave *find_best_interface(struct bonding *bond)
-{
-	struct slave *newslave, *oldslave;
-	struct slave *bestslave = NULL;
-	int mintime;
+	printk(KERN_INFO DRV_NAME
+	       ": %s: releasing %s interface %s\n",
+	       bond_dev->name,
+	       (slave->state == BOND_STATE_ACTIVE)
+	       ? "active" : "backup",
+	       slave_dev->name);
 
-	newslave = oldslave = bond->current_slave;
+	oldcurrent = bond->curr_active_slave;
 
-	if (newslave == NULL) { /* there were no active slaves left */
-		if (bond->next != (slave_t *)bond) {  /* found one slave */
-			newslave = bond->next;
-		} else {
-			return NULL; /* still no slave, return NULL */
-		}
-	}
+	bond->current_arp_slave = NULL;
 
-	mintime = updelay;
+	/* release the slave from its bond */
+	bond_detach_slave(bond, slave);
 
-	/* first try the primary link; if arping, a link must tx/rx traffic 
-	 * before it can be considered the current_slave - also, we would skip 
-	 * slaves between the current_slave and primary_slave that may be up 
-	 * and able to arp
-	 */
-	if ((bond->primary_slave != NULL) && (arp_interval == 0)) {
-		if (IS_UP(bond->primary_slave->dev)) 
-			newslave = bond->primary_slave;
+	if (bond->primary_slave == slave) {
+		bond->primary_slave = NULL;
 	}
 
-	/* remember where to stop iterating over the slaves */
-	oldslave = newslave;
-
-	do {
-		if (IS_UP(newslave->dev)) {
-			if (newslave->link == BOND_LINK_UP) {
-				return newslave;
-			}
-			else if (newslave->link == BOND_LINK_BACK) {
-				/* link up, but waiting for stabilization */
-				if (newslave->delay < mintime) {
-					mintime = newslave->delay;
-					bestslave = newslave;
-				}
-			}
-		}
-	} while ((newslave = newslave->next) != oldslave);
-
-	return bestslave;
-}
-
-/**
- * change_active_interface - change the active slave into the specified one
- * @bond: our bonding struct
- * @new: the new slave to make the active one
- * 
- * Set the new slave to the bond's settings and unset them on the old
- * current_slave.
- * Setting include flags, mc-list, promiscuity, allmulti, etc.
- *
- * If @new's link state is %BOND_LINK_BACK we'll set it to %BOND_LINK_UP,
- * because it is apparently the best available slave we have, even though its
- * updelay hasn't timed out yet.
- *
- * Warning: Caller must hold ptrlock for writing.
- */
-static void change_active_interface(struct bonding *bond, struct slave *new)
-{
-	struct slave *old = bond->current_slave;
-
-	if (old == new) {
-		return;
+	if (oldcurrent == slave) {
+		bond_change_active_slave(bond, NULL);
 	}
 
-	if (new) {
-		if (new->link == BOND_LINK_BACK) {
-			if (USES_PRIMARY(bond_mode)) {
-				printk (KERN_INFO
-					"%s: making interface %s the new "
-					"active one %d ms earlier.\n",
-					bond->device->name, new->dev->name,
-					(updelay - new->delay) * miimon);
-			}
-
-			new->delay = 0;
-			new->link = BOND_LINK_UP;
-			new->jiffies = jiffies;
-
-			if (bond_mode == BOND_MODE_8023AD) {
-				bond_3ad_handle_link_change(new, BOND_LINK_UP);
-			}
-
-			if ((bond_mode == BOND_MODE_TLB) ||
-			    (bond_mode == BOND_MODE_ALB)) {
-				bond_alb_handle_link_change(bond, new, BOND_LINK_UP);
-			}
-		} else {
-			if (USES_PRIMARY(bond_mode)) {
-				printk (KERN_INFO
-					"%s: making interface %s the new active one.\n",
-					bond->device->name, new->dev->name);
-			}
-		}
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		/* Must be called only after the slave has been
+		 * detached from the list and the curr_active_slave
+		 * has been cleared (if our_slave == old_current),
+		 * but before a new active slave is selected.
+		 */
+		bond_alb_deinit_slave(bond, slave);
 	}
 
-	if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-		if (old) {
-			bond_set_slave_inactive_flags(old);
-		}
+	if (oldcurrent == slave) {
+		bond_select_active_slave(bond);
 
-		if (new) {
-			bond_set_slave_active_flags(new);
+		if (!bond->curr_active_slave) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: now running without any active "
+			       "interface !\n",
+			       bond_dev->name);
 		}
 	}
 
-	if (USES_PRIMARY(bond_mode)) {
-		bond_mc_update(bond, new, old);
-	}
-
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		bond_alb_assign_current_slave(bond, new);
-	} else {
-		bond->current_slave = new;
-	}
-}
-
-/**
- * reselect_active_interface - select a new active slave, if needed
- * @bond: our bonding struct
- *
- * This functions shoud be called when one of the following occurs:
- * - The old current_slave has been released or lost its link.
- * - The primary_slave has got its link back.
- * - A slave has got its link back and there's no old current_slave.
- *
- * Warning: Caller must hold ptrlock for writing.
- */
-static void reselect_active_interface(struct bonding *bond)
-{
-	struct slave *best_slave;
-
-	best_slave = find_best_interface(bond);
-
-	if (best_slave != bond->current_slave) {
-		change_active_interface(bond, best_slave);
-	}
-}
-
-/*
- * Try to release the slave device <slave> from the bond device <master>
- * It is legal to access current_slave without a lock because all the function
- * is write-locked.
- *
- * The rules for slave state should be:
- *   for Active/Backup:
- *     Active stays on all backups go down
- *   for Bonded connections:
- *     The first up interface should be left on and all others downed.
- */
-static int bond_release(struct net_device *master, struct net_device *slave)
-{
-	bonding_t *bond;
-	slave_t *our_slave, *old_current;
-	struct sockaddr addr;
-	
-	if (master == NULL || slave == NULL)  {
-		return -ENODEV;
-	}
-
-	bond = (struct bonding *) master->priv;
+	if (bond->slave_cnt == 0) {
+		/* if the last slave was removed, zero the mac address
+		 * of the master so it will be set by the application
+		 * to the mac address of the first slave
+		 */
+		memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
 
-	/* master already enslaved, or slave not enslaved,
-	   or no slave for this master */
-	if ((master->flags & IFF_SLAVE) || !(slave->flags & IFF_SLAVE)) {
-		printk (KERN_DEBUG "%s: cannot release %s.\n", master->name, slave->name);
-		return -EINVAL;
+		if (list_empty(&bond->vlan_list)) {
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: clearing HW address of %s while it "
+			       "still has VLANs.\n",
+			       bond_dev->name);
+			printk(KERN_WARNING DRV_NAME
+			       ": When re-adding slaves, make sure the bond's "
+			       "HW address matches its VLANs'.\n");
+		}
+	} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
+		   !bond_has_challenged_slaves(bond)) {
+		printk(KERN_INFO DRV_NAME
+		       ": last VLAN challenged slave %s "
+		       "left bond %s. VLAN blocking is removed\n",
+		       slave_dev->name, bond_dev->name);
+		bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
 	}
 
-	write_lock_bh(&bond->lock);
-	bond->current_arp_slave = NULL;
-	our_slave = (slave_t *)bond;
-	old_current = bond->current_slave;
-	while ((our_slave = our_slave->prev) != (slave_t *)bond) {
-		if (our_slave->dev == slave) {
-			int mac_addr_differ = memcmp(bond->device->dev_addr,
-						 our_slave->perm_hwaddr,
-						 ETH_ALEN);
-			if (!mac_addr_differ && (bond->slave_cnt > 1)) {
-				printk(KERN_WARNING "WARNING: the permanent HWaddr of %s "
-				"- %02X:%02X:%02X:%02X:%02X:%02X - "
-				"is still in use by %s. Set the HWaddr "
-				"of %s to a different address "
-				"to avoid conflicts.\n",
-				       slave->name,
-				       our_slave->perm_hwaddr[0],
-				       our_slave->perm_hwaddr[1],
-				       our_slave->perm_hwaddr[2],
-				       our_slave->perm_hwaddr[3],
-				       our_slave->perm_hwaddr[4],
-				       our_slave->perm_hwaddr[5],
-				       bond->device->name,
-				       slave->name);
-			}
-
-			/* Inform AD package of unbinding of slave. */
-			if (bond_mode == BOND_MODE_8023AD) {
-				/* must be called before the slave is
-				 * detached from the list
-				 */
-				bond_3ad_unbind_slave(our_slave);
-			}
-
-			printk (KERN_INFO "%s: releasing %s interface %s\n",
-				master->name,
-				(our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
-				slave->name);
-
-			/* release the slave from its bond */
-			bond_detach_slave(bond, our_slave);
-
-			if (bond->primary_slave == our_slave) {
-				bond->primary_slave = NULL;
-			}
-
-			if (bond->current_slave == our_slave) {
-				change_active_interface(bond, NULL);
-				reselect_active_interface(bond);
-			}
-
-			if (bond->current_slave == NULL) {
-				printk(KERN_INFO
-					"%s: now running without any active interface !\n",
-					master->name);
-			}
+	write_unlock_bh(&bond->lock);
 
-			if ((bond_mode == BOND_MODE_TLB) ||
-			    (bond_mode == BOND_MODE_ALB)) {
-				/* must be called only after the slave has been
-				 * detached from the list and the current_slave
-				 * has been replaced (if our_slave == old_current)
-				 */
-				bond_alb_deinit_slave(bond, our_slave);
-			}
+	bond_del_vlans_from_slave(bond, slave_dev);
 
-			break;
+	/* If the mode USES_PRIMARY, then we should only remove its
+	 * promisc and mc settings if it was the curr_active_slave, but that was
+	 * already taken care of above when we detached the slave
+	 */
+	if (!USES_PRIMARY(bond->params.mode)) {
+		/* unset promiscuity level from slave */
+		if (bond_dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(slave_dev, -1);
 		}
 
-	}
-	write_unlock_bh(&bond->lock);
-	
-	if (our_slave == (slave_t *)bond) {
-		/* if we get here, it's because the device was not found */
-		printk (KERN_INFO "%s: %s not enslaved\n", master->name, slave->name);
-		return -EINVAL;
-	}
-
-	/* unset promiscuity level from slave */
-	if (master->flags & IFF_PROMISC) {
-		/* If the mode USES_PRIMARY, then we should only remove its
-		 * promisc settings if it was the current_slave, but that was
-		 * already taken care of above when we detached the slave
-		 */
-		if (!USES_PRIMARY(bond_mode)) {
-			dev_set_promiscuity(slave, -1); 
+		/* unset allmulti level from slave */
+		if (bond_dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(slave_dev, -1);
 		}
-	}
-
-	/* undo settings and restore original values */
-	if (multicast_mode == BOND_MULTICAST_ALL) {
-		/* flush master's mc_list from slave */ 
-		bond_mc_list_flush (slave, master); 
 
-		/* unset allmulti level from slave */ 
-		if (master->flags & IFF_ALLMULTI)
-			dev_set_allmulti(slave, -1); 
+		/* flush master's mc_list from slave */
+		bond_mc_list_flush(bond_dev, slave_dev);
 	}
 
-	netdev_set_master(slave, NULL);
+	netdev_set_master(slave_dev, NULL);
 
 	/* close slave before restoring its mac address */
-	dev_close(slave);
+	dev_close(slave_dev);
 
 	if (app_abi_ver >= 1) {
 		/* restore original ("permanent") mac address */
-		memcpy(addr.sa_data, our_slave->perm_hwaddr, ETH_ALEN);
-		addr.sa_family = slave->type;
-		slave->set_mac_address(slave, &addr);
+		memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
+		addr.sa_family = slave_dev->type;
+		slave_dev->set_mac_address(slave_dev, &addr);
 	}
 
 	/* restore the original state of the
 	 * IFF_NOARP flag that might have been
 	 * set by bond_set_slave_inactive_flags()
 	 */
-	if ((our_slave->original_flags & IFF_NOARP) == 0) {
-		slave->flags &= ~IFF_NOARP;
+	if ((slave->original_flags & IFF_NOARP) == 0) {
+		slave_dev->flags &= ~IFF_NOARP;
 	}
 
-	kfree(our_slave);
-
-	/* if the last slave was removed, zero the mac address
-	 * of the master so it will be set by the application
-	 * to the mac address of the first slave
-	 */
-	if (bond->next == (slave_t*)bond) {
-		memset(master->dev_addr, 0, master->addr_len);
-	}
+	kfree(slave);
 
 	return 0;  /* deletion OK */
 }
 
-/* 
+/*
  * This function releases all slaves.
  */
-static int bond_release_all(struct net_device *master)
+static int bond_release_all(struct net_device *bond_dev)
 {
-	bonding_t *bond;
-	slave_t *our_slave, *old_current;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
 	struct net_device *slave_dev;
 	struct sockaddr addr;
-	int err = 0;
-
-	if (master == NULL)  {
-		return -ENODEV;
-	}
-
-	if (master->flags & IFF_SLAVE) {
-		return -EINVAL;
-	}
-
-	bond = (struct bonding *) master->priv;
 
 	write_lock_bh(&bond->lock);
-	if (bond->next == (struct slave *) bond) {
-		err = -EINVAL;
+
+	if (bond->slave_cnt == 0) {
 		goto out;
 	}
 
-	old_current = bond->current_slave;
-	change_active_interface(bond, NULL);
 	bond->current_arp_slave = NULL;
 	bond->primary_slave = NULL;
+	bond_change_active_slave(bond, NULL);
 
-	while ((our_slave = bond->prev) != (slave_t *)bond) {
+	while ((slave = bond->first_slave) != NULL) {
 		/* Inform AD package of unbinding of slave
 		 * before slave is detached from the list.
 		 */
-		if (bond_mode == BOND_MODE_8023AD) {
-			bond_3ad_unbind_slave(our_slave);
+		if (bond->params.mode == BOND_MODE_8023AD) {
+			bond_3ad_unbind_slave(slave);
 		}
 
-		slave_dev = our_slave->dev;
-		bond_detach_slave(bond, our_slave);
+		slave_dev = slave->dev;
+		bond_detach_slave(bond, slave);
 
-		if ((bond_mode == BOND_MODE_TLB) ||
-		    (bond_mode == BOND_MODE_ALB)) {
+		if ((bond->params.mode == BOND_MODE_TLB) ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
 			/* must be called only after the slave
 			 * has been detached from the list
 			 */
-			bond_alb_deinit_slave(bond, our_slave);
+			bond_alb_deinit_slave(bond, slave);
 		}
 
 		/* now that the slave is detached, unlock and perform
@@ -2180,20 +2225,25 @@ static int bond_release_all(struct net_d
 		 */
 		write_unlock_bh(&bond->lock);
 
-		/* unset promiscuity level from slave */
-		if (master->flags & IFF_PROMISC) {
-			if (!USES_PRIMARY(bond_mode)) {
-				dev_set_promiscuity(slave_dev, -1); 
+		bond_del_vlans_from_slave(bond, slave_dev);
+
+		/* If the mode USES_PRIMARY, then we should only remove its
+		 * promisc and mc settings if it was the curr_active_slave, but that was
+		 * already taken care of above when we detached the slave
+		 */
+		if (!USES_PRIMARY(bond->params.mode)) {
+			/* unset promiscuity level from slave */
+			if (bond_dev->flags & IFF_PROMISC) {
+				dev_set_promiscuity(slave_dev, -1);
 			}
-		}
 
-		if (multicast_mode == BOND_MULTICAST_ALL) {
-			/* flush master's mc_list from slave */ 
-			bond_mc_list_flush (slave_dev, master); 
-
-			/* unset allmulti level from slave */ 
-			if (master->flags & IFF_ALLMULTI)
-				dev_set_allmulti(slave_dev, -1); 
+			/* unset allmulti level from slave */
+			if (bond_dev->flags & IFF_ALLMULTI) {
+				dev_set_allmulti(slave_dev, -1);
+			}
+
+			/* flush master's mc_list from slave */
+			bond_mc_list_flush(bond_dev, slave_dev);
 		}
 
 		netdev_set_master(slave_dev, NULL);
@@ -2203,7 +2253,7 @@ static int bond_release_all(struct net_d
 
 		if (app_abi_ver >= 1) {
 			/* restore original ("permanent") mac address*/
-			memcpy(addr.sa_data, our_slave->perm_hwaddr, ETH_ALEN);
+			memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
 			addr.sa_family = slave_dev->type;
 			slave_dev->set_mac_address(slave_dev, &addr);
 		}
@@ -2211,11 +2261,11 @@ static int bond_release_all(struct net_d
 		/* restore the original state of the IFF_NOARP flag that might have
 		 * been set by bond_set_slave_inactive_flags()
 		 */
-		if ((our_slave->original_flags & IFF_NOARP) == 0) {
+		if ((slave->original_flags & IFF_NOARP) == 0) {
 			slave_dev->flags &= ~IFF_NOARP;
 		}
 
-		kfree(our_slave);
+		kfree(slave);
 
 		/* re-acquire the lock before getting the next slave */
 		write_lock_bh(&bond->lock);
@@ -2225,124 +2275,304 @@ static int bond_release_all(struct net_d
 	 * set by the application to the mac address of the
 	 * first slave
 	 */
-	memset(master->dev_addr, 0, master->addr_len);
+	memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
+
+	if (list_empty(&bond->vlan_list)) {
+		bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+	} else {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: clearing HW address of %s while it "
+		       "still has VLANs.\n",
+		       bond_dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": When re-adding slaves, make sure the bond's "
+		       "HW address matches its VLANs'.\n");
+	}
 
-	printk (KERN_INFO "%s: released all slaves\n", master->name);
+	printk(KERN_INFO DRV_NAME
+	       ": %s: released all slaves\n",
+	       bond_dev->name);
 
 out:
 	write_unlock_bh(&bond->lock);
 
-	return err;
+	return 0;
 }
 
-/* this function is called regularly to monitor each slave's link. */
-static void bond_mii_monitor(struct net_device *master)
+/*
+ * This function changes the active slave to slave <slave_dev>.
+ * It returns -EINVAL in the following cases.
+ *  - <slave_dev> is not found in the list.
+ *  - There is not active slave now.
+ *  - <slave_dev> is already active.
+ *  - The link state of <slave_dev> is not BOND_LINK_UP.
+ *  - <slave_dev> is not running.
+ * In these cases, this fuction does nothing.
+ * In the other cases, currnt_slave pointer is changed and 0 is returned.
+ */
+static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_device *slave_dev)
 {
-	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave, *oldcurrent;
-	int slave_died = 0;
-	int do_failover = 0;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *old_active = NULL;
+	struct slave *new_active = NULL;
+	int res = 0;
 
-	read_lock(&bond->lock);
+	if (!USES_PRIMARY(bond->params.mode)) {
+		return -EINVAL;
+	}
 
-	/* we will try to read the link status of each of our slaves, and
-	 * set their IFF_RUNNING flag appropriately. For each slave not
-	 * supporting MII status, we won't do anything so that a user-space
-	 * program could monitor the link itself if needed.
-	 */
+	/* Verify that master_dev is indeed the master of slave_dev */
+	if (!(slave_dev->flags & IFF_SLAVE) ||
+	    (slave_dev->master != bond_dev)) {
+		return -EINVAL;
+	}
 
-	slave = (slave_t *)bond;
+	write_lock_bh(&bond->lock);
 
-	read_lock(&bond->ptrlock);
-	oldcurrent = bond->current_slave;
-	read_unlock(&bond->ptrlock);
+	old_active = bond->curr_active_slave;
+	new_active = bond_get_slave_by_dev(bond, slave_dev);
 
-	while ((slave = slave->prev) != (slave_t *)bond) {
-		struct net_device *dev = slave->dev;
-		int link_state;
-		u16 old_speed = slave->speed;
-		u8 old_duplex = slave->duplex;
-		
-		link_state = bond_check_dev_link(dev, 0);
+	/*
+	 * Changing to the current active: do nothing; return success.
+	 */
+	if (new_active && (new_active == old_active)) {
+		write_unlock_bh(&bond->lock);
+		return 0;
+	}
 
-		switch (slave->link) {
-		case BOND_LINK_UP:	/* the link was up */
-			if (link_state == BMSR_LSTATUS) {
-				/* link stays up, nothing more to do */
-				break;
-			}
-			else { /* link going down */
-				slave->link  = BOND_LINK_FAIL;
-				slave->delay = downdelay;
-				if (slave->link_failure_count < UINT_MAX) {
-					slave->link_failure_count++;
-				}
-				if (downdelay > 0) {
-					printk (KERN_INFO
-						"%s: link status down for %sinterface "
-						"%s, disabling it in %d ms.\n",
-						master->name,
-						IS_UP(dev)
-						? ((bond_mode == BOND_MODE_ACTIVEBACKUP)
-						   ? ((slave == oldcurrent)
-						      ? "active " : "backup ")
-						   : "")
-						: "idle ",
-						dev->name,
-						downdelay * miimon);
-					}
-			}
-			/* no break ! fall through the BOND_LINK_FAIL test to
-			   ensure proper action to be taken
-			*/
-		case BOND_LINK_FAIL:	/* the link has just gone down */
-			if (link_state != BMSR_LSTATUS) {
-				/* link stays down */
-				if (slave->delay <= 0) {
-					/* link down for too long time */
-					slave->link = BOND_LINK_DOWN;
-					/* in active/backup mode, we must
-					 * completely disable this interface
-					 */
-					if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
-					    (bond_mode == BOND_MODE_8023AD)) {
-						bond_set_slave_inactive_flags(slave);
-					}
+	if ((new_active) &&
+	    (old_active) &&
+	    (new_active->link == BOND_LINK_UP) &&
+	    IS_UP(new_active->dev)) {
+		bond_change_active_slave(bond, new_active);
+	} else {
+		res = -EINVAL;
+	}
 
-					printk(KERN_INFO
-						"%s: link status definitely down "
-						"for interface %s, disabling it",
-						master->name,
-						dev->name);
+	write_unlock_bh(&bond->lock);
 
-					/* notify ad that the link status has changed */
-					if (bond_mode == BOND_MODE_8023AD) {
-						bond_3ad_handle_link_change(slave, BOND_LINK_DOWN);
-					}
+	return res;
+}
 
-					if ((bond_mode == BOND_MODE_TLB) ||
-					    (bond_mode == BOND_MODE_ALB)) {
-						bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN);
-					}
+static int bond_ethtool_ioctl(struct net_device *bond_dev, struct ifreq *ifr)
+{
+	struct ethtool_drvinfo info;
+	void *addr = ifr->ifr_data;
+	uint32_t cmd;
 
-					if (slave == oldcurrent) {
-						do_failover = 1;
-					}
+	if (get_user(cmd, (uint32_t *)addr)) {
+		return -EFAULT;
+	}
 
-					slave_died = 1;
-				} else {
-					slave->delay--;
-				}
+	switch (cmd) {
+	case ETHTOOL_GDRVINFO:
+		if (copy_from_user(&info, addr, sizeof(info))) {
+			return -EFAULT;
+		}
+
+		if (strcmp(info.driver, "ifenslave") == 0) {
+			int new_abi_ver;
+			char *endptr;
+
+			new_abi_ver = simple_strtoul(info.fw_version,
+						     &endptr, 0);
+			if (*endptr) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: got invalid ABI "
+				       "version from application\n");
+
+				return -EINVAL;
+			}
+
+			if (orig_app_abi_ver == -1) {
+				orig_app_abi_ver  = new_abi_ver;
+			}
+
+			app_abi_ver = new_abi_ver;
+		}
+
+		strncpy(info.driver,  DRV_NAME, 32);
+		strncpy(info.version, DRV_VERSION, 32);
+		snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
+
+		if (copy_to_user(addr, &info, sizeof(info))) {
+			return -EFAULT;
+		}
+
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
+{
+	struct bonding *bond = bond_dev->priv;
+
+	info->bond_mode = bond->params.mode;
+	info->miimon = bond->params.miimon;
+
+	read_lock_bh(&bond->lock);
+	info->num_slaves = bond->slave_cnt;
+	read_unlock_bh(&bond->lock);
+
+	return 0;
+}
+
+static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *info)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i, found = 0;
+
+	if (info->slave_id < 0) {
+		return -ENODEV;
+	}
+
+	read_lock_bh(&bond->lock);
+
+	bond_for_each_slave(bond, slave, i) {
+		if (i == (int)info->slave_id) {
+			found = 1;
+			break;
+		}
+	}
+
+	read_unlock_bh(&bond->lock);
+
+	if (found) {
+		strcpy(info->slave_name, slave->dev->name);
+		info->link = slave->link;
+		info->state = slave->state;
+		info->link_failure_count = slave->link_failure_count;
+	} else {
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*-------------------------------- Monitoring -------------------------------*/
+
+/* this function is called regularly to monitor each slave's link. */
+static void bond_mii_monitor(struct net_device *bond_dev)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave, *oldcurrent;
+	int do_failover = 0;
+	int delta_in_ticks;
+	int i;
+
+	read_lock(&bond->lock);
+
+	delta_in_ticks = (bond->params.miimon * HZ) / 1000;
+
+	if (bond->kill_timers) {
+		goto out;
+	}
+
+	if (bond->slave_cnt == 0) {
+		goto re_arm;
+	}
+
+	/* we will try to read the link status of each of our slaves, and
+	 * set their IFF_RUNNING flag appropriately. For each slave not
+	 * supporting MII status, we won't do anything so that a user-space
+	 * program could monitor the link itself if needed.
+	 */
+
+	read_lock(&bond->curr_slave_lock);
+	oldcurrent = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+		int link_state;
+		u16 old_speed = slave->speed;
+		u8 old_duplex = slave->duplex;
+
+		link_state = bond_check_dev_link(bond, slave_dev, 0);
+
+		switch (slave->link) {
+		case BOND_LINK_UP:	/* the link was up */
+			if (link_state == BMSR_LSTATUS) {
+				/* link stays up, nothing more to do */
+				break;
+			} else { /* link going down */
+				slave->link  = BOND_LINK_FAIL;
+				slave->delay = bond->params.downdelay;
+
+				if (slave->link_failure_count < UINT_MAX) {
+					slave->link_failure_count++;
+				}
+
+				if (bond->params.downdelay) {
+					printk(KERN_INFO DRV_NAME
+					       ": %s: link status down for %s "
+					       "interface %s, disabling it in "
+					       "%d ms.\n",
+					       bond_dev->name,
+					       IS_UP(slave_dev)
+					       ? ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+						  ? ((slave == oldcurrent)
+						     ? "active " : "backup ")
+						  : "")
+					       : "idle ",
+					       slave_dev->name,
+					       bond->params.downdelay * bond->params.miimon);
+				}
+			}
+			/* no break ! fall through the BOND_LINK_FAIL test to
+			   ensure proper action to be taken
+			*/
+		case BOND_LINK_FAIL:	/* the link has just gone down */
+			if (link_state != BMSR_LSTATUS) {
+				/* link stays down */
+				if (slave->delay <= 0) {
+					/* link down for too long time */
+					slave->link = BOND_LINK_DOWN;
+
+					/* in active/backup mode, we must
+					 * completely disable this interface
+					 */
+					if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) ||
+					    (bond->params.mode == BOND_MODE_8023AD)) {
+						bond_set_slave_inactive_flags(slave);
+					}
+
+					printk(KERN_INFO DRV_NAME
+					       ": %s: link status definitely "
+					       "down for interface %s, "
+					       "disabling it\n",
+					       bond_dev->name,
+					       slave_dev->name);
+
+					/* notify ad that the link status has changed */
+					if (bond->params.mode == BOND_MODE_8023AD) {
+						bond_3ad_handle_link_change(slave, BOND_LINK_DOWN);
+					}
+
+					if ((bond->params.mode == BOND_MODE_TLB) ||
+					    (bond->params.mode == BOND_MODE_ALB)) {
+						bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN);
+					}
+
+					if (slave == oldcurrent) {
+						do_failover = 1;
+					}
+				} else {
+					slave->delay--;
+				}
 			} else {
 				/* link up again */
 				slave->link  = BOND_LINK_UP;
 				slave->jiffies = jiffies;
-				printk(KERN_INFO
-					"%s: link status up again after %d ms "
-					"for interface %s.\n",
-					master->name,
-					(downdelay - slave->delay) * miimon,
-					dev->name);
+				printk(KERN_INFO DRV_NAME
+				       ": %s: link status up again after %d "
+				       "ms for interface %s.\n",
+				       bond_dev->name,
+				       (bond->params.downdelay - slave->delay) * bond->params.miimon,
+				       slave_dev->name);
 			}
 			break;
 		case BOND_LINK_DOWN:	/* the link was down */
@@ -2351,17 +2581,18 @@ static void bond_mii_monitor(struct net_
 				break;
 			} else {	/* link going up */
 				slave->link  = BOND_LINK_BACK;
-				slave->delay = updelay;
-				
-				if (updelay > 0) {
+				slave->delay = bond->params.updelay;
+
+				if (bond->params.updelay) {
 					/* if updelay == 0, no need to
 					   advertise about a 0 ms delay */
-					printk (KERN_INFO
-						"%s: link status up for interface"
-						" %s, enabling it in %d ms.\n",
-						master->name,
-						dev->name,
-						updelay * miimon);
+					printk(KERN_INFO DRV_NAME
+					       ": %s: link status up for "
+					       "interface %s, enabling it "
+					       "in %d ms.\n",
+					       bond_dev->name,
+					       slave_dev->name,
+					       bond->params.updelay * bond->params.miimon);
 				}
 			}
 			/* no break ! fall through the BOND_LINK_BACK state in
@@ -2371,12 +2602,13 @@ static void bond_mii_monitor(struct net_
 			if (link_state != BMSR_LSTATUS) {
 				/* link down again */
 				slave->link  = BOND_LINK_DOWN;
-				printk(KERN_INFO
-					"%s: link status down again after %d ms "
-					"for interface %s.\n",
-					master->name,
-					(updelay - slave->delay) * miimon,
-					dev->name);
+
+				printk(KERN_INFO DRV_NAME
+				       ": %s: link status down again after %d "
+				       "ms for interface %s.\n",
+				       bond_dev->name,
+				       (bond->params.updelay - slave->delay) * bond->params.miimon,
+				       slave_dev->name);
 			} else {
 				/* link stays up */
 				if (slave->delay == 0) {
@@ -2384,11 +2616,10 @@ static void bond_mii_monitor(struct net_
 					slave->link = BOND_LINK_UP;
 					slave->jiffies = jiffies;
 
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						/* prevent it from being the active one */
 						slave->state = BOND_STATE_BACKUP;
-					}
-					else if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+					} else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
 						/* make it immediately active */
 						slave->state = BOND_STATE_ACTIVE;
 					} else if (slave != bond->primary_slave) {
@@ -2396,23 +2627,23 @@ static void bond_mii_monitor(struct net_
 						slave->state = BOND_STATE_BACKUP;
 					}
 
-					printk(KERN_INFO
-						"%s: link status definitely up "
-						"for interface %s.\n",
-						master->name,
-						dev->name);
-	
+					printk(KERN_INFO DRV_NAME
+					       ": %s: link status definitely "
+					       "up for interface %s.\n",
+					       bond_dev->name,
+					       slave_dev->name);
+
 					/* notify ad that the link status has changed */
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						bond_3ad_handle_link_change(slave, BOND_LINK_UP);
 					}
 
-					if ((bond_mode == BOND_MODE_TLB) ||
-					    (bond_mode == BOND_MODE_ALB)) {
+					if ((bond->params.mode == BOND_MODE_TLB) ||
+					    (bond->params.mode == BOND_MODE_ALB)) {
 						bond_alb_handle_link_change(bond, slave, BOND_LINK_UP);
 					}
 
-					if ((oldcurrent == NULL) ||
+					if ((!oldcurrent) ||
 					    (slave == bond->primary_slave)) {
 						do_failover = 1;
 					}
@@ -2421,120 +2652,128 @@ static void bond_mii_monitor(struct net_
 				}
 			}
 			break;
-		} /* end of switch */
+		default:
+			/* Should not happen */
+			printk(KERN_ERR "bonding: Error: %s  Illegal value (link=%d)\n",
+			       slave->dev->name, slave->link);
+			goto out;
+		} /* end of switch (slave->link) */
 
 		bond_update_speed_duplex(slave);
 
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			if (old_speed != slave->speed) {
 				bond_3ad_adapter_speed_changed(slave);
 			}
+
 			if (old_duplex != slave->duplex) {
 				bond_3ad_adapter_duplex_changed(slave);
 			}
 		}
 
-	} /* end of while */
+	} /* end of for */
 
 	if (do_failover) {
-		write_lock(&bond->ptrlock);
+		write_lock(&bond->curr_slave_lock);
 
-		reselect_active_interface(bond);
-		if (oldcurrent && !bond->current_slave) {
-			printk(KERN_INFO
-				"%s: now running without any active interface !\n",
-				master->name);
+		bond_select_active_slave(bond);
+
+		if (oldcurrent && !bond->curr_active_slave) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: now running without any active "
+			       "interface !\n",
+			       bond_dev->name);
 		}
 
-		write_unlock(&bond->ptrlock);
+		write_unlock(&bond->curr_slave_lock);
 	}
 
+re_arm:
+	if (bond->params.miimon) {
+		mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
+	}
+out:
 	read_unlock(&bond->lock);
-	/* re-arm the timer */
-	mod_timer(&bond->mii_timer, jiffies + (miimon * HZ / 1000));
 }
 
-/* 
- * this function is called regularly to monitor each slave's link 
+static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
+{
+	int i;
+	u32 *targets = bond->params.arp_targets;
+
+	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+		arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev,
+			 my_ip, NULL, slave->dev->dev_addr,
+			 NULL);
+	}
+}
+
+/*
+ * this function is called regularly to monitor each slave's link
  * ensuring that traffic is being sent and received when arp monitoring
- * is used in load-balancing mode. if the adapter has been dormant, then an 
- * arp is transmitted to generate traffic. see activebackup_arp_monitor for 
- * arp monitoring in active backup mode. 
- */
-static void loadbalance_arp_monitor(struct net_device *master)
-{
-	bonding_t *bond;
-	slave_t *slave, *oldcurrent;
-	int the_delta_in_ticks =  arp_interval * HZ / 1000;
-	int next_timer = jiffies + (arp_interval * HZ / 1000);
+ * is used in load-balancing mode. if the adapter has been dormant, then an
+ * arp is transmitted to generate traffic. see activebackup_arp_monitor for
+ * arp monitoring in active backup mode.
+ */
+static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave, *oldcurrent;
 	int do_failover = 0;
+	int delta_in_ticks;
+	int i;
 
-	bond = (struct bonding *) master->priv; 
-	if (master->priv == NULL) {
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
-	}
+	read_lock(&bond->lock);
 
-	/* TODO: investigate why rtnl_shlock_nowait and rtnl_exlock_nowait
-	 * are called below and add comment why they are required... 
-	 */
-	if ((!IS_UP(master)) || rtnl_shlock_nowait()) {
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
-	}
+	delta_in_ticks = (bond->params.arp_interval * HZ) / 1000;
 
-	if (rtnl_exlock_nowait()) {
-		rtnl_shunlock();
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
+	if (bond->kill_timers) {
+		goto out;
 	}
 
-	read_lock(&bond->lock);
+	if (bond->slave_cnt == 0) {
+		goto re_arm;
+	}
 
-	read_lock(&bond->ptrlock);
-	oldcurrent = bond->current_slave;
-	read_unlock(&bond->ptrlock);
+	read_lock(&bond->curr_slave_lock);
+	oldcurrent = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
 
 	/* see if any of the previous devices are up now (i.e. they have
-	 * xmt and rcv traffic). the current_slave does not come into
+	 * xmt and rcv traffic). the curr_active_slave does not come into
 	 * the picture unless it is null. also, slave->jiffies is not needed
 	 * here because we send an arp on each slave and give a slave as
 	 * long as it needs to get the tx/rx within the delta.
 	 * TODO: what about up/down delay in arp mode? it wasn't here before
-	 *       so it can wait 
+	 *       so it can wait
 	 */
-	slave = (slave_t *)bond;
-	while ((slave = slave->prev) != (slave_t *)bond)  {
-
-	  	if (slave->link != BOND_LINK_UP) {
-
-	  		if (((jiffies - slave->dev->trans_start) <= 
-						the_delta_in_ticks) &&  
-			     ((jiffies - slave->dev->last_rx) <= 
-						the_delta_in_ticks)) {
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->link != BOND_LINK_UP) {
+			if (((jiffies - slave->dev->trans_start) <= delta_in_ticks) &&
+			    ((jiffies - slave->dev->last_rx) <= delta_in_ticks)) {
 
 				slave->link  = BOND_LINK_UP;
 				slave->state = BOND_STATE_ACTIVE;
 
 				/* primary_slave has no meaning in round-robin
-				 * mode. the window of a slave being up and 
-				 * current_slave being null after enslaving
+				 * mode. the window of a slave being up and
+				 * curr_active_slave being null after enslaving
 				 * is closed.
 				 */
-				if (oldcurrent == NULL) {
-					printk(KERN_INFO
-						"%s: link status definitely up "
-						"for interface %s, ",
-						master->name,
-						slave->dev->name);
+				if (!oldcurrent) {
+					printk(KERN_INFO DRV_NAME
+					       ": %s: link status definitely "
+					       "up for interface %s, ",
+					       bond_dev->name,
+					       slave->dev->name);
 					do_failover = 1;
 				} else {
-					printk(KERN_INFO
-						"%s: interface %s is now up\n",
-						master->name,
-						slave->dev->name);
+					printk(KERN_INFO DRV_NAME
+					       ": %s: interface %s is now up\n",
+					       bond_dev->name,
+					       slave->dev->name);
 				}
-			} 
+			}
 		} else {
 			/* slave->link == BOND_LINK_UP */
 
@@ -2542,224 +2781,237 @@ static void loadbalance_arp_monitor(stru
 			 * when the source ip is 0, so don't take the link down
 			 * if we don't know our ip yet
 			 */
-			if (((jiffies - slave->dev->trans_start) >= 
-		              (2*the_delta_in_ticks)) ||
-		             (((jiffies - slave->dev->last_rx) >= 
-		               (2*the_delta_in_ticks)) && my_ip !=0)) {
+			if (((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
+			    (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+			     my_ip)) {
+
 				slave->link  = BOND_LINK_DOWN;
 				slave->state = BOND_STATE_BACKUP;
+
 				if (slave->link_failure_count < UINT_MAX) {
 					slave->link_failure_count++;
 				}
-				printk(KERN_INFO
-				       "%s: interface %s is now down.\n",
-				       master->name,
+
+				printk(KERN_INFO DRV_NAME
+				       ": %s: interface %s is now down.\n",
+				       bond_dev->name,
 				       slave->dev->name);
 
 				if (slave == oldcurrent) {
 					do_failover = 1;
 				}
 			}
-		} 
+		}
 
-		/* note: if switch is in round-robin mode, all links 
+		/* note: if switch is in round-robin mode, all links
 		 * must tx arp to ensure all links rx an arp - otherwise
-		 * links may oscillate or not come up at all; if switch is 
-		 * in something like xor mode, there is nothing we can 
-		 * do - all replies will be rx'ed on same link causing slaves 
+		 * links may oscillate or not come up at all; if switch is
+		 * in something like xor mode, there is nothing we can
+		 * do - all replies will be rx'ed on same link causing slaves
 		 * to be unstable during low/no traffic periods
 		 */
 		if (IS_UP(slave->dev)) {
-			arp_send_all(slave);
+			bond_arp_send_all(bond, slave);
 		}
 	}
 
 	if (do_failover) {
-		write_lock(&bond->ptrlock);
+		write_lock(&bond->curr_slave_lock);
+
+		bond_select_active_slave(bond);
 
-		reselect_active_interface(bond);
-		if (oldcurrent && !bond->current_slave) {
-			printk(KERN_INFO
-				"%s: now running without any active interface !\n",
-				master->name);
+		if (oldcurrent && !bond->curr_active_slave) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: now running without any active "
+			       "interface !\n",
+			       bond_dev->name);
 		}
 
-		write_unlock(&bond->ptrlock);
+		write_unlock(&bond->curr_slave_lock);
 	}
 
+re_arm:
+	if (bond->params.arp_interval) {
+		mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	}
+out:
 	read_unlock(&bond->lock);
-	rtnl_exunlock();
-	rtnl_shunlock();
-
-	/* re-arm the timer */
-	mod_timer(&bond->arp_timer, next_timer);
 }
 
-/* 
+/*
  * When using arp monitoring in active-backup mode, this function is
  * called to determine if any backup slaves have went down or a new
  * current slave needs to be found.
- * The backup slaves never generate traffic, they are considered up by merely 
- * receiving traffic. If the current slave goes down, each backup slave will 
- * be given the opportunity to tx/rx an arp before being taken down - this 
- * prevents all slaves from being taken down due to the current slave not 
+ * The backup slaves never generate traffic, they are considered up by merely
+ * receiving traffic. If the current slave goes down, each backup slave will
+ * be given the opportunity to tx/rx an arp before being taken down - this
+ * prevents all slaves from being taken down due to the current slave not
  * sending any traffic for the backups to receive. The arps are not necessarily
- * necessary, any tx and rx traffic will keep the current slave up. While any 
- * rx traffic will keep the backup slaves up, the current slave is responsible 
- * for generating traffic to keep them up regardless of any other traffic they 
+ * necessary, any tx and rx traffic will keep the current slave up. While any
+ * rx traffic will keep the backup slaves up, the current slave is responsible
+ * for generating traffic to keep them up regardless of any other traffic they
  * may have received.
  * see loadbalance_arp_monitor for arp monitoring in load balancing mode
  */
-static void activebackup_arp_monitor(struct net_device *master)
+static void bond_activebackup_arp_mon(struct net_device *bond_dev)
 {
-	bonding_t *bond;
-	slave_t *slave;
-	int the_delta_in_ticks =  arp_interval * HZ / 1000;
-	int next_timer = jiffies + (arp_interval * HZ / 1000);
-
-	bond = (struct bonding *) master->priv; 
-	if (master->priv == NULL) {
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
-	}
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int delta_in_ticks;
+	int i;
 
-	if (!IS_UP(master)) {
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
+	read_lock(&bond->lock);
+
+	delta_in_ticks = (bond->params.arp_interval * HZ) / 1000;
+
+	if (bond->kill_timers) {
+		goto out;
 	}
 
-	read_lock(&bond->lock);
+	if (bond->slave_cnt == 0) {
+		goto re_arm;
+	}
 
-	/* determine if any slave has come up or any backup slave has 
-	 * gone down 
+	/* determine if any slave has come up or any backup slave has
+	 * gone down
 	 * TODO: what about up/down delay in arp mode? it wasn't here before
-	 *       so it can wait 
+	 *       so it can wait
 	 */
-	slave = (slave_t *)bond;
-	while ((slave = slave->prev) != (slave_t *)bond)  {
-
-	  	if (slave->link != BOND_LINK_UP) {
-			if ((jiffies - slave->dev->last_rx) <=
-			    the_delta_in_ticks) {
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->link != BOND_LINK_UP) {
+			if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) {
 
 				slave->link = BOND_LINK_UP;
-				write_lock(&bond->ptrlock);
-				if ((bond->current_slave == NULL) &&
-				    ((jiffies - slave->dev->trans_start) <=
-				     the_delta_in_ticks)) {
-					change_active_interface(bond, slave);
+
+				write_lock(&bond->curr_slave_lock);
+
+				if ((!bond->curr_active_slave) &&
+				    ((jiffies - slave->dev->trans_start) <= delta_in_ticks)) {
+					bond_change_active_slave(bond, slave);
 					bond->current_arp_slave = NULL;
-				} else if (bond->current_slave != slave) {
-					/* this slave has just come up but we 
+				} else if (bond->curr_active_slave != slave) {
+					/* this slave has just come up but we
 					 * already have a current slave; this
 					 * can also happen if bond_enslave adds
-					 * a new slave that is up while we are 
+					 * a new slave that is up while we are
 					 * searching for a new slave
 					 */
 					bond_set_slave_inactive_flags(slave);
 					bond->current_arp_slave = NULL;
 				}
 
-				if (slave == bond->current_slave) {
-					printk(KERN_INFO
-						"%s: %s is up and now the "
-						"active interface\n",
-						master->name,
-						slave->dev->name);
+				if (slave == bond->curr_active_slave) {
+					printk(KERN_INFO DRV_NAME
+					       ": %s: %s is up and now the "
+					       "active interface\n",
+					       bond_dev->name,
+					       slave->dev->name);
 				} else {
-					printk(KERN_INFO
-						"%s: backup interface %s is "
-						"now up\n",
-						master->name,
-						slave->dev->name);
+					printk(KERN_INFO DRV_NAME
+					       ": %s: backup interface %s is "
+					       "now up\n",
+					       bond_dev->name,
+					       slave->dev->name);
 				}
 
-				write_unlock(&bond->ptrlock);
+				write_unlock(&bond->curr_slave_lock);
 			}
 		} else {
-			read_lock(&bond->ptrlock);
-			if ((slave != bond->current_slave) &&
-			    (bond->current_arp_slave == NULL) &&
-			    (((jiffies - slave->dev->last_rx) >=
-			     3*the_delta_in_ticks) && (my_ip != 0))) {
-				/* a backup slave has gone down; three times 
-				 * the delta allows the current slave to be 
+			read_lock(&bond->curr_slave_lock);
+
+			if ((slave != bond->curr_active_slave) &&
+			    (!bond->current_arp_slave) &&
+			    (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
+			     my_ip)) {
+				/* a backup slave has gone down; three times
+				 * the delta allows the current slave to be
 				 * taken out before the backup slave.
 				 * note: a non-null current_arp_slave indicates
-				 * the current_slave went down and we are 
-				 * searching for a new one; under this 
-				 * condition we only take the current_slave 
-				 * down - this gives each slave a chance to 
+				 * the curr_active_slave went down and we are
+				 * searching for a new one; under this
+				 * condition we only take the curr_active_slave
+				 * down - this gives each slave a chance to
 				 * tx/rx traffic before being taken out
 				 */
-				read_unlock(&bond->ptrlock);
+
+				read_unlock(&bond->curr_slave_lock);
+
 				slave->link  = BOND_LINK_DOWN;
+
 				if (slave->link_failure_count < UINT_MAX) {
 					slave->link_failure_count++;
 				}
+
 				bond_set_slave_inactive_flags(slave);
-				printk(KERN_INFO
-					"%s: backup interface %s is now down\n",
-					master->name,
-					slave->dev->name);
+
+				printk(KERN_INFO DRV_NAME
+				       ": %s: backup interface %s is now down\n",
+				       bond_dev->name,
+				       slave->dev->name);
 			} else {
-				read_unlock(&bond->ptrlock);
+				read_unlock(&bond->curr_slave_lock);
 			}
 		}
 	}
 
-	read_lock(&bond->ptrlock);
-	slave = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	if (slave != NULL) {
+	read_lock(&bond->curr_slave_lock);
+	slave = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
 
+	if (slave) {
 		/* if we have sent traffic in the past 2*arp_intervals but
-		 * haven't xmit and rx traffic in that time interval, select 
+		 * haven't xmit and rx traffic in that time interval, select
 		 * a different slave. slave->jiffies is only updated when
-		 * a slave first becomes the current_slave - not necessarily
-		 * after every arp; this ensures the slave has a full 2*delta 
-		 * before being taken out. if a primary is being used, check 
-		 * if it is up and needs to take over as the current_slave
+		 * a slave first becomes the curr_active_slave - not necessarily
+		 * after every arp; this ensures the slave has a full 2*delta
+		 * before being taken out. if a primary is being used, check
+		 * if it is up and needs to take over as the curr_active_slave
 		 */
-		if ((((jiffies - slave->dev->trans_start) >= 
-		       (2*the_delta_in_ticks)) ||
-		     (((jiffies - slave->dev->last_rx) >= 
-		       (2*the_delta_in_ticks)) && (my_ip != 0))) &&
-		    ((jiffies - slave->jiffies) >= 2*the_delta_in_ticks)) {
+		if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
+		     (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+		      my_ip)) &&
+		    ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
 
 			slave->link  = BOND_LINK_DOWN;
+
 			if (slave->link_failure_count < UINT_MAX) {
 				slave->link_failure_count++;
 			}
-			printk(KERN_INFO "%s: link status down for "
-					 "active interface %s, disabling it",
-			       master->name,
+
+			printk(KERN_INFO DRV_NAME
+			       ": %s: link status down for active interface "
+			       "%s, disabling it\n",
+			       bond_dev->name,
 			       slave->dev->name);
-			write_lock(&bond->ptrlock);
-			reselect_active_interface(bond);
-			slave = bond->current_slave;
-			write_unlock(&bond->ptrlock);
+
+			write_lock(&bond->curr_slave_lock);
+
+			bond_select_active_slave(bond);
+			slave = bond->curr_active_slave;
+
+			write_unlock(&bond->curr_slave_lock);
+
 			bond->current_arp_slave = slave;
-			if (slave != NULL) {
+
+			if (slave) {
 				slave->jiffies = jiffies;
 			}
-
-		} else if ((bond->primary_slave != NULL) && 
-			   (bond->primary_slave != slave) && 
+		} else if ((bond->primary_slave) &&
+			   (bond->primary_slave != slave) &&
 			   (bond->primary_slave->link == BOND_LINK_UP)) {
-			/* at this point, slave is the current_slave */
-			printk(KERN_INFO 
-			       "%s: changing from interface %s to primary "
+			/* at this point, slave is the curr_active_slave */
+			printk(KERN_INFO DRV_NAME
+			       ": %s: changing from interface %s to primary "
 			       "interface %s\n",
-			       master->name, 
-			       slave->dev->name, 
+			       bond_dev->name,
+			       slave->dev->name,
 			       bond->primary_slave->dev->name);
-			       
+
 			/* primary is up so switch to it */
-			write_lock(&bond->ptrlock);
-			change_active_interface(bond, bond->primary_slave);
-			write_unlock(&bond->ptrlock);
+			write_lock(&bond->curr_slave_lock);
+			bond_change_active_slave(bond, bond->primary_slave);
+			write_unlock(&bond->curr_slave_lock);
+
 			slave = bond->primary_slave;
 			slave->jiffies = jiffies;
 		} else {
@@ -2769,567 +3021,618 @@ static void activebackup_arp_monitor(str
 		/* the current slave must tx an arp to ensure backup slaves
 		 * rx traffic
 		 */
-		if ((slave != NULL) && (my_ip != 0)) {
-			arp_send_all(slave);
+		if (slave && my_ip) {
+			bond_arp_send_all(bond, slave);
 		}
 	}
 
-	/* if we don't have a current_slave, search for the next available 
-	 * backup slave from the current_arp_slave and make it the candidate 
-	 * for becoming the current_slave
+	/* if we don't have a curr_active_slave, search for the next available
+	 * backup slave from the current_arp_slave and make it the candidate
+	 * for becoming the curr_active_slave
 	 */
-	if (slave == NULL) { 
-
-		if ((bond->current_arp_slave == NULL) ||
-		    (bond->current_arp_slave == (slave_t *)bond)) {
-			bond->current_arp_slave = bond->prev;
-		} 
+	if (!slave) {
+		if (!bond->current_arp_slave) {
+			bond->current_arp_slave = bond->first_slave;
+		}
 
-		if (bond->current_arp_slave != (slave_t *)bond) {
+		if (bond->current_arp_slave) {
 			bond_set_slave_inactive_flags(bond->current_arp_slave);
-			slave = bond->current_arp_slave->next;
 
 			/* search for next candidate */
-			do {
+			bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave) {
 				if (IS_UP(slave->dev)) {
 					slave->link = BOND_LINK_BACK;
 					bond_set_slave_active_flags(slave);
-					arp_send_all(slave);
+					bond_arp_send_all(bond, slave);
 					slave->jiffies = jiffies;
 					bond->current_arp_slave = slave;
 					break;
 				}
 
-				/* if the link state is up at this point, we 
-				 * mark it down - this can happen if we have 
-				 * simultaneous link failures and 
-				 * reselect_active_interface doesn't make this 
-				 * one the current slave so it is still marked 
+				/* if the link state is up at this point, we
+				 * mark it down - this can happen if we have
+				 * simultaneous link failures and
+				 * reselect_active_interface doesn't make this
+				 * one the current slave so it is still marked
 				 * up when it is actually down
 				 */
 				if (slave->link == BOND_LINK_UP) {
 					slave->link  = BOND_LINK_DOWN;
-					if (slave->link_failure_count < 
-							UINT_MAX) {
+					if (slave->link_failure_count < UINT_MAX) {
 						slave->link_failure_count++;
 					}
 
 					bond_set_slave_inactive_flags(slave);
-					printk(KERN_INFO
-						"%s: backup interface "
-						"%s is now down.\n",
-						master->name,
-						slave->dev->name);
+
+					printk(KERN_INFO DRV_NAME
+					       ": %s: backup interface %s is "
+					       "now down.\n",
+					       bond_dev->name,
+					       slave->dev->name);
 				}
-			} while ((slave = slave->next) != 
-					bond->current_arp_slave->next);
+			}
 		}
 	}
 
+re_arm:
+	if (bond->params.arp_interval) {
+		mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	}
+out:
 	read_unlock(&bond->lock);
-	mod_timer(&bond->arp_timer, next_timer);
-}
-
-static int bond_sethwaddr(struct net_device *master, struct net_device *slave)
-{
-#ifdef BONDING_DEBUG
-	printk(KERN_CRIT "bond_sethwaddr: master=%x\n", (unsigned int)master);
-	printk(KERN_CRIT "bond_sethwaddr: slave=%x\n", (unsigned int)slave);
-	printk(KERN_CRIT "bond_sethwaddr: slave->addr_len=%d\n", slave->addr_len);
-#endif
-	memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);
-	return 0;
 }
 
-static int bond_info_query(struct net_device *master, struct ifbond *info)
-{
-	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave;
-
-	info->bond_mode = bond_mode;
-	info->num_slaves = 0;
-	info->miimon = miimon;
+/*------------------------------ proc/seq_file-------------------------------*/
 
-	read_lock_bh(&bond->lock);
-	for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) {
-		info->num_slaves++;
-	}
-	read_unlock_bh(&bond->lock);
+#ifdef CONFIG_PROC_FS
 
-	return 0;
-}
+#define SEQ_START_TOKEN ((void *)1)
 
-static int bond_slave_info_query(struct net_device *master, 
-					struct ifslave *info)
+static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave;
-	int cur_ndx = 0;
-
-	if (info->slave_id < 0) {
-		return -ENODEV;
-	}
+	struct bonding *bond = seq->private;
+	loff_t off = 0;
+	struct slave *slave;
+	int i;
 
+	/* make sure the bond won't be taken away */
+	read_lock(&dev_base_lock);
 	read_lock_bh(&bond->lock);
-	for (slave = bond->prev; 
-		 slave != (slave_t *)bond && cur_ndx < info->slave_id; 
-		 slave = slave->prev) {
-		cur_ndx++;
+
+	if (*pos == 0) {
+		return SEQ_START_TOKEN;
 	}
-	read_unlock_bh(&bond->lock);
 
-	if (slave != (slave_t *)bond) {
-		strcpy(info->slave_name, slave->dev->name);
-		info->link = slave->link;
-		info->state = slave->state;
-		info->link_failure_count = slave->link_failure_count;
-	} else {
-		return -ENODEV;
+	bond_for_each_slave(bond, slave, i) {
+		if (++off == *pos) {
+			return slave;
+		}
 	}
 
-	return 0;
+	return NULL;
 }
 
-static int bond_ethtool_ioctl(struct net_device *master_dev, struct ifreq *ifr)
+static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	void *addr = ifr->ifr_data;
-	uint32_t cmd;
-
-	if (get_user(cmd, (uint32_t *) addr))
-		return -EFAULT;
+	struct bonding *bond = seq->private;
+	struct slave *slave = v;
 
-	switch (cmd) {
+	++*pos;
+	if (v == SEQ_START_TOKEN) {
+		return bond->first_slave;
+	}
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info;
-			char *endptr;
+	slave = slave->next;
 
-			if (copy_from_user(&info, addr, sizeof(info)))
-				return -EFAULT;
+	return (slave == bond->first_slave) ? NULL : slave;
+}
 
-			if (strcmp(info.driver, "ifenslave") == 0) {
-				int new_abi_ver;
+static void bond_info_seq_stop(struct seq_file *seq, void *v)
+{
+	struct bonding *bond = seq->private;
 
-				new_abi_ver = simple_strtoul(info.fw_version,
-						             &endptr, 0);
-				if (*endptr) {
-					printk(KERN_ERR
-					       "bonding: Error: got invalid ABI"
-					       " version from application\n");
+	read_unlock_bh(&bond->lock);
+	read_unlock(&dev_base_lock);
+}
 
-					return -EINVAL;
-				}
+static void bond_info_show_master(struct seq_file *seq)
+{
+	struct bonding *bond = seq->private;
+	struct slave *curr;
 
-				if (orig_app_abi_ver == -1) {
-					orig_app_abi_ver  = new_abi_ver;
-				}
+	read_lock(&bond->curr_slave_lock);
+	curr = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	seq_printf(seq, "Bonding Mode: %s\n",
+		   bond_mode_name(bond->params.mode));
+
+	if (USES_PRIMARY(bond->params.mode)) {
+		seq_printf(seq, "Primary Slave: %s\n",
+			   (bond->params.primary[0]) ?
+			   	bond->params.primary : "None");
 
-				app_abi_ver = new_abi_ver;
-			}
+		seq_printf(seq, "Currently Active Slave: %s\n",
+			   (curr) ? curr->dev->name : "None");
+	}
 
-			strncpy(info.driver,  DRV_NAME, 32);
-			strncpy(info.version, DRV_VERSION, 32);
-			snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
+	seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
+	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
+	seq_printf(seq, "Up Delay (ms): %d\n",
+		   bond->params.updelay * bond->params.miimon);
+	seq_printf(seq, "Down Delay (ms): %d\n",
+		   bond->params.downdelay * bond->params.miimon);
 
-			if (copy_to_user(addr, &info, sizeof(info)))
-				return -EFAULT;
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
 
-			return 0;
+		seq_puts(seq, "\n802.3ad info\n");
+		seq_printf(seq, "LACP rate: %s\n",
+			   (bond->params.lacp_fast) ? "fast" : "slow");
+
+		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+			seq_printf(seq, "bond %s has no active aggregator\n",
+				   bond->dev->name);
+		} else {
+			seq_printf(seq, "Active Aggregator Info:\n");
+
+			seq_printf(seq, "\tAggregator ID: %d\n",
+				   ad_info.aggregator_id);
+			seq_printf(seq, "\tNumber of ports: %d\n",
+				   ad_info.ports);
+			seq_printf(seq, "\tActor Key: %d\n",
+				   ad_info.actor_key);
+			seq_printf(seq, "\tPartner Key: %d\n",
+				   ad_info.partner_key);
+			seq_printf(seq, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+				   ad_info.partner_system[0],
+				   ad_info.partner_system[1],
+				   ad_info.partner_system[2],
+				   ad_info.partner_system[3],
+				   ad_info.partner_system[4],
+				   ad_info.partner_system[5]);
 		}
-		break;
-	default:
-		return -EOPNOTSUPP;
 	}
 }
 
-static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
+static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
 {
-	struct net_device *slave_dev = NULL;
-	struct ifbond *u_binfo = NULL, k_binfo;
-	struct ifslave *u_sinfo = NULL, k_sinfo;
-	struct mii_ioctl_data *mii = NULL;
-	int prev_abi_ver = orig_app_abi_ver;
-	int ret = 0;
+	struct bonding *bond = seq->private;
 
-#ifdef BONDING_DEBUG
-	printk(KERN_INFO "bond_ioctl: master=%s, cmd=%d\n", 
-		master_dev->name, cmd);
-#endif
+	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
+	seq_printf(seq, "MII Status: %s\n",
+		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
+	seq_printf(seq, "Link Failure Count: %d\n",
+		   slave->link_failure_count);
 
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return bond_ethtool_ioctl(master_dev, ifr);
+	if (app_abi_ver >= 1) {
+		seq_printf(seq,
+			   "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+			   slave->perm_hwaddr[0],
+			   slave->perm_hwaddr[1],
+			   slave->perm_hwaddr[2],
+			   slave->perm_hwaddr[3],
+			   slave->perm_hwaddr[4],
+			   slave->perm_hwaddr[5]);
+	}
 
-	case SIOCGMIIPHY:
-		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
-		if (mii == NULL) {
-			return -EINVAL;
-		}
-		mii->phy_id = 0;
-		/* Fall Through */
-	case SIOCGMIIREG:
-		/* 
-		 * We do this again just in case we were called by SIOCGMIIREG
-		 * instead of SIOCGMIIPHY.
-		 */
-		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
-		if (mii == NULL) {
-			return -EINVAL;
-		}
-		if (mii->reg_num == 1) {
-			mii->val_out = bond_check_mii_link(
-				(struct bonding *)master_dev->priv);
-		}
-		return 0;
-	case BOND_INFO_QUERY_OLD:
-	case SIOCBONDINFOQUERY:
-		u_binfo = (struct ifbond *)ifr->ifr_data;
-		if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
-			return -EFAULT;
-		}
-		ret = bond_info_query(master_dev, &k_binfo);
-		if (ret == 0) {
-			if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) {
-				return -EFAULT;
-			}
-		}
-		return ret;
-	case BOND_SLAVE_INFO_QUERY_OLD:
-	case SIOCBONDSLAVEINFOQUERY:
-		u_sinfo = (struct ifslave *)ifr->ifr_data;
-		if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
-			return -EFAULT;
-		}
-		ret = bond_slave_info_query(master_dev, &k_sinfo);
-		if (ret == 0) {
-			if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) {
-				return -EFAULT;
-			}
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		const struct aggregator *agg
+			= SLAVE_AD_INFO(slave).port.aggregator;
+
+		if (agg) {
+			seq_printf(seq, "Aggregator ID: %d\n",
+				   agg->aggregator_identifier);
+		} else {
+			seq_puts(seq, "Aggregator ID: N/A\n");
 		}
-		return ret;
 	}
+}
 
-	if (!capable(CAP_NET_ADMIN)) {
-		return -EPERM;
+static int bond_info_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "%s\n", version);
+		bond_info_show_master(seq);
+	} else {
+		bond_info_show_slave(seq, v);
 	}
 
-	if (orig_app_abi_ver == -1) {
-		/* no orig_app_abi_ver was provided yet, so we'll use the
-		 * current one from now on, even if it's 0
-		 */
-		orig_app_abi_ver = app_abi_ver;
+	return 0;
+}
 
-	} else if (orig_app_abi_ver != app_abi_ver) {
-		printk(KERN_ERR
-		       "bonding: Error: already using ifenslave ABI "
-		       "version %d; to upgrade ifenslave to version %d, "
-		       "you must first reload bonding.\n",
-		       orig_app_abi_ver, app_abi_ver);
-		return -EINVAL;
+static struct seq_operations bond_info_seq_ops = {
+	.start = bond_info_seq_start,
+	.next  = bond_info_seq_next,
+	.stop  = bond_info_seq_stop,
+	.show  = bond_info_seq_show,
+};
+
+static int bond_info_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	struct proc_dir_entry *proc;
+	int res;
+
+	res = seq_open(file, &bond_info_seq_ops);
+	if (!res) {
+		/* recover the pointer buried in proc_dir_entry data */
+		seq = file->private_data;
+		proc = PDE(inode);
+		seq->private = proc->data;
 	}
 
-	slave_dev = dev_get_by_name(ifr->ifr_slave);
+	return res;
+}
 
-#ifdef BONDING_DEBUG
-	printk(KERN_INFO "slave_dev=%x: \n", (unsigned int)slave_dev);
-	printk(KERN_INFO "slave_dev->name=%s: \n", slave_dev->name);
-#endif
+static struct file_operations bond_info_fops = {
+	.owner   = THIS_MODULE,
+	.open    = bond_info_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
 
-	if (slave_dev == NULL) {
-		ret = -ENODEV;
-	} else {
-		switch (cmd) {
-		case BOND_ENSLAVE_OLD:
-		case SIOCBONDENSLAVE:		
-			ret = bond_enslave(master_dev, slave_dev);
-			break;
-		case BOND_RELEASE_OLD:			
-		case SIOCBONDRELEASE:	
-			ret = bond_release(master_dev, slave_dev); 
-			break;
-		case BOND_SETHWADDR_OLD:
-		case SIOCBONDSETHWADDR:
-			ret = bond_sethwaddr(master_dev, slave_dev);
+static int bond_create_proc_entry(struct bonding *bond)
+{
+	struct net_device *bond_dev = bond->dev;
+
+	if (bond_proc_dir) {
+		bond->proc_entry = create_proc_entry(bond_dev->name,
+						     S_IRUGO,
+						     bond_proc_dir);
+		if (bond->proc_entry == NULL) {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: Cannot create /proc/net/%s/%s\n",
+			       DRV_NAME, bond_dev->name);
+		} else {
+			bond->proc_entry->data = bond;
+			bond->proc_entry->proc_fops = &bond_info_fops;
+			bond->proc_entry->owner = THIS_MODULE;
+			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
+		}
+	}
+
+	return 0;
+}
+
+static void bond_remove_proc_entry(struct bonding *bond)
+{
+	if (bond_proc_dir && bond->proc_entry) {
+		remove_proc_entry(bond->proc_file_name, bond_proc_dir);
+		memset(bond->proc_file_name, 0, IFNAMSIZ);
+		bond->proc_entry = NULL;
+	}
+}
+
+/* Create the bonding directory under /proc/net, if doesn't exist yet.
+ * Caller must hold rtnl_lock.
+ */
+static void bond_create_proc_dir(void)
+{
+	int len = strlen(DRV_NAME);
+
+	for (bond_proc_dir = proc_net->subdir; bond_proc_dir;
+	     bond_proc_dir = bond_proc_dir->next) {
+		if ((bond_proc_dir->namelen == len) &&
+		    !memcmp(bond_proc_dir->name, DRV_NAME, len)) {
 			break;
-		case BOND_CHANGE_ACTIVE_OLD:
-		case SIOCBONDCHANGEACTIVE:
-			if (USES_PRIMARY(bond_mode)) {
-				ret = bond_change_active(master_dev, slave_dev);
-			}
-			else {
-				ret = -EINVAL;
-			}
+		}
+	}
+
+	if (!bond_proc_dir) {
+		bond_proc_dir = proc_mkdir(DRV_NAME, proc_net);
+		if (bond_proc_dir) {
+			bond_proc_dir->owner = THIS_MODULE;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+				": Warning: cannot create /proc/net/%s\n",
+				DRV_NAME);
+		}
+	}
+}
+
+/* Destroy the bonding directory under /proc/net, if empty.
+ * Caller must hold rtnl_lock.
+ */
+static void bond_destroy_proc_dir(void)
+{
+	struct proc_dir_entry *de;
+
+	if (!bond_proc_dir) {
+		return;
+	}
+
+	/* verify that the /proc dir is empty */
+	for (de = bond_proc_dir->subdir; de; de = de->next) {
+		/* ignore . and .. */
+		if (*(de->name) != '.') {
 			break;
-		default:
-			ret = -EOPNOTSUPP;
 		}
-		dev_put(slave_dev);
 	}
 
-	if (ret < 0) {
-		/* The ioctl failed, so there's no point in changing the
-		 * orig_app_abi_ver. We'll restore it's value just in case
-		 * we've changed it earlier in this function.
+	if (de) {
+		if (bond_proc_dir->owner == THIS_MODULE) {
+			bond_proc_dir->owner = NULL;
+		}
+	} else {
+		remove_proc_entry(DRV_NAME, proc_net);
+		bond_proc_dir = NULL;
+	}
+}
+#endif /* CONFIG_PROC_FS */
+
+/*-------------------------- netdev event handling --------------------------*/
+
+/*
+ * Change device name
+ */
+static int bond_event_changename(struct bonding *bond)
+{
+#ifdef CONFIG_PROC_FS
+	bond_remove_proc_entry(bond);
+	bond_create_proc_entry(bond);
+#endif
+
+	return NOTIFY_DONE;
+}
+
+static int bond_master_netdev_event(unsigned long event, struct net_device *bond_dev)
+{
+	struct bonding *event_bond = bond_dev->priv;
+
+	switch (event) {
+	case NETDEV_CHANGENAME:
+		return bond_event_changename(event_bond);
+	case NETDEV_UNREGISTER:
+		/*
+		 * TODO: remove a bond from the list?
 		 */
-		orig_app_abi_ver = prev_abi_ver;
+		break;
+	default:
+		break;
 	}
 
-	return ret;
+	return NOTIFY_DONE;
 }
 
-#ifdef CONFIG_NET_FASTROUTE
-static int bond_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
+static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
 {
-	return -1;
+	struct net_device *bond_dev = slave_dev->master;
+
+	switch (event) {
+	case NETDEV_UNREGISTER:
+		if (bond_dev) {
+			bond_release(bond_dev, slave_dev);
+		}
+		break;
+	case NETDEV_CHANGE:
+		/*
+		 * TODO: is this what we get if somebody
+		 * sets up a hierarchical bond, then rmmod's
+		 * one of the slave bonding devices?
+		 */
+		break;
+	case NETDEV_DOWN:
+		/*
+		 * ... Or is it this?
+		 */
+		break;
+	case NETDEV_CHANGEMTU:
+		/*
+		 * TODO: Should slaves be allowed to
+		 * independently alter their MTU?  For
+		 * an active-backup bond, slaves need
+		 * not be the same type of device, so
+		 * MTUs may vary.  For other modes,
+		 * slaves arguably should have the
+		 * same MTUs. To do this, we'd need to
+		 * take over the slave's change_mtu
+		 * function for the duration of their
+		 * servitude.
+		 */
+		break;
+	case NETDEV_CHANGENAME:
+		/*
+		 * TODO: handle changing the primary's name
+		 */
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
 }
-#endif
 
-/* 
- * in broadcast mode, we send everything to all usable interfaces.
+/*
+ * bond_netdev_event: handle netdev notifier chain events.
+ *
+ * This function receives events for the netdev chain.  The caller (an
+ * ioctl handler calling notifier_call_chain) holds the necessary
+ * locks for us to safely manipulate the slave devices (RTNL lock,
+ * dev_probe_lock).
  */
-static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *dev)
+static int bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
-	struct net_device *device_we_should_send_to = 0;
+	struct net_device *event_dev = (struct net_device *)ptr;
+
+	dprintk("event_dev: %s, event: %lx\n",
+		(event_dev ? event_dev->name : "None"),
+		event);
+
+	if (event_dev->flags & IFF_MASTER) {
+		dprintk("IFF_MASTER\n");
+		return bond_master_netdev_event(event, event_dev);
+	}
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
+	if (event_dev->flags & IFF_SLAVE) {
+		dprintk("IFF_SLAVE\n");
+		return bond_slave_netdev_event(event, event_dev);
 	}
 
-	read_lock(&bond->lock);
+	return NOTIFY_DONE;
+}
 
-	read_lock(&bond->ptrlock);
-	slave = start_at = bond->current_slave;
-	read_unlock(&bond->ptrlock);
+static struct notifier_block bond_netdev_notifier = {
+	.notifier_call = bond_netdev_event,
+};
 
-	if (slave == NULL) { /* we're at the root, get the first slave */
-		/* no suitable interface, frame not sent */
-		read_unlock(&bond->lock);
-		dev_kfree_skb(skb);
-		return 0;
-	}
+/*-------------------------- Packet type handling ---------------------------*/
 
-	do {
-		if (IS_UP(slave->dev)
-		    && (slave->link == BOND_LINK_UP)
-		    && (slave->state == BOND_STATE_ACTIVE)) {
-			if (device_we_should_send_to) {
-				struct sk_buff *skb2;
-				if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-					printk(KERN_ERR "bond_xmit_broadcast: skb_clone() failed\n");
-					continue;
-				}
+/* register to receive lacpdus on a bond */
+static void bond_register_lacpdu(struct bonding *bond)
+{
+	struct packet_type *pk_type = &(BOND_AD_INFO(bond).ad_pkt_type);
 
-				skb2->dev = device_we_should_send_to;
-				skb2->priority = 1;
-				dev_queue_xmit(skb2);
-			}
-			device_we_should_send_to = slave->dev;
-		}
-	} while ((slave = slave->next) != start_at);
+	/* initialize packet type */
+	pk_type->type = PKT_TYPE_LACPDU;
+	pk_type->dev = bond->dev;
+	pk_type->func = bond_3ad_lacpdu_recv;
+	pk_type->data = (void*)1;  /* understand shared skbs */
 
-	if (device_we_should_send_to) {
-		skb->dev = device_we_should_send_to;
-		skb->priority = 1;
-		dev_queue_xmit(skb);
-	} else
-		dev_kfree_skb(skb);
+	dev_add_pack(pk_type);
+}
 
-	/* frame sent to all suitable interfaces */
-	read_unlock(&bond->lock);
-	return 0;
+/* unregister to receive lacpdus on a bond */
+static void bond_unregister_lacpdu(struct bonding *bond)
+{
+	dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
 }
 
-static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev)
+/*-------------------------- Device entry points ----------------------------*/
+
+static int bond_open(struct net_device *bond_dev)
 {
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
+	struct bonding *bond = bond_dev->priv;
+	struct timer_list *mii_timer = &bond->mii_timer;
+	struct timer_list *arp_timer = &bond->arp_timer;
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
+	bond->kill_timers = 0;
 
-	read_lock(&bond->lock);
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
 
-	read_lock(&bond->ptrlock);
-	slave = start_at = bond->current_slave;
-	read_unlock(&bond->ptrlock);
+		/* bond_alb_initialize must be called before the timer
+		 * is started.
+		 */
+		if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
+			/* something went wrong - fail the open operation */
+			return -1;
+		}
 
-	if (slave == NULL) { /* we're at the root, get the first slave */
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		init_timer(alb_timer);
+		alb_timer->expires  = jiffies + 1;
+		alb_timer->data     = (unsigned long)bond;
+		alb_timer->function = (void *)&bond_alb_monitor;
+		add_timer(alb_timer);
 	}
 
-	do {
-		if (IS_UP(slave->dev)
-		    && (slave->link == BOND_LINK_UP)
-		    && (slave->state == BOND_STATE_ACTIVE)) {
-
-			skb->dev = slave->dev;
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-
-			write_lock(&bond->ptrlock);
-			bond->current_slave = slave->next;
-			write_unlock(&bond->ptrlock);
+	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
+		init_timer(mii_timer);
+		mii_timer->expires  = jiffies + 1;
+		mii_timer->data     = (unsigned long)bond_dev;
+		mii_timer->function = (void *)&bond_mii_monitor;
+		add_timer(mii_timer);
+	}
 
-			read_unlock(&bond->lock);
-			return 0;
+	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
+		init_timer(arp_timer);
+		arp_timer->expires  = jiffies + 1;
+		arp_timer->data     = (unsigned long)bond_dev;
+		if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+			arp_timer->function = (void *)&bond_activebackup_arp_mon;
+		} else {
+			arp_timer->function = (void *)&bond_loadbalance_arp_mon;
 		}
-	} while ((slave = slave->next) != start_at);
+		add_timer(arp_timer);
+	}
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
+		init_timer(ad_timer);
+		ad_timer->expires  = jiffies + 1;
+		ad_timer->data     = (unsigned long)bond;
+		ad_timer->function = (void *)&bond_3ad_state_machine_handler;
+		add_timer(ad_timer);
+
+		/* register to receive LACPDUs */
+		bond_register_lacpdu(bond);
+	}
 
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	read_unlock(&bond->lock);
 	return 0;
 }
 
-/* 
- * in XOR mode, we determine the output device by performing xor on
- * the source and destination hw adresses.  If this device is not 
- * enabled, find the next slave following this xor slave. 
- */
-static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
+static int bond_close(struct net_device *bond_dev)
 {
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-	int slave_no;
+	struct bonding *bond = bond_dev->priv;
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
+	write_lock_bh(&bond->lock);
 
-	read_lock(&bond->lock);
-	slave = bond->prev;
+	bond_mc_list_destroy(bond);
 
-	/* we're at the root, get the first slave */
-	if (bond->slave_cnt == 0) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		/* Unregister the receive of LACPDUs */
+		bond_unregister_lacpdu(bond);
 	}
 
-	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
-
-	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
-		slave = slave->prev;
-		slave_no--;
-	} 
-	start_at = slave;
-
-	do {
-		if (IS_UP(slave->dev)
-		    && (slave->link == BOND_LINK_UP)
-		    && (slave->state == BOND_STATE_ACTIVE)) {
-
-			skb->dev = slave->dev;
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-
-			read_unlock(&bond->lock);
-			return 0;
-		}
-	} while ((slave = slave->next) != start_at);
+	/* signal timers not to re-arm */
+	bond->kill_timers = 1;
 
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	read_unlock(&bond->lock);
-	return 0;
-}
+	write_unlock_bh(&bond->lock);
 
-/* 
- * in active-backup mode, we know that bond->current_slave is always valid if
- * the bond has a usable interface.
- */
-static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bonding *bond = (struct bonding *) dev->priv;
-	int ret;
+	/* del_timer_sync must run without holding the bond->lock
+	 * because a running timer might be trying to hold it too
+	 */
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
+	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
+		del_timer_sync(&bond->mii_timer);
 	}
 
-	/* if we are sending arp packets, try to at least 
-	   identify our own ip address */
-	if ( (arp_interval > 0) && (my_ip == 0) &&
-		(skb->protocol == __constant_htons(ETH_P_ARP) ) ) {
-		char *the_ip = (((char *)skb->data)) 
-				+ sizeof(struct ethhdr)  
-				+ sizeof(struct arphdr) + 
-				ETH_ALEN;
-		memcpy(&my_ip, the_ip, 4);
+	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
+		del_timer_sync(&bond->arp_timer);
 	}
 
-	/* if we are sending arp packets and don't know 
-	 * the target hw address, save it so we don't need 
-	 * to use a broadcast address.
-	 * don't do this if in active backup mode because the slaves must 
-	 * receive packets to stay up, and the only ones they receive are 
-	 * broadcasts. 
-	 */
-	if ( (bond_mode != BOND_MODE_ACTIVEBACKUP) && 
-             (arp_ip_count == 1) &&
-	     (arp_interval > 0) && (arp_target_hw_addr == NULL) &&
-	     (skb->protocol == __constant_htons(ETH_P_IP) ) ) {
-		struct ethhdr *eth_hdr = 
-			(struct ethhdr *) (((char *)skb->data));
-		struct iphdr *ip_hdr = (struct iphdr *)(eth_hdr + 1);
-
-		if (arp_target[0] == ip_hdr->daddr) {
-			arp_target_hw_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
-			if (arp_target_hw_addr != NULL)
-				memcpy(arp_target_hw_addr, eth_hdr->h_dest, ETH_ALEN);
-		}
+	switch (bond->params.mode) {
+	case BOND_MODE_8023AD:
+		del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
+		break;
+	case BOND_MODE_TLB:
+	case BOND_MODE_ALB:
+		del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer));
+		break;
+	default:
+		break;
 	}
 
-	read_lock(&bond->lock);
+	/* Release the bonded slaves */
+	bond_release_all(bond_dev);
 
-	read_lock(&bond->ptrlock);
-	if (bond->current_slave != NULL) { /* one usable interface */
-		skb->dev = bond->current_slave->dev;
-		read_unlock(&bond->ptrlock);
-		skb->priority = 1;
-		ret = dev_queue_xmit(skb);
-		read_unlock(&bond->lock);
-		return 0;
-	}
-	else {
-		read_unlock(&bond->ptrlock);
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		/* Must be called only after all
+		 * slaves have been released
+		 */
+		bond_alb_deinitialize(bond);
 	}
 
-	/* no suitable interface, frame not sent */
-#ifdef BONDING_DEBUG
-	printk(KERN_INFO "There was no suitable interface, so we don't transmit\n");
-#endif
-	dev_kfree_skb(skb);
-	read_unlock(&bond->lock);
 	return 0;
 }
 
-static struct net_device_stats *bond_get_stats(struct net_device *dev)
+static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
 {
-	bonding_t *bond = dev->priv;
+	struct bonding *bond = bond_dev->priv;
 	struct net_device_stats *stats = &(bond->stats), *sstats;
-	slave_t *slave;
+	struct slave *slave;
+	int i;
 
 	memset(stats, 0, sizeof(struct net_device_stats));
 
 	read_lock_bh(&bond->lock);
 
-	for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) {
+	bond_for_each_slave(bond, slave, i) {
 		sstats = slave->dev->get_stats(slave->dev);
- 
+
 		stats->rx_packets += sstats->rx_packets;
 		stats->rx_bytes += sstats->rx_bytes;
 		stats->rx_errors += sstats->rx_errors;
@@ -3347,290 +3650,290 @@ static struct net_device_stats *bond_get
 		stats->rx_over_errors += sstats->rx_over_errors;
 		stats->rx_crc_errors += sstats->rx_crc_errors;
 		stats->rx_frame_errors += sstats->rx_frame_errors;
-		stats->rx_fifo_errors += sstats->rx_fifo_errors;	
+		stats->rx_fifo_errors += sstats->rx_fifo_errors;
 		stats->rx_missed_errors += sstats->rx_missed_errors;
-	
+
 		stats->tx_aborted_errors += sstats->tx_aborted_errors;
 		stats->tx_carrier_errors += sstats->tx_carrier_errors;
 		stats->tx_fifo_errors += sstats->tx_fifo_errors;
 		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
 		stats->tx_window_errors += sstats->tx_window_errors;
-
 	}
 
 	read_unlock_bh(&bond->lock);
+
 	return stats;
 }
 
-#ifdef CONFIG_PROC_FS
-
-#define SEQ_START_TOKEN ((void *)1)
-
-static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
+static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
 {
-	struct bonding *bond = seq->private;
-	loff_t off = 0;
-	struct slave *slave;
-
-	/* make sure the bond won't be taken away */
-	read_lock(&dev_base_lock);
-	read_lock_bh(&bond->lock);
-
-	if (*pos == 0) {
-		return SEQ_START_TOKEN;
-	}
+	struct net_device *slave_dev = NULL;
+	struct ifbond *u_binfo = NULL, k_binfo;
+	struct ifslave *u_sinfo = NULL, k_sinfo;
+	struct mii_ioctl_data *mii = NULL;
+	int prev_abi_ver = orig_app_abi_ver;
+	int res = 0;
 
-	for (slave = bond->prev; slave != (slave_t *)bond;
-	     slave = slave->prev) {
+	dprintk("bond_ioctl: master=%s, cmd=%d\n",
+		bond_dev->name, cmd);
 
-		if (++off == *pos) {
-			return slave;
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return bond_ethtool_ioctl(bond_dev, ifr);
+	case SIOCGMIIPHY:
+		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+		if (!mii) {
+			return -EINVAL;
+		}
+		mii->phy_id = 0;
+		/* Fall Through */
+	case SIOCGMIIREG:
+		/*
+		 * We do this again just in case we were called by SIOCGMIIREG
+		 * instead of SIOCGMIIPHY.
+		 */
+		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+		if (!mii) {
+			return -EINVAL;
 		}
-	}
-
-	return NULL;
-}
-
-static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	struct bonding *bond = seq->private;
-	struct slave *slave = v;
-
-	++*pos;
-	if (v == SEQ_START_TOKEN) {
-		slave = bond->prev;
-	} else {
-		slave = slave->prev;
-	}
-
-	return (slave == (struct slave *) bond) ? NULL : slave;
-}
 
-static void bond_info_seq_stop(struct seq_file *seq, void *v)
-{
-	struct bonding *bond = seq->private;
+		if (mii->reg_num == 1) {
+			struct bonding *bond = bond_dev->priv;
+			mii->val_out = 0;
+			read_lock_bh(&bond->lock);
+			read_lock(&bond->curr_slave_lock);
+			if (bond->curr_active_slave) {
+				mii->val_out = BMSR_LSTATUS;
+			}
+			read_unlock(&bond->curr_slave_lock);
+			read_unlock_bh(&bond->lock);
+		}
 
-	read_unlock_bh(&bond->lock);
-	read_unlock(&dev_base_lock);
-}
+		return 0;
+	case BOND_INFO_QUERY_OLD:
+	case SIOCBONDINFOQUERY:
+		u_binfo = (struct ifbond *)ifr->ifr_data;
 
-static void bond_info_show_master(struct seq_file *seq, struct bonding *bond)
-{
-	struct slave *curr;
+		if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
+			return -EFAULT;
+		}
 
-	read_lock(&bond->ptrlock);
-	curr = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	seq_printf(seq, "Bonding Mode: %s\n", bond_mode_name());
-
-	if (USES_PRIMARY(bond_mode)) {
-		if (curr) {
-			seq_printf(seq,
-				   "Currently Active Slave: %s\n",
-				   curr->dev->name);
+		res = bond_info_query(bond_dev, &k_binfo);
+		if (res == 0) {
+			if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) {
+				return -EFAULT;
+			}
 		}
-	}
 
-	seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
-	seq_printf(seq, "MII Polling Interval (ms): %d\n", miimon);
-	seq_printf(seq, "Up Delay (ms): %d\n", updelay * miimon);
-	seq_printf(seq, "Down Delay (ms): %d\n", downdelay * miimon);
-	seq_printf(seq, "Multicast Mode: %s\n", multicast_mode_name());
+		return res;
+	case BOND_SLAVE_INFO_QUERY_OLD:
+	case SIOCBONDSLAVEINFOQUERY:
+		u_sinfo = (struct ifslave *)ifr->ifr_data;
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		struct ad_info ad_info;
+		if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
+			return -EFAULT;
+		}
 
-		seq_puts(seq, "\n802.3ad info\n");
+		res = bond_slave_info_query(bond_dev, &k_sinfo);
+		if (res == 0) {
+			if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) {
+				return -EFAULT;
+			}
+		}
 
-		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
-			seq_printf(seq, "bond %s has no active aggregator\n",
-				   bond->device->name);
-		} else {
-			seq_printf(seq, "Active Aggregator Info:\n");
+		return res;
+	default:
+		/* Go on */
+		break;
+	}
 
-			seq_printf(seq, "\tAggregator ID: %d\n",
-				   ad_info.aggregator_id);
-			seq_printf(seq, "\tNumber of ports: %d\n",
-				   ad_info.ports);
-			seq_printf(seq, "\tActor Key: %d\n",
-				   ad_info.actor_key);
-			seq_printf(seq, "\tPartner Key: %d\n",
-				   ad_info.partner_key);
-			seq_printf(seq, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
-				   ad_info.partner_system[0],
-				   ad_info.partner_system[1],
-				   ad_info.partner_system[2],
-				   ad_info.partner_system[3],
-				   ad_info.partner_system[4],
-				   ad_info.partner_system[5]);
-		}
+	if (!capable(CAP_NET_ADMIN)) {
+		return -EPERM;
 	}
-}
 
-static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
-{
-	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
-	seq_printf(seq, "MII Status: %s\n",
-		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-	seq_printf(seq, "Link Failure Count: %d\n",
-		   slave->link_failure_count);
+	if (orig_app_abi_ver == -1) {
+		/* no orig_app_abi_ver was provided yet, so we'll use the
+		 * current one from now on, even if it's 0
+		 */
+		orig_app_abi_ver = app_abi_ver;
 
-	if (app_abi_ver >= 1) {
-		seq_printf(seq,
-			   "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
-			   slave->perm_hwaddr[0],
-			   slave->perm_hwaddr[1],
-			   slave->perm_hwaddr[2],
-			   slave->perm_hwaddr[3],
-			   slave->perm_hwaddr[4],
-			   slave->perm_hwaddr[5]);
+	} else if (orig_app_abi_ver != app_abi_ver) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: already using ifenslave ABI version %d; to "
+		       "upgrade ifenslave to version %d, you must first "
+		       "reload bonding.\n",
+		       orig_app_abi_ver, app_abi_ver);
+		return -EINVAL;
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		const struct aggregator *agg
-			= SLAVE_AD_INFO(slave).port.aggregator;
+	slave_dev = dev_get_by_name(ifr->ifr_slave);
 
-		if (agg) {
-			seq_printf(seq, "Aggregator ID: %d\n",
-				   agg->aggregator_identifier);
-		} else {
-			seq_puts(seq, "Aggregator ID: N/A\n");
+	dprintk("slave_dev=%p: \n", slave_dev);
+
+	if (!slave_dev) {
+		res = -ENODEV;
+	} else {
+		dprintk("slave_dev->name=%s: \n", slave_dev->name);
+		switch (cmd) {
+		case BOND_ENSLAVE_OLD:
+		case SIOCBONDENSLAVE:
+			res = bond_enslave(bond_dev, slave_dev);
+			break;
+		case BOND_RELEASE_OLD:
+		case SIOCBONDRELEASE:
+			res = bond_release(bond_dev, slave_dev);
+			break;
+		case BOND_SETHWADDR_OLD:
+		case SIOCBONDSETHWADDR:
+			res = bond_sethwaddr(bond_dev, slave_dev);
+			break;
+		case BOND_CHANGE_ACTIVE_OLD:
+		case SIOCBONDCHANGEACTIVE:
+			res = bond_ioctl_change_active(bond_dev, slave_dev);
+			break;
+		default:
+			res = -EOPNOTSUPP;
 		}
+
+		dev_put(slave_dev);
 	}
-}
 
-static int bond_info_seq_show(struct seq_file *seq, void *v)
-{
-	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "%s\n", version);
-		bond_info_show_master(seq, seq->private);
-	} else {
-		bond_info_show_slave(seq, v);
+	if (res < 0) {
+		/* The ioctl failed, so there's no point in changing the
+		 * orig_app_abi_ver. We'll restore it's value just in case
+		 * we've changed it earlier in this function.
+		 */
+		orig_app_abi_ver = prev_abi_ver;
 	}
 
-	return 0;
+	return res;
 }
 
-static struct seq_operations bond_info_seq_ops = {
-	.start = bond_info_seq_start,
-	.next  = bond_info_seq_next,
-	.stop  = bond_info_seq_stop,
-	.show  = bond_info_seq_show,
-};
-
-static int bond_info_open(struct inode *inode, struct file *file)
+static void bond_set_multicast_list(struct net_device *bond_dev)
 {
-	struct seq_file *seq;
-	struct proc_dir_entry *proc;
-	int rc;
-
-	rc = seq_open(file, &bond_info_seq_ops);
-	if (!rc) {
-		/* recover the pointer buried in proc_dir_entry data */
-		seq = file->private_data;
-		proc = PDE(inode);
-		seq->private = proc->data;
-	}
-	return rc;
-}
+	struct bonding *bond = bond_dev->priv;
+	struct dev_mc_list *dmi;
 
-static struct file_operations bond_info_fops = {
-	.owner	 = THIS_MODULE,
-	.open    = bond_info_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
+	write_lock_bh(&bond->lock);
 
-static int bond_create_proc_info(struct bonding *bond)
-{
-	struct net_device *dev = bond->device;
+	/*
+	 * Do promisc before checking multicast_mode
+	 */
+	if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC)) {
+		bond_set_promiscuity(bond, 1);
+	}
 
-	if (bond_proc_dir) {
-		bond->bond_proc_file = create_proc_entry(dev->name,
-							 S_IRUGO, 
-							 bond_proc_dir);
-		if (bond->bond_proc_file == NULL) {
-			printk(KERN_WARNING
-			       "%s: Cannot create /proc/net/bonding/%s\n", 
-			       dev->name, dev->name);
-		} else {
-			bond->bond_proc_file->data = bond;
-			bond->bond_proc_file->proc_fops = &bond_info_fops;
-			bond->bond_proc_file->owner = THIS_MODULE;
-			memcpy(bond->procdir_name, dev->name, IFNAMSIZ);
-		}
+	if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC)) {
+		bond_set_promiscuity(bond, -1);
 	}
 
-	return 0;
-}
+	/* set allmulti flag to slaves */
+	if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI)) {
+		bond_set_allmulti(bond, 1);
+	}
 
-static void bond_destroy_proc_info(struct bonding *bond)
-{
-	if (bond_proc_dir && bond->bond_proc_file) {
-		remove_proc_entry(bond->procdir_name, bond_proc_dir);
-		memset(bond->procdir_name, 0, IFNAMSIZ);
-		bond->bond_proc_file = NULL;
+	if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI)) {
+		bond_set_allmulti(bond, -1);
 	}
-}
 
-/* Create the bonding directory under /proc/net, if doesn't exist yet.
- * Caller must hold rtnl_lock.
- */
-static void bond_create_proc_dir(void)
-{
-	int len = strlen(DRV_NAME);
+	bond->flags = bond_dev->flags;
 
-	for (bond_proc_dir = proc_net->subdir; bond_proc_dir;
-	     bond_proc_dir = bond_proc_dir->next) {
-		if ((bond_proc_dir->namelen == len) &&
-		    !memcmp(bond_proc_dir->name, DRV_NAME, len)) {
-			break;
+	/* looking for addresses to add to slaves' mc list */
+	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
+		if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) {
+			bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen);
 		}
 	}
 
-	if (!bond_proc_dir) {
-		bond_proc_dir = proc_mkdir(DRV_NAME, proc_net);
-		if (bond_proc_dir) {
-			bond_proc_dir->owner = THIS_MODULE;
-		} else {
-			printk(KERN_WARNING DRV_NAME
-				": Warning: cannot create /proc/net/%s\n",
-				DRV_NAME);
+	/* looking for addresses to delete from slaves' list */
+	for (dmi = bond->mc_list; dmi; dmi = dmi->next) {
+		if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) {
+			bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen);
 		}
 	}
+
+	/* save master's multicast list */
+	bond_mc_list_destroy(bond);
+	bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC);
+
+	write_unlock_bh(&bond->lock);
 }
 
-/* Destroy the bonding directory under /proc/net, if empty.
- * Caller must hold rtnl_lock.
+/*
+ * Change the MTU of all of a master's slaves to match the master
  */
-static void bond_destroy_proc_dir(void)
+static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 {
-	struct proc_dir_entry *de;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave, *stop_at;
+	int res = 0;
+	int i;
 
-	if (!bond_proc_dir) {
-		return;
-	}
+	dprintk("bond=%p, name=%s, new_mtu=%d\n", bond,
+		(bond_dev ? bond_dev->name : "None"), new_mtu);
 
-	/* verify that the /proc dir is empty */
-	for (de = bond_proc_dir->subdir; de; de = de->next) {
-		/* ignore . and .. */
-		if (*(de->name) != '.') {
-			break;
+	/* Can't hold bond->lock with bh disabled here since
+	 * some base drivers panic. On the other hand we can't
+	 * hold bond->lock without bh disabled because we'll
+	 * deadlock. The only solution is to rely on the fact
+	 * that we're under rtnl_lock here, and the slaves
+	 * list won't change. This doesn't solve the problem
+	 * of setting the slave's MTU while it is
+	 * transmitting, but the assumption is that the base
+	 * driver can handle that.
+	 *
+	 * TODO: figure out a way to safely iterate the slaves
+	 * list, but without holding a lock around the actual
+	 * call to the base driver.
+	 */
+
+	bond_for_each_slave(bond, slave, i) {
+		dprintk("s %p s->p %p c_m %p\n", slave,
+			slave->prev, slave->dev->change_mtu);
+		if (slave->dev->change_mtu) {
+			res = slave->dev->change_mtu(slave->dev, new_mtu);
+		} else {
+			slave->dev->mtu = new_mtu;
+			res = 0;
+		}
+
+		if (res) {
+			/* If we failed to set the slave's mtu to the new value
+			 * we must abort the operation even in ACTIVE_BACKUP
+			 * mode, because if we allow the backup slaves to have
+			 * different mtu values than the active slave we'll
+			 * need to change their mtu when doing a failover. That
+			 * means changing their mtu from timer context, which
+			 * is probably not a good idea.
+			 */
+			dprintk("err %d %s\n", res, slave->dev->name);
+			goto unwind;
 		}
 	}
 
-	if (de) {
-		if (bond_proc_dir->owner == THIS_MODULE) {
-			bond_proc_dir->owner = NULL;
+	bond_dev->mtu = new_mtu;
+
+	return 0;
+
+unwind:
+	/* unwind from head to the slave that failed */
+	stop_at = slave;
+	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
+		int tmp_res;
+
+		if (slave->dev->change_mtu) {
+			tmp_res = slave->dev->change_mtu(slave->dev, bond_dev->mtu);
+			if (tmp_res) {
+				dprintk("unwind err %d dev %s\n", tmp_res,
+					slave->dev->name);
+			}
+		} else {
+			slave->dev->mtu = bond_dev->mtu;
 		}
-	} else {
-		remove_proc_entry(DRV_NAME, proc_net);
-		bond_proc_dir = NULL;
 	}
+
+	return res;
 }
-#endif /* CONFIG_PROC_FS */
 
 /*
  * Change HW address
@@ -3639,263 +3942,404 @@ static void bond_destroy_proc_dir(void)
  * downing the master releases all slaves.  We can make bonds full of
  * bonding devices to test this, however.
  */
-static inline int
-bond_set_mac_address(struct net_device *dev, void *addr)
+static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
 {
-	struct bonding *bond = dev->priv;
+	struct bonding *bond = bond_dev->priv;
 	struct sockaddr *sa = addr, tmp_sa;
-	struct slave *slave;
-	int error;
+	struct slave *slave, *stop_at;
+	int res = 0;
+	int i;
 
-	dprintk(KERN_INFO "bond_set_mac_address %p %s\n", dev,
-	       dev->name);
+	dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
 
 	if (!is_valid_ether_addr(sa->sa_data)) {
 		return -EADDRNOTAVAIL;
 	}
 
-	for (slave = bond->prev; slave != (struct slave *)bond;
-	     slave = slave->prev) {
-		dprintk(KERN_INFO "bond_set_mac: slave %p %s\n", slave,
-			slave->dev->name);
+	/* Can't hold bond->lock with bh disabled here since
+	 * some base drivers panic. On the other hand we can't
+	 * hold bond->lock without bh disabled because we'll
+	 * deadlock. The only solution is to rely on the fact
+	 * that we're under rtnl_lock here, and the slaves
+	 * list won't change. This doesn't solve the problem
+	 * of setting the slave's hw address while it is
+	 * transmitting, but the assumption is that the base
+	 * driver can handle that.
+	 *
+	 * TODO: figure out a way to safely iterate the slaves
+	 * list, but without holding a lock around the actual
+	 * call to the base driver.
+	 */
+
+	bond_for_each_slave(bond, slave, i) {
+		dprintk("slave %p %s\n", slave, slave->dev->name);
+
 		if (slave->dev->set_mac_address == NULL) {
-			error = -EOPNOTSUPP;
-			dprintk(KERN_INFO "bond_set_mac EOPNOTSUPP %s\n",
-				slave->dev->name);
+			res = -EOPNOTSUPP;
+			dprintk("EOPNOTSUPP %s\n", slave->dev->name);
 			goto unwind;
 		}
 
-		error = slave->dev->set_mac_address(slave->dev, addr);
-		if (error) {
-			/* TODO: consider downing the slave 
+		res = slave->dev->set_mac_address(slave->dev, addr);
+		if (res) {
+			/* TODO: consider downing the slave
 			 * and retry ?
 			 * User should expect communications
 			 * breakage anyway until ARP finish
 			 * updating, so...
 			 */
-			dprintk(KERN_INFO "bond_set_mac err %d %s\n",
-				error, slave->dev->name);
+			dprintk("err %d %s\n", res, slave->dev->name);
 			goto unwind;
 		}
 	}
 
 	/* success */
-	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+	memcpy(bond_dev->dev_addr, sa->sa_data, bond_dev->addr_len);
 	return 0;
 
 unwind:
-	memcpy(tmp_sa.sa_data, dev->dev_addr, dev->addr_len);
-	tmp_sa.sa_family = dev->type;
+	memcpy(tmp_sa.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
+	tmp_sa.sa_family = bond_dev->type;
+
+	/* unwind from head to the slave that failed */
+	stop_at = slave;
+	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
+		int tmp_res;
+
+		tmp_res = slave->dev->set_mac_address(slave->dev, &tmp_sa);
+		if (tmp_res) {
+			dprintk("unwind err %d dev %s\n", tmp_res,
+				slave->dev->name);
+		}
+	}
+
+	return res;
+}
+
+static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave, *start_at;
+	int i;
+	int res = 1;
+
+	read_lock(&bond->lock);
+
+	if (!BOND_IS_OK(bond)) {
+		goto out;
+	}
+
+	read_lock(&bond->curr_slave_lock);
+	slave = start_at = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	if (!slave) {
+		goto out;
+	}
 
-	for (slave = slave->next; slave != bond->next;
-	     slave = slave->next) {
-		int tmp_error;
+	bond_for_each_slave_from(bond, slave, i, start_at) {
+		if (IS_UP(slave->dev) &&
+		    (slave->link == BOND_LINK_UP) &&
+		    (slave->state == BOND_STATE_ACTIVE)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+
+			write_lock(&bond->curr_slave_lock);
+			bond->curr_active_slave = slave->next;
+			write_unlock(&bond->curr_slave_lock);
 
-		tmp_error = slave->dev->set_mac_address(slave->dev, &tmp_sa);
-		if (tmp_error) {
-			dprintk(KERN_INFO "bond_set_mac_address: "
-				"unwind err %d dev %s\n",
-				tmp_error, slave->dev->name);
+			break;
 		}
 	}
 
-	return error;
+
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
+	read_unlock(&bond->lock);
+	return 0;
 }
 
 /*
- * Change the MTU of all of a master's slaves to match the master
+ * in active-backup mode, we know that bond->curr_active_slave is always valid if
+ * the bond has a usable interface.
  */
-static inline int
-bond_change_mtu(struct net_device *dev, int newmtu)
+static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev)
 {
-	bonding_t *bond = dev->priv;
-	slave_t *slave;
-	int error;
-
-	dprintk(KERN_INFO "CM: b %p nm %d\n", bond, newmtu);
-	for (slave = bond->prev; slave != (slave_t *)bond;
-	     slave = slave->prev) {
-		dprintk(KERN_INFO "CM: s %p s->p %p c_m %p\n", slave,
-			slave->prev, slave->dev->change_mtu);
-		if (slave->dev->change_mtu) {
-			error = slave->dev->change_mtu(slave->dev, newmtu);
-		} else {
-			slave->dev->mtu = newmtu;
-			error = 0;
-		}
+	struct bonding *bond = bond_dev->priv;
+	int res = 1;
 
-		if (error) {
-			/* If we failed to set the slave's mtu to the new value
-			 * we must abort the operation even in ACTIVE_BACKUP
-			 * mode, because if we allow the backup slaves to have
-			 * different mtu values than the active slave we'll
-			 * need to change their mtu when doing a failover. That
-			 * means changing their mtu from timer context, which
-			 * is probably not a good idea.
-			 */
-			dprintk(KERN_INFO "bond_change_mtu err %d %s\n",
-			       error, slave->dev->name);
-			goto unwind;
-		}
+	/* if we are sending arp packets, try to at least
+	   identify our own ip address */
+	if (bond->params.arp_interval && !my_ip &&
+		(skb->protocol == __constant_htons(ETH_P_ARP))) {
+		char *the_ip = (char *)skb->data +
+				sizeof(struct ethhdr) +
+				sizeof(struct arphdr) +
+				ETH_ALEN;
+		memcpy(&my_ip, the_ip, 4);
 	}
 
-	dev->mtu = newmtu;
+	read_lock(&bond->lock);
+	read_lock(&bond->curr_slave_lock);
+
+	if (!BOND_IS_OK(bond)) {
+		goto out;
+	}
+
+	if (bond->curr_active_slave) { /* one usable interface */
+		res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+	}
+
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
+	read_unlock(&bond->curr_slave_lock);
+	read_unlock(&bond->lock);
 	return 0;
+}
 
+/*
+ * in XOR mode, we determine the output device by performing xor on
+ * the source and destination hw adresses.  If this device is not
+ * enabled, find the next slave following this xor slave.
+ */
+static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct ethhdr *data = (struct ethhdr *)skb->data;
+	struct slave *slave, *start_at;
+	int slave_no;
+	int i;
+	int res = 1;
 
-unwind:
-	for (slave = slave->next; slave != bond->next;
-	     slave = slave->next) {
+	read_lock(&bond->lock);
 
-		if (slave->dev->change_mtu) {
-			slave->dev->change_mtu(slave->dev, dev->mtu);
-		} else {
-			slave->dev->mtu = dev->mtu;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
+	}
+
+	slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt;
+
+	bond_for_each_slave(bond, slave, i) {
+		slave_no--;
+		if (slave_no < 0) {
+			break;
+		}
+	}
+
+	start_at = slave;
+
+	bond_for_each_slave_from(bond, slave, i, start_at) {
+		if (IS_UP(slave->dev) &&
+		    (slave->link == BOND_LINK_UP) &&
+		    (slave->state == BOND_STATE_ACTIVE)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
 	}
 
-	return error;
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
+	read_unlock(&bond->lock);
+	return 0;
 }
 
 /*
- * Change device name
+ * in broadcast mode, we send everything to all usable interfaces.
  */
-static inline int bond_event_changename(struct bonding *bond)
+static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 {
-#ifdef CONFIG_PROC_FS
-	bond_destroy_proc_info(bond);
-	bond_create_proc_info(bond);
-#endif
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave, *start_at;
+	struct net_device *tx_dev = NULL;
+	int i;
+	int res = 1;
 
-	return NOTIFY_DONE;
-}
+	read_lock(&bond->lock);
 
-static int bond_master_netdev_event(unsigned long event, struct net_device *event_dev)
-{
-	struct bonding *bond, *event_bond = NULL;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
+	}
 
-	list_for_each_entry(bond, &bond_dev_list, bond_list) {
-		if (bond == event_dev->priv) {
-			event_bond = bond;
-			break;
-		}
+	read_lock(&bond->curr_slave_lock);
+	start_at = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	if (!start_at) {
+		goto out;
 	}
 
-	if (event_bond == NULL) {
-		return NOTIFY_DONE;
+	bond_for_each_slave_from(bond, slave, i, start_at) {
+		if (IS_UP(slave->dev) &&
+		    (slave->link == BOND_LINK_UP) &&
+		    (slave->state == BOND_STATE_ACTIVE)) {
+			if (tx_dev) {
+				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+				if (!skb2) {
+					printk(KERN_ERR DRV_NAME
+					       ": Error: bond_xmit_broadcast(): "
+					       "skb_clone() failed\n");
+					continue;
+				}
+
+				res = bond_dev_queue_xmit(bond, skb2, tx_dev);
+				if (res) {
+					dev_kfree_skb(skb2);
+					continue;
+				}
+			}
+			tx_dev = slave->dev;
+		}
 	}
 
-	switch (event) {
-	case NETDEV_CHANGENAME:
-		return bond_event_changename(event_bond);
-	case NETDEV_UNREGISTER:
-		/*
-		 * TODO: remove a bond from the list?
-		 */
-		break;
-	default:
-		break;
+	if (tx_dev) {
+		res = bond_dev_queue_xmit(bond, skb, tx_dev);
 	}
 
-	return NOTIFY_DONE;
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
+	/* frame sent to all suitable interfaces */
+	read_unlock(&bond->lock);
+	return 0;
 }
 
-static int bond_slave_netdev_event(unsigned long event, struct net_device *event_dev)
+#ifdef CONFIG_NET_FASTROUTE
+static int bond_accept_fastpath(struct net_device *bond_dev, struct dst_entry *dst)
 {
-	struct net_device *master = event_dev->master;
+	return -1;
+}
+#endif
 
-	switch (event) {
-	case NETDEV_UNREGISTER:
-		if (master != NULL) {
-			bond_release(master, event_dev);
-		}
+/*------------------------- Device initialization ---------------------------*/
+
+/*
+ * set bond mode specific net device operations
+ */
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode)
+{
+	switch (mode) {
+	case BOND_MODE_ROUNDROBIN:
+		bond_dev->hard_start_xmit = bond_xmit_roundrobin;
 		break;
-	case NETDEV_CHANGE:
-		/*
-		 * TODO: is this what we get if somebody
-		 * sets up a hierarchical bond, then rmmod's
-		 * one of the slave bonding devices?
-		 */
+	case BOND_MODE_ACTIVEBACKUP:
+		bond_dev->hard_start_xmit = bond_xmit_activebackup;
 		break;
-	case NETDEV_DOWN:
-		/*
-		 * ... Or is it this?
-		 */
+	case BOND_MODE_XOR:
+		bond_dev->hard_start_xmit = bond_xmit_xor;
 		break;
-	case NETDEV_CHANGEMTU:
-		/*
-		 * TODO: Should slaves be allowed to
-		 * independently alter their MTU?  For
-		 * an active-backup bond, slaves need
-		 * not be the same type of device, so
-		 * MTUs may vary.  For other modes,
-		 * slaves arguably should have the
-		 * same MTUs. To do this, we'd need to
-		 * take over the slave's change_mtu
-		 * function for the duration of their
-		 * servitude.
-		 */
+	case BOND_MODE_BROADCAST:
+		bond_dev->hard_start_xmit = bond_xmit_broadcast;
 		break;
-	case NETDEV_CHANGENAME:
-		/*
-		 * TODO: handle changing the primary's name
-		 */
+	case BOND_MODE_8023AD:
+		bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
+		break;
+	case BOND_MODE_TLB:
+	case BOND_MODE_ALB:
+		bond_dev->hard_start_xmit = bond_alb_xmit;
+		bond_dev->set_mac_address = bond_alb_set_mac_address;
 		break;
 	default:
+		/* Should never happen, mode already checked */
+		printk(KERN_ERR DRV_NAME
+		       ": Error: Unknown bonding mode %d\n",
+		       mode);
 		break;
 	}
-
-	return NOTIFY_DONE;
 }
 
 /*
- * bond_netdev_event: handle netdev notifier chain events.
- *
- * This function receives events for the netdev chain.  The caller (an
- * ioctl handler calling notifier_call_chain) holds the necessary
- * locks for us to safely manipulate the slave devices (RTNL lock,
- * dev_probe_lock).
+ * Does not allocate but creates a /proc entry.
+ * Allowed to fail.
  */
-static int bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
 {
-	struct net_device *event_dev = (struct net_device *)ptr;
-	unsigned short flags;
-	int res = NOTIFY_DONE;
+	struct bonding *bond = bond_dev->priv;
 
-	dprintk(KERN_INFO "bond_netdev_event n_b %p ev %lx ptr %p\n",
-		this, event, ptr);
+	dprintk("Begin bond_init for %s\n", bond_dev->name);
 
-	flags = event_dev->flags & (IFF_MASTER | IFF_SLAVE);
-	switch (flags) {
-	case IFF_MASTER:
-		res = bond_master_netdev_event(event, event_dev);
-		break;
-	case IFF_SLAVE:
-		res = bond_slave_netdev_event(event, event_dev);
-		break;
-	default:
-		/* A master that is also a slave ? */
-		break;
-	}
+	/* initialize rwlocks */
+	rwlock_init(&bond->lock);
+	rwlock_init(&bond->curr_slave_lock);
 
-	return res;
-}
+	bond->params = *params; /* copy params struct */
 
-static struct notifier_block bond_netdev_notifier = {
-	.notifier_call = bond_netdev_event,
-};
+	/* Initialize pointers */
+	bond->first_slave = NULL;
+	bond->curr_active_slave = NULL;
+	bond->current_arp_slave = NULL;
+	bond->primary_slave = NULL;
+	bond->dev = bond_dev;
+	INIT_LIST_HEAD(&bond->vlan_list);
+
+	/* Initialize the device entry points */
+	bond_dev->open = bond_open;
+	bond_dev->stop = bond_close;
+	bond_dev->get_stats = bond_get_stats;
+	bond_dev->do_ioctl = bond_do_ioctl;
+	bond_dev->set_multicast_list = bond_set_multicast_list;
+	bond_dev->change_mtu = bond_change_mtu;
+	bond_dev->set_mac_address = bond_set_mac_address;
+
+	bond_set_mode_ops(bond_dev, bond->params.mode);
+
+#ifdef CONFIG_NET_FASTROUTE
+	bond_dev->accept_fastpath = bond_accept_fastpath;
+#endif
+
+	/* Initialize the device options */
+	bond_dev->tx_queue_len = 0;
+	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
+
+	/* At first, we block adding VLANs. That's the only way to
+	 * prevent problems that occur when adding VLANs over an
+	 * empty bond. The block will be removed once non-challenged
+	 * slaves are enslaved.
+	 */
+	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+
+	/* By default, we declare the bond to be fully
+	 * VLAN hardware accelerated capable. Special
+	 * care is taken in the various xmit functions
+	 * when there are slaves that are not hw accel
+	 * capable
+	 */
+	bond_dev->vlan_rx_register = bond_vlan_rx_register;
+	bond_dev->vlan_rx_add_vid  = bond_vlan_rx_add_vid;
+	bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid;
+	bond_dev->features |= (NETIF_F_HW_VLAN_TX |
+			       NETIF_F_HW_VLAN_RX |
+			       NETIF_F_HW_VLAN_FILTER);
+
+#ifdef CONFIG_PROC_FS
+	bond_create_proc_entry(bond);
+#endif
+
+	list_add_tail(&bond->bond_list, &bond_dev_list);
+
+	return 0;
+}
 
 /* De-initialize device specific data.
  * Caller must hold rtnl_lock.
  */
-static inline void bond_deinit(struct net_device *dev)
+static inline void bond_deinit(struct net_device *bond_dev)
 {
-	struct bonding *bond = dev->priv;
+	struct bonding *bond = bond_dev->priv;
 
 	list_del(&bond->bond_list);
 
 #ifdef CONFIG_PROC_FS
-	bond_destroy_proc_info(bond);
+	bond_remove_proc_entry(bond);
 #endif
 }
 
@@ -3907,11 +4351,11 @@ static void bond_free_all(void)
 	struct bonding *bond, *nxt;
 
 	list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
-		struct net_device *dev = bond->device;
+		struct net_device *bond_dev = bond->dev;
 
-		unregister_netdevice(dev);
-		bond_deinit(dev);
-		free_netdev(dev);
+		unregister_netdevice(bond_dev);
+		bond_deinit(bond_dev);
+		free_netdev(bond_dev);
 	}
 
 #ifdef CONFIG_PROC_FS
@@ -3919,123 +4363,21 @@ static void bond_free_all(void)
 #endif
 }
 
-/*
- * Does not allocate but creates a /proc entry.
- * Allowed to fail.
- */
-static int __init bond_init(struct net_device *dev)
-{
-	struct bonding *bond;
-	int count;
-
-#ifdef BONDING_DEBUG
-	printk (KERN_INFO "Begin bond_init for %s\n", dev->name);
-#endif
-	bond = dev->priv;
-
-	/* initialize rwlocks */
-	rwlock_init(&bond->lock);
-	rwlock_init(&bond->ptrlock);
-
-	/* Initialize pointers */
-	bond->next = bond->prev = (slave_t *)bond;
-	bond->current_slave = NULL;
-	bond->current_arp_slave = NULL;
-	bond->device = dev;
-
-	/* Initialize the device structure. */
-	dev->set_mac_address = bond_set_mac_address;
-
-	switch (bond_mode) {
-	case BOND_MODE_ACTIVEBACKUP:
-		dev->hard_start_xmit = bond_xmit_activebackup;
-		break;
-	case BOND_MODE_ROUNDROBIN:
-		dev->hard_start_xmit = bond_xmit_roundrobin;
-		break;
-	case BOND_MODE_XOR:
-		dev->hard_start_xmit = bond_xmit_xor;
-		break;
-	case BOND_MODE_BROADCAST:
-		dev->hard_start_xmit = bond_xmit_broadcast;
-		break;
-	case BOND_MODE_8023AD:
-		dev->hard_start_xmit = bond_3ad_xmit_xor;
-		break;
-	case BOND_MODE_TLB:
-	case BOND_MODE_ALB:
-		dev->hard_start_xmit = bond_alb_xmit;
-		dev->set_mac_address = bond_alb_set_mac_address;
-		break;
-	default:
-		printk(KERN_ERR "Unknown bonding mode %d\n", bond_mode);
-		return -EINVAL;
-	}
-
-	dev->get_stats = bond_get_stats;
-	dev->open = bond_open;
-	dev->stop = bond_close;
-	dev->set_multicast_list = set_multicast_list;
-	dev->do_ioctl = bond_ioctl;
-	dev->change_mtu = bond_change_mtu;
-	dev->tx_queue_len = 0;
-	dev->flags |= IFF_MASTER|IFF_MULTICAST;
-#ifdef CONFIG_NET_FASTROUTE
-	dev->accept_fastpath = bond_accept_fastpath;
-#endif
-
-	printk(KERN_INFO "%s registered with", dev->name);
-	if (miimon > 0) {
-		printk(" MII link monitoring set to %d ms", miimon);
-		updelay /= miimon;
-		downdelay /= miimon;
-	} else {
-		printk("out MII link monitoring");
-	}
-	printk(", in %s mode.\n", bond_mode_name());
-
-	printk(KERN_INFO "%s registered with", dev->name);
-	if (arp_interval > 0) {
-		printk(" ARP monitoring set to %d ms with %d target(s):", 
-			arp_interval, arp_ip_count);
-		for (count=0 ; count<arp_ip_count ; count++)
-                        printk (" %s", arp_ip_target[count]);
-		printk("\n");
-	} else {
-		printk("out ARP monitoring\n");
-	}
- 
-#ifdef CONFIG_PROC_FS
-	bond_create_proc_info(bond);
-#endif
-
-	list_add_tail(&bond->bond_list, &bond_dev_list);
-
-	return 0;
-}
-
-/*
-static int __init bond_probe(struct net_device *dev)
-{
-	bond_init(dev);
-	return 0;
-}
- */
+/*------------------------- Module initialization ---------------------------*/
 
 /*
  * Convert string input module parms.  Accept either the
  * number of the mode or its string name.
  */
-static inline int
-bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
+static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
 {
 	int i;
 
-	for (i = 0; tbl[i].modename != NULL; i++) {
+	for (i = 0; tbl[i].modename; i++) {
 		if ((isdigit(*mode_arg) &&
-		    tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) ||
-		    (0 == strncmp(mode_arg, tbl[i].modename,
-				  strlen(tbl[i].modename)))) {
+		     tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) ||
+		    (strncmp(mode_arg, tbl[i].modename,
+			     strlen(tbl[i].modename)) == 0)) {
 			return tbl[i].mode;
 		}
 	}
@@ -4043,275 +4385,281 @@ bond_parse_parm(char *mode_arg, struct b
 	return -1;
 }
 
-
-static int __init bonding_init(void)
+static int bond_check_params(struct bond_params *params)
 {
-	int no;
-	int err;
-
-	printk(KERN_INFO "%s", version);
-
 	/*
 	 * Convert string parameters.
 	 */
 	if (mode) {
 		bond_mode = bond_parse_parm(mode, bond_mode_tbl);
 		if (bond_mode == -1) {
-			printk(KERN_WARNING
-			       "bonding_init(): Invalid bonding mode \"%s\"\n",
+			printk(KERN_ERR DRV_NAME
+			       ": Error: Invalid bonding mode \"%s\"\n",
 			       mode == NULL ? "NULL" : mode);
 			return -EINVAL;
 		}
 	}
 
-	if (USES_PRIMARY(bond_mode)) {
-		multicast_mode = BOND_MULTICAST_ACTIVE;
-	} else {
-		multicast_mode = BOND_MULTICAST_ALL;
-	}
-
-	if (multicast) {
-		multicast_mode = bond_parse_parm(multicast, bond_mc_tbl);
-		if (multicast_mode == -1) {
-			printk(KERN_WARNING 
-		       "bonding_init(): Invalid multicast mode \"%s\"\n",
-			       multicast == NULL ? "NULL" : multicast);
-			return -EINVAL;
-		}
-	}
-
 	if (lacp_rate) {
 		if (bond_mode != BOND_MODE_8023AD) {
-			printk(KERN_WARNING
-			       "lacp_rate param is irrelevant in mode %s\n",
-			       bond_mode_name());
+			printk(KERN_INFO DRV_NAME
+			       ": lacp_rate param is irrelevant in mode %s\n",
+			       bond_mode_name(bond_mode));
 		} else {
 			lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
 			if (lacp_fast == -1) {
-				printk(KERN_WARNING
-			       	       "bonding_init(): Invalid lacp rate "
-				       "\"%s\"\n",
+				printk(KERN_ERR DRV_NAME
+				       ": Error: Invalid lacp rate \"%s\"\n",
 				       lacp_rate == NULL ? "NULL" : lacp_rate);
-
 				return -EINVAL;
 			}
 		}
 	}
 
 	if (max_bonds < 1 || max_bonds > INT_MAX) {
-		printk(KERN_WARNING 
-		       "bonding_init(): max_bonds (%d) not in range %d-%d, "
-		       "so it was reset to BOND_DEFAULT_MAX_BONDS (%d)",
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: max_bonds (%d) not in range %d-%d, so it "
+		       "was reset to BOND_DEFAULT_MAX_BONDS (%d)",
 		       max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS);
 		max_bonds = BOND_DEFAULT_MAX_BONDS;
 	}
 
 	if (miimon < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): miimon module parameter (%d), "
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: miimon module parameter (%d), "
 		       "not in range 0-%d, so it was reset to %d\n",
 		       miimon, INT_MAX, BOND_LINK_MON_INTERV);
 		miimon = BOND_LINK_MON_INTERV;
 	}
 
 	if (updelay < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): updelay module parameter (%d), "
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: updelay module parameter (%d), "
 		       "not in range 0-%d, so it was reset to 0\n",
 		       updelay, INT_MAX);
 		updelay = 0;
 	}
 
 	if (downdelay < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): downdelay module parameter (%d), "
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: downdelay module parameter (%d), "
 		       "not in range 0-%d, so it was reset to 0\n",
 		       downdelay, INT_MAX);
 		downdelay = 0;
 	}
 
+	if ((use_carrier != 0) && (use_carrier != 1)) {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: use_carrier module parameter (%d), "
+		       "not of valid value (0/1), so it was set to 1\n",
+		       use_carrier);
+		use_carrier = 1;
+	}
+
 	/* reset values for 802.3ad */
 	if (bond_mode == BOND_MODE_8023AD) {
-		if (arp_interval != 0) {
-			printk(KERN_WARNING "bonding_init(): ARP monitoring"
-			       "can't be used simultaneously with 802.3ad, "
-			       "disabling ARP monitoring\n");
-			arp_interval = 0;
-		}
-
-		if (miimon == 0) {
-			printk(KERN_ERR
-			       "bonding_init(): miimon must be specified, "
-			       "otherwise bonding will not detect link failure, "
-			       "speed and duplex which are essential "
-			       "for 802.3ad operation\n");
-			printk(KERN_ERR "Forcing miimon to 100msec\n");
+		if (!miimon) {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: miimon must be specified, "
+			       "otherwise bonding will not detect link "
+			       "failure, speed and duplex which are "
+			       "essential for 802.3ad operation\n");
+			printk(KERN_WARNING "Forcing miimon to 100msec\n");
 			miimon = 100;
 		}
-
-		if (multicast_mode != BOND_MULTICAST_ALL) {
-			printk(KERN_ERR
-			       "bonding_init(): Multicast mode must "
-			       "be set to ALL for 802.3ad\n");
-			printk(KERN_ERR "Forcing Multicast mode to ALL\n");
-			multicast_mode = BOND_MULTICAST_ALL;
-		}
 	}
 
 	/* reset values for TLB/ALB */
 	if ((bond_mode == BOND_MODE_TLB) ||
 	    (bond_mode == BOND_MODE_ALB)) {
-		if (miimon == 0) {
-			printk(KERN_ERR
-			       "bonding_init(): miimon must be specified, "
-			       "otherwise bonding will not detect link failure "
-			       "and link speed which are essential "
+		if (!miimon) {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: miimon must be specified, "
+			       "otherwise bonding will not detect link "
+			       "failure and link speed which are essential "
 			       "for TLB/ALB load balancing\n");
-			printk(KERN_ERR "Forcing miimon to 100msec\n");
+			printk(KERN_WARNING "Forcing miimon to 100msec\n");
 			miimon = 100;
 		}
-
-		if (multicast_mode != BOND_MULTICAST_ACTIVE) {
-			printk(KERN_ERR
-			       "bonding_init(): Multicast mode must "
-			       "be set to ACTIVE for TLB/ALB\n");
-			printk(KERN_ERR "Forcing Multicast mode to ACTIVE\n");
-			multicast_mode = BOND_MULTICAST_ACTIVE;
-		}
 	}
 
 	if (bond_mode == BOND_MODE_ALB) {
-		printk(KERN_INFO
-		       "In ALB mode you might experience client disconnections"
-		       " upon reconnection of a link if the bonding module"
-		       " updelay parameter (%d msec) is incompatible with the"
-		       " forwarding delay time of the switch\n", updelay);
+		printk(KERN_NOTICE DRV_NAME
+		       ": In ALB mode you might experience client "
+		       "disconnections upon reconnection of a link if the "
+		       "bonding module updelay parameter (%d msec) is "
+		       "incompatible with the forwarding delay time of the "
+		       "switch\n",
+		       updelay);
 	}
 
-	if (miimon == 0) {
-		if ((updelay != 0) || (downdelay != 0)) {
+	if (!miimon) {
+		if (updelay || downdelay) {
 			/* just warn the user the up/down delay will have
 			 * no effect since miimon is zero...
 			 */
-			printk(KERN_WARNING 
-		               "bonding_init(): miimon module parameter not "
-			       "set and updelay (%d) or downdelay (%d) module "
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: miimon module parameter not set "
+			       "and updelay (%d) or downdelay (%d) module "
 			       "parameter is set; updelay and downdelay have "
 			       "no effect unless miimon is set\n",
-		               updelay, downdelay);
+			       updelay, downdelay);
 		}
 	} else {
 		/* don't allow arp monitoring */
-		if (arp_interval != 0) {
-			printk(KERN_WARNING 
-		               "bonding_init(): miimon (%d) and arp_interval "
-			       "(%d) can't be used simultaneously, "
-			       "disabling ARP monitoring\n",
-		               miimon, arp_interval);
+		if (arp_interval) {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: miimon (%d) and arp_interval (%d) "
+			       "can't be used simultaneously, disabling ARP "
+			       "monitoring\n",
+			       miimon, arp_interval);
 			arp_interval = 0;
 		}
 
 		if ((updelay % miimon) != 0) {
-			/* updelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
-			printk(KERN_WARNING 
-		               "bonding_init(): updelay (%d) is not a multiple "
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: updelay (%d) is not a multiple "
 			       "of miimon (%d), updelay rounded to %d ms\n",
-		               updelay, miimon, (updelay / miimon) * miimon);
+			       updelay, miimon, (updelay / miimon) * miimon);
 		}
 
+		updelay /= miimon;
+
 		if ((downdelay % miimon) != 0) {
-			/* downdelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
-			printk(KERN_WARNING 
-		               "bonding_init(): downdelay (%d) is not a "
-			       "multiple of miimon (%d), downdelay rounded "
-			       "to %d ms\n",
-		               downdelay, miimon, 
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: downdelay (%d) is not a multiple "
+			       "of miimon (%d), downdelay rounded to %d ms\n",
+			       downdelay, miimon,
 			       (downdelay / miimon) * miimon);
 		}
+
+		downdelay /= miimon;
 	}
 
 	if (arp_interval < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): arp_interval module parameter (%d), "
-		       "not in range 0-%d, so it was reset to %d\n",
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: arp_interval module parameter (%d) "
+		       ", not in range 0-%d, so it was reset to %d\n",
 		       arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
 		arp_interval = BOND_LINK_ARP_INTERV;
 	}
 
-        for (arp_ip_count=0 ;
-             (arp_ip_count < MAX_ARP_IP_TARGETS) && arp_ip_target[arp_ip_count];
-              arp_ip_count++ ) {
+	for (arp_ip_count = 0;
+	     (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[arp_ip_count];
+	     arp_ip_count++) {
 		/* not complete check, but should be good enough to
 		   catch mistakes */
-		if (!isdigit(arp_ip_target[arp_ip_count][0])) { 
-                        printk(KERN_WARNING
-                               "bonding_init(): bad arp_ip_target module "
-                               "parameter (%s), ARP monitoring will not be "
-                               "performed\n",
-                               arp_ip_target[arp_ip_count]);
-                        arp_interval = 0;
-		} else { 
-			u32 ip = in_aton(arp_ip_target[arp_ip_count]); 
+		if (!isdigit(arp_ip_target[arp_ip_count][0])) {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: bad arp_ip_target module parameter "
+			       "(%s), ARP monitoring will not be performed\n",
+			       arp_ip_target[arp_ip_count]);
+			arp_interval = 0;
+		} else {
+			u32 ip = in_aton(arp_ip_target[arp_ip_count]);
 			arp_target[arp_ip_count] = ip;
 		}
-        }
-
+	}
 
-	if ( (arp_interval > 0) && (arp_ip_count==0)) {
+	if (arp_interval && !arp_ip_count) {
 		/* don't allow arping if no arp_ip_target given... */
-		printk(KERN_WARNING 
-		       "bonding_init(): arp_interval module parameter "
-		       "(%d) specified without providing an arp_ip_target "
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: arp_interval module parameter (%d) "
+		       "specified without providing an arp_ip_target "
 		       "parameter, arp_interval was reset to 0\n",
 		       arp_interval);
 		arp_interval = 0;
 	}
 
-	if ((miimon == 0) && (arp_interval == 0)) {
+	if (miimon) {
+		printk(KERN_INFO DRV_NAME
+		       ": MII link monitoring set to %d ms\n",
+		       miimon);
+	} else if (arp_interval) {
+		int i;
+
+		printk(KERN_INFO DRV_NAME
+		       ": ARP monitoring set to %d ms with %d target(s):",
+		       arp_interval, arp_ip_count);
+
+		for (i = 0; i < arp_ip_count; i++)
+			printk (" %s", arp_ip_target[i]);
+
+		printk("\n");
+
+	} else {
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
-		printk(KERN_ERR 
-		       "bonding_init(): either miimon or "
-		       "arp_interval and arp_ip_target module parameters "
-		       "must be specified, otherwise bonding will not detect "
-		       "link failures! see bonding.txt for details.\n");
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: either miimon or arp_interval and "
+		       "arp_ip_target module parameters must be specified, "
+		       "otherwise bonding will not detect link failures! see "
+		       "bonding.txt for details.\n");
 	}
 
-	if ((primary != NULL) && !USES_PRIMARY(bond_mode)) {
+	if (primary && !USES_PRIMARY(bond_mode)) {
 		/* currently, using a primary only makes sense
 		 * in active backup, TLB or ALB modes
 		 */
-		printk(KERN_WARNING 
-		       "bonding_init(): %s primary device specified but has "
-		       "no effect in %s mode\n",
-		       primary, bond_mode_name());
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: %s primary device specified but has no "
+		       "effect in %s mode\n",
+		       primary, bond_mode_name(bond_mode));
 		primary = NULL;
 	}
 
+	/* fill params struct with the proper values */
+	params->mode = bond_mode;
+	params->miimon = miimon;
+	params->arp_interval = arp_interval;
+	params->updelay = updelay;
+	params->downdelay = downdelay;
+	params->use_carrier = use_carrier;
+	params->lacp_fast = lacp_fast;
+	params->primary[0] = 0;
+
+	if (primary) {
+		strncpy(params->primary, primary, IFNAMSIZ);
+		params->primary[IFNAMSIZ - 1] = 0;
+	}
+
+	memcpy(params->arp_targets, arp_target, sizeof(arp_target));
+
+	return 0;
+}
+
+static int __init bonding_init(void)
+{
+	struct bond_params params;
+	int i;
+	int res;
+
+	printk(KERN_INFO "%s", version);
+
+	res = bond_check_params(&params);
+	if (res) {
+		return res;
+	}
+
 	rtnl_lock();
 
 #ifdef CONFIG_PROC_FS
 	bond_create_proc_dir();
 #endif
 
-	err = 0;
-	for (no = 0; no < max_bonds; no++) {
-		struct net_device *dev;
-
-		dev = alloc_netdev(sizeof(struct bonding), "", ether_setup);
-		if (!dev) {
-			err = -ENOMEM;
+	for (i = 0; i < max_bonds; i++) {
+		struct net_device *bond_dev;
+
+		bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup);
+		if (!bond_dev) {
+			res = -ENOMEM;
 			goto out_err;
 		}
 
-		err = dev_alloc_name(dev, "bond%d");
-		if (err < 0) {
-			free_netdev(dev);
+		res = dev_alloc_name(bond_dev, "bond%d");
+		if (res < 0) {
+			free_netdev(bond_dev);
 			goto out_err;
 		}
 
@@ -4319,18 +4667,18 @@ static int __init bonding_init(void)
 		 * /proc files), but before register_netdevice(), because we
 		 * need to set function pointers.
 		 */
-		err = bond_init(dev);
-		if (err < 0) {
-			free_netdev(dev);
+		res = bond_init(bond_dev, &params);
+		if (res < 0) {
+			free_netdev(bond_dev);
 			goto out_err;
 		}
 
-		SET_MODULE_OWNER(dev);
+		SET_MODULE_OWNER(bond_dev);
 
-		err = register_netdevice(dev);
-		if (err < 0) {
-			bond_deinit(dev);
-			free_netdev(dev);
+		res = register_netdevice(bond_dev);
+		if (res < 0) {
+			bond_deinit(bond_dev);
+			free_netdev(bond_dev);
 			goto out_err;
 		}
 	}
@@ -4346,7 +4694,7 @@ out_err:
 
 	rtnl_unlock();
 
-	return err;
+	return res;
 }
 
 static void __exit bonding_exit(void)
@@ -4362,6 +4710,8 @@ module_init(bonding_init);
 module_exit(bonding_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
+MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
+MODULE_SUPPORTED_DEVICE("most ethernet devices");
 
 /*
  * Local variables:
@@ -4370,3 +4720,4 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION ", v"
  *  tab-width: 8
  * End:
  */
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bonding.h linux-2.4.26-pre6/drivers/net/bonding/bonding.h
--- linux-2.4.25/drivers/net/bonding/bonding.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/bonding/bonding.h	2004-03-25 00:19:19.000000000 +0000
@@ -9,7 +9,7 @@
  *
  *	This software may be used and distributed according to the terms
  *	of the GNU Public License, incorporated herein by reference.
- * 
+ *
  *
  * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
  *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
@@ -22,160 +22,231 @@
  *
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Added support for Transmit load balancing mode.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
- 
+
 #ifndef _LINUX_BONDING_H
 #define _LINUX_BONDING_H
 
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
+#include <linux/if_bonding.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#ifdef BONDING_DEBUG
+#define DRV_VERSION	"2.6.0"
+#define DRV_RELDATE	"January 14, 2004"
+#define DRV_NAME	"bonding"
+#define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
-// use this like so: BOND_PRINT_DBG(("foo = %d, bar = %d", foo, bar));
-#define BOND_PRINT_DBG(X)                                     \
-do {                                                          \
-	printk(KERN_DEBUG "%s (%d)", __FUNCTION__, __LINE__); \
-	printk X;                                             \
-	printk("\n");                                         \
-} while(0)
+#define BOND_MAX_ARP_TARGETS	16
 
+#ifdef BONDING_DEBUG
+#define dprintk(fmt, args...) \
+	printk(KERN_DEBUG     \
+	       DRV_NAME ": %s() %d: " fmt, __FUNCTION__, __LINE__ , ## args )
 #else
-#define BOND_PRINT_DBG(X)
+#define dprintk(fmt, args...)
 #endif /* BONDING_DEBUG */
 
-#define IS_UP(dev)  ((((dev)->flags & (IFF_UP)) == (IFF_UP)) && \
-		     (netif_running(dev) && netif_carrier_ok(dev)))
+#define IS_UP(dev)					   \
+	      ((((dev)->flags & IFF_UP) == IFF_UP)	&& \
+	       netif_running(dev)			&& \
+	       netif_carrier_ok(dev))
+
+/*
+ * Checks whether bond is ready for transmit.
+ *
+ * Caller must hold bond->lock
+ */
+#define BOND_IS_OK(bond)			     \
+		   (((bond)->dev->flags & IFF_UP) && \
+		    netif_running((bond)->dev)	  && \
+		    ((bond)->slave_cnt > 0))
 
-/* Checks whether the dev is ready for transmit. We do not check netif_running
- * since a device can be stopped by the driver for short periods of time for
- * maintainance. dev_queue_xmit() handles this by queing the packet until the
- * the dev is running again. Keeping packets ordering requires sticking the
- * same dev as much as possible
- */
-#define SLAVE_IS_OK(slave) \
-		     ((((slave)->dev->flags & (IFF_UP)) == (IFF_UP)) && \
-		     netif_carrier_ok((slave)->dev) && \
+/*
+ * Checks whether slave is ready for transmit.
+ */
+#define SLAVE_IS_OK(slave)			        \
+		    (((slave)->dev->flags & IFF_UP)  && \
+		     netif_running((slave)->dev)     && \
 		     ((slave)->link == BOND_LINK_UP) && \
 		     ((slave)->state == BOND_STATE_ACTIVE))
 
 
-typedef struct slave {
+#define USES_PRIMARY(mode)				\
+		(((mode) == BOND_MODE_ACTIVEBACKUP) ||	\
+		 ((mode) == BOND_MODE_TLB)          ||	\
+		 ((mode) == BOND_MODE_ALB))
+
+/*
+ * Less bad way to call ioctl from within the kernel; this needs to be
+ * done some other way to get the call out of interrupt context.
+ * Needs "ioctl" variable to be supplied by calling context.
+ */
+#define IOCTL(dev, arg, cmd) ({		\
+	int res = 0;			\
+	mm_segment_t fs = get_fs();	\
+	set_fs(get_ds());		\
+	res = ioctl(dev, arg, cmd);	\
+	set_fs(fs);			\
+	res; })
+
+/**
+ * bond_for_each_slave_from - iterate the slaves list from a starting point
+ * @bond:	the bond holding this list.
+ * @pos:	current slave.
+ * @cnt:	counter for max number of moves
+ * @start:	starting point.
+ *
+ * Caller must hold bond->lock
+ */
+#define bond_for_each_slave_from(bond, pos, cnt, start)	\
+	for (cnt = 0, pos = start;				\
+	     cnt < (bond)->slave_cnt;				\
+             cnt++, pos = (pos)->next)
+
+/**
+ * bond_for_each_slave_from_to - iterate the slaves list from start point to stop point
+ * @bond:	the bond holding this list.
+ * @pos:	current slave.
+ * @cnt:	counter for number max of moves
+ * @start:	start point.
+ * @stop:	stop point.
+ *
+ * Caller must hold bond->lock
+ */
+#define bond_for_each_slave_from_to(bond, pos, cnt, start, stop)	\
+	for (cnt = 0, pos = start;					\
+	     ((cnt < (bond)->slave_cnt) && (pos != (stop)->next));	\
+             cnt++, pos = (pos)->next)
+
+/**
+ * bond_for_each_slave - iterate the slaves list from head
+ * @bond:	the bond holding this list.
+ * @pos:	current slave.
+ * @cnt:	counter for max number of moves
+ *
+ * Caller must hold bond->lock
+ */
+#define bond_for_each_slave(bond, pos, cnt)	\
+		bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
+
+
+struct bond_params {
+	int mode;
+	int miimon;
+	int arp_interval;
+	int use_carrier;
+	int updelay;
+	int downdelay;
+	int lacp_fast;
+	char primary[IFNAMSIZ];
+	u32 arp_targets[BOND_MAX_ARP_TARGETS];
+};
+
+struct vlan_entry {
+	struct list_head vlan_list;
+	unsigned short vlan_id;
+};
+
+struct slave {
+	struct net_device *dev; /* first - usefull for panic debug */
 	struct slave *next;
 	struct slave *prev;
-	struct net_device *dev;
-	short  delay;
-	unsigned long jiffies;
-	char   link;    /* one of BOND_LINK_XXXX */
-	char   state;   /* one of BOND_STATE_XXXX */
-	unsigned short original_flags;
-	u32 link_failure_count;
+	s16    delay;
+	u32    jiffies;
+	s8     link;    /* one of BOND_LINK_XXXX */
+	s8     state;   /* one of BOND_STATE_XXXX */
+	u32    original_flags;
+	u32    link_failure_count;
 	u16    speed;
 	u8     duplex;
 	u8     perm_hwaddr[ETH_ALEN];
 	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
 	struct tlb_slave_info tlb_info;
-} slave_t;
+};
 
 /*
  * Here are the locking policies for the two bonding locks:
  *
  * 1) Get bond->lock when reading/writing slave list.
- * 2) Get bond->ptrlock when reading/writing bond->current_slave.
+ * 2) Get bond->curr_slave_lock when reading/writing bond->curr_active_slave.
  *    (It is unnecessary when the write-lock is put with bond->lock.)
- * 3) When we lock with bond->ptrlock, we must lock with bond->lock
+ * 3) When we lock with bond->curr_slave_lock, we must lock with bond->lock
  *    beforehand.
  */
-typedef struct bonding {
-	slave_t *next;
-	slave_t *prev;
-	slave_t *current_slave;
-	slave_t *primary_slave;
-	slave_t *current_arp_slave;
-	__s32 slave_cnt;
+struct bonding {
+	struct   net_device *dev; /* first - usefull for panic debug */
+	struct   slave *first_slave;
+	struct   slave *curr_active_slave;
+	struct   slave *current_arp_slave;
+	struct   slave *primary_slave;
+	s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
 	rwlock_t lock;
-	rwlock_t ptrlock;
-	struct timer_list mii_timer;
-	struct timer_list arp_timer;
-	struct net_device_stats stats;
+	rwlock_t curr_slave_lock;
+	struct   timer_list mii_timer;
+	struct   timer_list arp_timer;
+	s8       kill_timers;
+	struct   net_device_stats stats;
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *bond_proc_file;
-	char procdir_name[IFNAMSIZ];
+	struct   proc_dir_entry *proc_entry;
+	char     proc_file_name[IFNAMSIZ];
 #endif /* CONFIG_PROC_FS */
-	struct list_head bond_list;
-	struct net_device *device;
-	struct dev_mc_list *mc_list;
-	unsigned short flags;
-	struct ad_bond_info ad_info;
-	struct alb_bond_info alb_info;
-} bonding_t;
-
-/* Forward declarations */
-void bond_set_slave_active_flags(slave_t *slave);
-void bond_set_slave_inactive_flags(slave_t *slave);
-
-/**
- * These functions can be used for iterating the slave list
- * (which is circular)
- * Caller must hold bond lock for read
- */
-extern inline struct slave*
-bond_get_first_slave(struct bonding *bond)
-{
-	/* if there are no slaves return NULL */
-	if (bond->next == (slave_t *)bond) {
-		return NULL;
-	}
-	return bond->next;
-}
-
-/**
- * Caller must hold bond lock for read
- */
-extern inline struct slave*
-bond_get_next_slave(struct bonding *bond, struct slave *slave)
-{
-	/* If we have reached the last slave return NULL */
-	if (slave->next == bond->next) {
-		return NULL;
-	}
-	return slave->next;
-}
+	struct   list_head bond_list;
+	struct   dev_mc_list *mc_list;
+	u16      flags;
+	struct   ad_bond_info ad_info;
+	struct   alb_bond_info alb_info;
+	struct   bond_params params;
+	struct   list_head vlan_list;
+	struct   vlan_group *vlgrp;
+};
 
 /**
  * Returns NULL if the net_device does not belong to any of the bond's slaves
  *
  * Caller must hold bond lock for read
  */
-extern inline struct slave*
-bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
 {
-	struct slave *our_slave = bond->next;
+	struct slave *slave = NULL;
+	int i;
 
-	/* check if the list of slaves is empty */
-	if (our_slave == (slave_t *)bond) {
-		return NULL;
-	}
-
-	for (; our_slave; our_slave = bond_get_next_slave(bond, our_slave)) {
-		if (our_slave->dev == slave_dev) {
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev == slave_dev) {
 			break;
 		}
 	}
-	return our_slave;
+
+	return slave;
 }
 
-extern inline struct bonding*
-bond_get_bond_by_slave(struct slave *slave)
+extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
 {
 	if (!slave || !slave->dev->master) {
 		return NULL;
 	}
 
-	return (struct bonding *)(slave->dev->master->priv);
+	return (struct bonding *)slave->dev->master->priv;
 }
 
+extern inline void bond_set_slave_inactive_flags(struct slave *slave)
+{
+	slave->state = BOND_STATE_BACKUP;
+	slave->dev->flags |= IFF_NOARP;
+}
+
+extern inline void bond_set_slave_active_flags(struct slave *slave)
+{
+	slave->state = BOND_STATE_ACTIVE;
+	slave->dev->flags &= ~IFF_NOARP;
+}
+
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+
 #endif /* _LINUX_BONDING_H */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000.h linux-2.4.26-pre6/drivers/net/e1000/e1000.h
--- linux-2.4.25/drivers/net/e1000/e1000.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000.h	2004-03-25 00:19:04.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
@@ -92,6 +92,16 @@ struct e1000_adapter;
 
 #define E1000_MAX_INTR 10
 
+/* How many descriptors for TX and RX ? */
+#define E1000_DEFAULT_TXD                  256
+#define E1000_MAX_TXD                      256
+#define E1000_MIN_TXD                       80
+#define E1000_MAX_82544_TXD               4096
+#define E1000_DEFAULT_RXD                  256
+#define E1000_MAX_RXD                      256
+#define E1000_MIN_RXD                       80
+#define E1000_MAX_82544_RXD               4096
+
 /* Supported Rx Buffer Sizes */
 #define E1000_RXBUFFER_2048  2048
 #define E1000_RXBUFFER_4096  4096
@@ -192,10 +202,14 @@ struct e1000_adapter {
 
 	/* TX */
 	struct e1000_desc_ring tx_ring;
+	spinlock_t tx_lock;
 	uint32_t txd_cmd;
 	uint32_t tx_int_delay;
 	uint32_t tx_abs_int_delay;
 	uint32_t gotcl;
+	uint64_t gotcl_old;
+	uint64_t tpt_old;
+	uint64_t colc_old;
 	uint32_t tx_fifo_head;
 	uint32_t tx_head_addr;
 	uint32_t tx_fifo_size;
@@ -210,6 +224,7 @@ struct e1000_adapter {
 	uint32_t rx_abs_int_delay;
 	boolean_t rx_csum;
 	uint32_t gorcl;
+	uint64_t gorcl_old;
 
 	/* Interrupt Throttle Rate */
 	uint32_t itr;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000_ethtool.c linux-2.4.26-pre6/drivers/net/e1000/e1000_ethtool.c
--- linux-2.4.25/drivers/net/e1000/e1000_ethtool.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000_ethtool.c	2004-03-25 00:20:50.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
@@ -39,6 +39,11 @@ extern int e1000_up(struct e1000_adapter
 extern void e1000_down(struct e1000_adapter *adapter);
 extern void e1000_reset(struct e1000_adapter *adapter);
 extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
+extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_update_stats(struct e1000_adapter *adapter);
 
 struct e1000_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -579,8 +584,8 @@ e1000_intr_test(struct e1000_adapter *ad
 	*data = 0;
 
 	/* Hook up test interrupt handler just for this test */
-	if(request_irq
-	   (netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) {
+	if(request_irq(adapter->pdev->irq, &e1000_test_intr, SA_SHIRQ,
+	   netdev->name, netdev)) {
 		*data = 1;
 		return -1;
 	}
@@ -664,7 +669,7 @@ e1000_intr_test(struct e1000_adapter *ad
 	msec_delay(10);
 
 	/* Unhook test interrupt handler */
-	free_irq(netdev->irq, netdev);
+	free_irq(adapter->pdev->irq, netdev);
 
 	return *data;
 }
@@ -770,9 +775,9 @@ e1000_setup_desc_rings(struct e1000_adap
 				       PCI_DMA_TODEVICE);
 		tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
 		tx_desc->lower.data = cpu_to_le32(skb->len);
-		tx_desc->lower.data |= E1000_TXD_CMD_EOP;
-		tx_desc->lower.data |= E1000_TXD_CMD_IFCS;
-		tx_desc->lower.data |= E1000_TXD_CMD_RPS;
+		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
+						   E1000_TXD_CMD_IFCS |
+						   E1000_TXD_CMD_RPS);
 		tx_desc->upper.data = 0;
 	}
 
@@ -1522,6 +1527,7 @@ err_geeprom_ioctl:
 		} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
 		int i;
 
+		e1000_update_stats(adapter);
 		for(i = 0; i < E1000_STATS_LEN; i++)
 			stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
 					sizeof(uint64_t)) ?
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000_hw.c linux-2.4.26-pre6/drivers/net/e1000/e1000_hw.c
--- linux-2.4.25/drivers/net/e1000/e1000_hw.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000_hw.c	2004-03-25 00:20:52.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
@@ -96,8 +96,14 @@ e1000_set_phy_type(struct e1000_hw *hw)
         hw->phy_type = e1000_phy_m88;
         break;
     case IGP01E1000_I_PHY_ID:
-        hw->phy_type = e1000_phy_igp;
-        break;
+        if(hw->mac_type == e1000_82541 ||
+           hw->mac_type == e1000_82541_rev_2 ||
+           hw->mac_type == e1000_82547 ||
+           hw->mac_type == e1000_82547_rev_2) {
+            hw->phy_type = e1000_phy_igp;
+            break;
+        }
+        /* Fall Through */
     default:
         /* Should never have loaded on this device */
         hw->phy_type = e1000_phy_undefined;
@@ -148,7 +154,6 @@ e1000_phy_init_script(struct e1000_hw *h
 
         e1000_write_phy_reg(hw, 0x0000, 0x3300);
 
-
         if(hw->mac_type == e1000_82547) {
             uint16_t fused, fine, coarse;
 
@@ -1485,8 +1490,8 @@ e1000_phy_force_speed_duplex(struct e100
             if(mii_status_reg & MII_SR_LINK_STATUS) break;
             msec_delay(100);
         }
-        if(i == 0) { /* We didn't get link */
-            /* Reset the DSP and wait again for link. */
+        if((i == 0) && (hw->phy_type == e1000_phy_m88)) {
+            /* We didn't get link.  Reset the DSP and wait again for link. */
             if((ret_val = e1000_phy_reset_dsp(hw))) {
                 DEBUGOUT("Error Resetting PHY DSP\n");
                 return ret_val;
@@ -1533,6 +1538,25 @@ e1000_phy_force_speed_duplex(struct e100
                                           phy_data)))
             return ret_val;
 
+        /* Polarity reversal workaround for forced 10F/10H links. */
+        if(hw->mac_type <= e1000_82544 &&
+           (hw->forced_speed_duplex == e1000_10_full ||
+            hw->forced_speed_duplex == e1000_10_half)) {
+            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
+                                              0x0019)))
+                return ret_val;
+            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
+                                              0x8F0F)))
+                return ret_val;
+            /* IEEE requirement is 150ms */
+            msec_delay(200);
+            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
+                                              0x0019)))
+                return ret_val;
+            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
+                                              0x8F00)))
+                return ret_val;
+        }
     }
     return E1000_SUCCESS;
 }
@@ -1916,7 +1940,6 @@ e1000_check_for_link(struct e1000_hw *hw
     uint32_t signal = 0;
     int32_t ret_val;
     uint16_t phy_data;
-    uint16_t lp_capability;
 
     DEBUGFUNC("e1000_check_for_link");
 
@@ -1996,24 +2019,17 @@ e1000_check_for_link(struct e1000_hw *hw
 
         /* At this point we know that we are on copper and we have
          * auto-negotiated link.  These are conditions for checking the link
-         * parter capability register.  We use the link partner capability to
-         * determine if TBI Compatibility needs to be turned on or off.  If
-         * the link partner advertises any speed in addition to Gigabit, then
-         * we assume that they are GMII-based, and TBI compatibility is not
-         * needed. If no other speeds are advertised, we assume the link
-         * partner is TBI-based, and we turn on TBI Compatibility.
-         */
-        if(hw->tbi_compatibility_en) {
-            if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
-                                             &lp_capability)))
-                return ret_val;
-            if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
-                                NWAY_LPAR_10T_FD_CAPS |
-                                NWAY_LPAR_100TX_HD_CAPS |
-                                NWAY_LPAR_100TX_FD_CAPS |
-                                NWAY_LPAR_100T4_CAPS)) {
-                /* If our link partner advertises anything in addition to
-                 * gigabit, we do not need to enable TBI compatibility.
+         * partner capability register.  We use the link speed to determine if
+         * TBI compatibility needs to be turned on or off.  If the link is not
+         * at gigabit speed, then TBI compatibility is not needed.  If we are
+         * at gigabit speed, we turn on TBI compatibility.
+         */
+	if(hw->tbi_compatibility_en) {
+            uint16_t speed, duplex;
+            e1000_get_speed_and_duplex(hw, &speed, &duplex);
+            if(speed != SPEED_1000) {
+                /* If link speed is not set to gigabit speed, we do not need
+                 * to enable TBI compatibility.
                  */
                 if(hw->tbi_compatibility_on) {
                     /* If we previously were in the mode, turn it off. */
@@ -2081,6 +2097,29 @@ e1000_check_for_link(struct e1000_hw *hw
         DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+
+        hw->serdes_link_down = FALSE;
+    }
+    /* If we force link for non-auto-negotiation switch, check link status
+     * based on MAC synchronization for internal serdes media type.
+     */
+    else if((hw->media_type == e1000_media_type_internal_serdes) &&
+            !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+        /* SYNCH bit and IV bit are sticky. */
+        udelay(10);
+        if(E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+            if(!(rxcw & E1000_RXCW_IV)) {
+                hw->serdes_link_down = FALSE;
+                DEBUGOUT("SERDES: Link is up.\n");
+            }
+        } else {
+            hw->serdes_link_down = TRUE;
+            DEBUGOUT("SERDES: Link is down.\n");
+        }
+    }
+    if((hw->media_type == e1000_media_type_internal_serdes) &&
+       (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+        hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS));
     }
     return E1000_SUCCESS;
 }
@@ -3742,22 +3781,13 @@ void
 e1000_init_rx_addrs(struct e1000_hw *hw)
 {
     uint32_t i;
-    uint32_t addr_low;
-    uint32_t addr_high;
 
     DEBUGFUNC("e1000_init_rx_addrs");
 
     /* Setup the receive address. */
     DEBUGOUT("Programming MAC Address into RAR[0]\n");
-    addr_low = (hw->mac_addr[0] |
-                (hw->mac_addr[1] << 8) |
-                (hw->mac_addr[2] << 16) | (hw->mac_addr[3] << 24));
-
-    addr_high = (hw->mac_addr[4] |
-                 (hw->mac_addr[5] << 8) | E1000_RAH_AV);
 
-    E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low);
-    E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high);
+    e1000_rar_set(hw, hw->mac_addr, 0);
 
     /* Zero out the other 15 receive addresses. */
     DEBUGOUT("Clearing RAR[1-15]\n");
@@ -3774,6 +3804,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
  * mc_addr_list - the list of new multicast addresses
  * mc_addr_count - number of addresses
  * pad - number of bytes between addresses in the list
+ * rar_used_count - offset where to start adding mc addresses into the RAR's
  *
  * The given list replaces any existing list. Clears the last 15 receive
  * address registers and the multicast table. Uses receive address registers
@@ -3784,11 +3815,11 @@ void
 e1000_mc_addr_list_update(struct e1000_hw *hw,
                           uint8_t *mc_addr_list,
                           uint32_t mc_addr_count,
-                          uint32_t pad)
+                          uint32_t pad,
+                          uint32_t rar_used_count)
 {
     uint32_t hash_value;
     uint32_t i;
-    uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
 
     DEBUGFUNC("e1000_mc_addr_list_update");
 
@@ -4522,8 +4553,8 @@ uint32_t
 e1000_read_reg_io(struct e1000_hw *hw,
                   uint32_t offset)
 {
-    uint32_t io_addr = hw->io_base;
-    uint32_t io_data = hw->io_base + 4;
+    unsigned long io_addr = hw->io_base;
+    unsigned long io_data = hw->io_base + 4;
 
     e1000_io_write(hw, io_addr, offset);
     return e1000_io_read(hw, io_data);
@@ -4542,8 +4573,8 @@ e1000_write_reg_io(struct e1000_hw *hw,
                    uint32_t offset,
                    uint32_t value)
 {
-    uint32_t io_addr = hw->io_base;
-    uint32_t io_data = hw->io_base + 4;
+    unsigned long io_addr = hw->io_base;
+    unsigned long io_data = hw->io_base + 4;
 
     e1000_io_write(hw, io_addr, offset);
     e1000_io_write(hw, io_data, value);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000_hw.h linux-2.4.26-pre6/drivers/net/e1000/e1000_hw.h
--- linux-2.4.25/drivers/net/e1000/e1000_hw.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000_hw.h	2004-03-25 00:17:55.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
@@ -291,7 +291,7 @@ int32_t e1000_read_mac_addr(struct e1000
 
 /* Filters (multicast, vlan, receive) */
 void e1000_init_rx_addrs(struct e1000_hw *hw);
-void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad);
+void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
 uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
 void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
 void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -317,9 +317,9 @@ void e1000_pci_clear_mwi(struct e1000_hw
 void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 /* Port I/O is only supported on 82544 and newer */
-uint32_t e1000_io_read(struct e1000_hw *hw, uint32_t port);
+uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
 uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
-void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value);
+void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
 void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
 int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up);
 int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
@@ -978,7 +978,7 @@ struct e1000_hw {
     e1000_ms_type master_slave;
     e1000_ms_type original_master_slave;
     e1000_ffe_config ffe_config_state;
-    uint32_t io_base;
+    unsigned long io_base;
     uint32_t phy_id;
     uint32_t phy_revision;
     uint32_t phy_addr;
@@ -1021,6 +1021,7 @@ struct e1000_hw {
     boolean_t speed_downgraded;
     e1000_dsp_config dsp_config_state;
     boolean_t get_link_status;
+    boolean_t serdes_link_down;
     boolean_t tbi_compatibility_en;
     boolean_t tbi_compatibility_on;
     boolean_t phy_reset_disable;
@@ -1310,6 +1311,7 @@ struct e1000_hw {
 #define E1000_RCTL_DPF            0x00400000    /* discard pause frames */
 #define E1000_RCTL_PMCF           0x00800000    /* pass MAC control frames */
 #define E1000_RCTL_BSEX           0x02000000    /* Buffer size extension */
+#define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
 
 /* Receive Descriptor */
 #define E1000_RDT_DELAY 0x0000ffff      /* Delay timer (1=1024us) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000_main.c linux-2.4.26-pre6/drivers/net/e1000/e1000_main.c
--- linux-2.4.25/drivers/net/e1000/e1000_main.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000_main.c	2004-03-25 00:19:24.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
@@ -30,10 +30,24 @@
 
 /* Change Log
  *
- * 5.2.20	9/30/03
+ * 5.2.30.1	1/29/03
+ *   o Set VLAN filtering to IEEE 802.1Q after reset so we don't break
+ *     SoL connections that use VLANs.
+ *   o Allow 1000/Full setting for AutoNeg param for Fiber connections
+ *     Jon D Mason [jonmason@us.ibm.com].
+ *   o Race between Tx queue and Tx clean fixed with a spin lock.
+ *   o Added netpoll support.
+ *   o Fixed endianess bug causing ethtool loopback diags to fail on ppc.
+ *   o Use pdev->irq rather than netdev->irq in preparation for MSI support.
+ *   o Report driver message on user override of InterruptThrottleRate
+ *     module parameter.
+ *   o Change I/O address storage from uint32_t to unsigned long.
+ *
+ * 5.2.22	10/15/03
  *   o Bug fix: SERDES devices might be connected to a back-plane
  *     switch that doesn't support auto-neg, so add the capability
- *     to force 1000/Full.
+ *     to force 1000/Full.  Also, since forcing 1000/Full, sample
+ *     RxSynchronize bit to detect link state.
  *   o Bug fix: Flow control settings for hi/lo watermark didn't
  *     consider changes in the Rx FIFO size, which could occur with
  *     Jumbo Frames or with the reduced FIFO in 82547.
@@ -42,30 +56,19 @@
  *   o Bug fix: hang under heavy Tx stress when running out of Tx
  *     descriptors; wasn't clearing context descriptor when backing
  *     out of send because of no-resource condition.
+ *   o Bug fix: check netif_running in dev->poll so we don't have to
+ *     hang in dev->close until all polls are finished.  [Robert
+ *     Ollson (robert.olsson@data.slu.se)].
+ *   o Revert TxDescriptor ring size back to 256 since change to 1024
+ *     wasn't accepted into the kernel.
  *
  * 5.2.16	8/8/03
- *   o Added support for new controllers: 82545GM, 82546GB, 82541/7_B1
- *   o Bug fix: reset h/w before first EEPROM read because we don't know
- *     who may have been messing with the device before we got there.
- *     [Dave Johnson (ddj -a-t- cascv.brown.edu)]
- *   o Bug fix: read the correct work from EEPROM to detect programmed
- *     WoL settings.
- *   o Bug fix: TSO would hang if space left in FIFO was being miscalculated
- *     when mss dropped without a correspoding drop in the DMA buffer size.
- *   o ASF for Fiber nics isn't supported.
- *   o Bug fix: Workaround added for potential hang with 82544 running in
- *     PCI-X if send buffer terminates within an evenly-aligned dword.
- *   o Feature: Add support for ethtool flow control setting.
- *   o Feature: Add support for ethtool TSO setting.
- *   o Feature: Increase default Tx Descriptor count to 1024 for >= 82544.
- *   
- * 5.1.13	5/28/03
  */
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.2.20-k1";
-char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
+char e1000_driver_version[] = "5.2.30.1-k1";
+char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
@@ -89,7 +92,6 @@ static struct pci_device_id e1000_pci_tb
 	{0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -113,12 +115,17 @@ static struct pci_device_id e1000_pci_tb
 
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-/* Local Function Prototypes */
-
 int e1000_up(struct e1000_adapter *adapter);
 void e1000_down(struct e1000_adapter *adapter);
 void e1000_reset(struct e1000_adapter *adapter);
 int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
+int e1000_setup_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_rx_resources(struct e1000_adapter *adapter);
+void e1000_update_stats(struct e1000_adapter *adapter);
+
+/* Local Function Prototypes */
 
 static int e1000_init_module(void);
 static void e1000_exit_module(void);
@@ -127,15 +134,11 @@ static void __devexit e1000_remove(struc
 static int e1000_sw_init(struct e1000_adapter *adapter);
 static int e1000_open(struct net_device *netdev);
 static int e1000_close(struct net_device *netdev);
-static int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-static int e1000_setup_rx_resources(struct e1000_adapter *adapter);
 static void e1000_configure_tx(struct e1000_adapter *adapter);
 static void e1000_configure_rx(struct e1000_adapter *adapter);
 static void e1000_setup_rctl(struct e1000_adapter *adapter);
 static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
 static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
-static void e1000_free_tx_resources(struct e1000_adapter *adapter);
-static void e1000_free_rx_resources(struct e1000_adapter *adapter);
 static void e1000_set_multi(struct net_device *netdev);
 static void e1000_update_phy_info(unsigned long data);
 static void e1000_watchdog(unsigned long data);
@@ -144,7 +147,6 @@ static int e1000_xmit_frame(struct sk_bu
 static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
 static int e1000_set_mac(struct net_device *netdev, void *p);
-static void e1000_update_stats(struct e1000_adapter *adapter);
 static inline void e1000_irq_disable(struct e1000_adapter *adapter);
 static inline void e1000_irq_enable(struct e1000_adapter *adapter);
 static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
@@ -182,6 +184,11 @@ static int e1000_suspend(struct pci_dev 
 static int e1000_resume(struct pci_dev *pdev);
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/* for netdump / net console */
+static void e1000_netpoll (struct net_device *dev);
+#endif
+
 struct notifier_block e1000_notifier_reboot = {
 	.notifier_call	= e1000_notify_reboot,
 	.next		= NULL,
@@ -268,7 +275,7 @@ e1000_up(struct e1000_adapter *adapter)
 	e1000_configure_rx(adapter);
 	e1000_alloc_rx_buffers(adapter);
 
-	if((err = request_irq(netdev->irq, &e1000_intr,
+	if((err = request_irq(adapter->pdev->irq, &e1000_intr,
 		              SA_SHIRQ | SA_SAMPLE_RANDOM,
 		              netdev->name, netdev)))
 		return err;
@@ -285,7 +292,7 @@ e1000_down(struct e1000_adapter *adapter
 	struct net_device *netdev = adapter->netdev;
 
 	e1000_irq_disable(adapter);
-	free_irq(netdev->irq, netdev);
+	free_irq(adapter->pdev->irq, netdev);
 	del_timer_sync(&adapter->tx_fifo_stall_timer);
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
@@ -336,6 +343,10 @@ e1000_reset(struct e1000_adapter *adapte
 	if(adapter->hw.mac_type >= e1000_82544)
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
 	e1000_init_hw(&adapter->hw);
+
+	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
+	E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
+
 	e1000_reset_adaptive(&adapter->hw);
 	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
 }
@@ -433,8 +444,10 @@ e1000_probe(struct pci_dev *pdev,
 	netdev->vlan_rx_register = e1000_vlan_rx_register;
 	netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
 	netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = e1000_netpoll;
+#endif
 
-	netdev->irq = pdev->irq;
 	netdev->mem_start = mmio_start;
 	netdev->mem_end = mmio_start + mmio_len;
 	netdev->base_addr = adapter->hw.io_base;
@@ -668,6 +681,7 @@ e1000_sw_init(struct e1000_adapter *adap
 
 	atomic_set(&adapter->irq_sem, 1);
 	spin_lock_init(&adapter->stats_lock);
+	spin_lock_init(&adapter->tx_lock);
 
 	return 0;
 }
@@ -748,7 +762,7 @@ e1000_close(struct net_device *netdev)
  * Return 0 on success, negative on failure
  **/
 
-static int
+int
 e1000_setup_tx_resources(struct e1000_adapter *adapter)
 {
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
@@ -865,7 +879,7 @@ e1000_configure_tx(struct e1000_adapter 
  * Returns 0 on success, negative on failure
  **/
 
-static int
+int
 e1000_setup_rx_resources(struct e1000_adapter *adapter)
 {
 	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
@@ -1004,7 +1018,7 @@ e1000_configure_rx(struct e1000_adapter 
  * Free all transmit software resources
  **/
 
-static void
+void
 e1000_free_tx_resources(struct e1000_adapter *adapter)
 {
 	struct pci_dev *pdev = adapter->pdev;
@@ -1072,7 +1086,7 @@ e1000_clean_tx_ring(struct e1000_adapter
  * Free all receive software resources
  **/
 
-static void
+void
 e1000_free_rx_resources(struct e1000_adapter *adapter)
 {
 	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
@@ -1280,41 +1294,6 @@ e1000_set_multi(struct net_device *netde
 		e1000_leave_82542_rst(adapter);
 }
 
-static void
-e1000_tx_flush(struct e1000_adapter *adapter)
-{
-	uint32_t ctrl, tctl, txcw, icr;
-
-	e1000_irq_disable(adapter);
-
-	if(adapter->hw.mac_type < e1000_82543) {
-		/* Transmit Unit Reset */
-		tctl = E1000_READ_REG(&adapter->hw, TCTL);
-		E1000_WRITE_REG(&adapter->hw, TCTL, tctl | E1000_TCTL_RST);
-		E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
-		e1000_clean_tx_ring(adapter);
-		e1000_configure_tx(adapter);
-	} else {
-		txcw = E1000_READ_REG(&adapter->hw, TXCW);
-		E1000_WRITE_REG(&adapter->hw, TXCW, txcw & ~E1000_TXCW_ANE);
-
-		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
-		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl | E1000_CTRL_SLU |
-				E1000_CTRL_ILOS);
-
-		mdelay(10);
-
-		e1000_clean_tx_irq(adapter);
-		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
-		E1000_WRITE_REG(&adapter->hw, TXCW, txcw);
-
-		/* clear the link status change interrupts this caused */
-		icr = E1000_READ_REG(&adapter->hw, ICR);
-	}
-
-	e1000_irq_enable(adapter);
-}
-
 /* need to wait a few seconds after link up to get diagnostic information from the phy */
 
 static void
@@ -1378,10 +1357,17 @@ e1000_watchdog(unsigned long data)
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
 	unsigned int i;
+	uint32_t link;
 
 	e1000_check_for_link(&adapter->hw);
 
-	if(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
+	if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+	   !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
+		link = !adapter->hw.serdes_link_down;
+	else
+		link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
+
+	if(link) {
 		if(!netif_carrier_ok(netdev)) {
 			e1000_get_speed_and_duplex(&adapter->hw,
 			                           &adapter->link_speed,
@@ -1414,14 +1400,26 @@ e1000_watchdog(unsigned long data)
 	}
 
 	e1000_update_stats(adapter);
+
+	adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
+	adapter->tpt_old = adapter->stats.tpt;
+	adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
+	adapter->colc_old = adapter->stats.colc;
+	
+	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
+	adapter->gorcl_old = adapter->stats.gorcl;
+	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
+	adapter->gotcl_old = adapter->stats.gotcl;
+
 	e1000_update_adaptive(&adapter->hw);
 
 	if(!netif_carrier_ok(netdev)) {
 		if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
-			unsigned long flags;
-			spin_lock_irqsave(&netdev->xmit_lock, flags);
-			e1000_tx_flush(adapter);
-			spin_unlock_irqrestore(&netdev->xmit_lock, flags);
+			/* We've lost link, so the controller stops DMA,
+			 * but we've got queued Tx work that's never going
+			 * to get done, so reset controller to flush Tx.
+			 * (Do the reset outside of interrupt context). */
+			schedule_task(&adapter->tx_timeout_task);
 		}
 	}
 
@@ -1685,7 +1683,7 @@ e1000_tx_map(struct e1000_adapter *adapt
 	i = (i == 0) ? tx_ring->count - 1 : i - 1;
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
-
+	
 	return count;
 }
 
@@ -1782,6 +1780,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
 	struct e1000_adapter *adapter = netdev->priv;
 	unsigned int first;
 	unsigned int tx_flags = 0;
+	unsigned long flags;
 	int count;
 
 	if(skb->len <= 0) {
@@ -1789,10 +1788,13 @@ e1000_xmit_frame(struct sk_buff *skb, st
 		return 0;
 	}
 
+	spin_lock_irqsave(&adapter->tx_lock, flags);
+
 	if(adapter->hw.mac_type == e1000_82547) {
 		if(e1000_82547_fifo_workaround(adapter, skb)) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
+			spin_unlock_irqrestore(&adapter->tx_lock, flags);
 			return 1;
 		}
 	}
@@ -1813,11 +1815,14 @@ e1000_xmit_frame(struct sk_buff *skb, st
 		e1000_tx_queue(adapter, count, tx_flags);
 	else {
 		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
 		return 1;
 	}
 
 	netdev->trans_start = jiffies;
 
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	
 	return 0;
 }
 
@@ -1859,6 +1864,7 @@ e1000_get_stats(struct net_device *netde
 {
 	struct e1000_adapter *adapter = netdev->priv;
 
+	e1000_update_stats(adapter);
 	return &adapter->net_stats;
 }
 
@@ -1917,7 +1923,7 @@ e1000_change_mtu(struct net_device *netd
  * @adapter: board private structure
  **/
 
-static void
+void
 e1000_update_stats(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
@@ -1935,8 +1941,7 @@ e1000_update_stats(struct e1000_adapter 
 
 	adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
 	adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
-	adapter->gorcl = E1000_READ_REG(hw, GORCL);
-	adapter->stats.gorcl += adapter->gorcl;
+	adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
 	adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
 	adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
 	adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
@@ -1948,8 +1953,6 @@ e1000_update_stats(struct e1000_adapter 
 	adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
 	adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
 
-	spin_unlock_irqrestore(&adapter->stats_lock, flags);
-
 	/* the rest of the counters are only modified here */
 
 	adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
@@ -1967,8 +1970,7 @@ e1000_update_stats(struct e1000_adapter 
 	adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
 	adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
 	adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
-	adapter->gotcl = E1000_READ_REG(hw, GOTCL);
-	adapter->stats.gotcl += adapter->gotcl;
+	adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
 	adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
 	adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
 	adapter->stats.ruc += E1000_READ_REG(hw, RUC);
@@ -2050,6 +2052,8 @@ e1000_update_stats(struct e1000_adapter 
 		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
 			adapter->phy_stats.receive_errors += phy_tmp;
 	}
+
+	spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
 /**
@@ -2092,6 +2096,7 @@ e1000_intr(int irq, void *data, struct p
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev->priv;
+	struct e1000_hw *hw = &adapter->hw;
 	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
 #ifndef CONFIG_E1000_NAPI
 	unsigned int i;
@@ -2101,7 +2106,7 @@ e1000_intr(int irq, void *data, struct p
 		return IRQ_NONE;  /* Not our interrupt */
 
 	if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
-		adapter->hw.get_link_status = 1;
+		hw->get_link_status = 1;
 		mod_timer(&adapter->watchdog_timer, jiffies);
 	}
 
@@ -2113,14 +2118,30 @@ e1000_intr(int irq, void *data, struct p
 		*/
 
 		atomic_inc(&adapter->irq_sem);
-		E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+		E1000_WRITE_REG(hw, IMC, ~0);
 		__netif_rx_schedule(netdev);
 	}
 #else
+        /* Writing IMC and IMS is needed for 82547.
+	   Due to Hub Link bus being occupied, an interrupt 
+	   de-assertion message is not able to be sent. 
+	   When an interrupt assertion message is generated later,
+	   two messages are re-ordered and sent out.
+	   That causes APIC to think 82547 is in de-assertion
+	   state, while 82547 is in assertion state, resulting 
+	   in dead lock. Writing IMC forces 82547 into 
+	   de-assertion state.
+        */
+	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+		e1000_irq_disable(adapter);
+
 	for(i = 0; i < E1000_MAX_INTR; i++)
 		if(!e1000_clean_rx_irq(adapter) &
 		   !e1000_clean_tx_irq(adapter))
 			break;
+
+	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+		e1000_irq_enable(adapter);
 #endif
 
 	return IRQ_HANDLED;
@@ -2145,7 +2166,7 @@ e1000_clean(struct net_device *netdev, i
 	*budget -= work_done;
 	netdev->quota -= work_done;
 	
-	if(work_done < work_to_do) {
+	if(work_done < work_to_do || !netif_running(netdev)) {
 		netif_rx_complete(netdev);
 		e1000_irq_enable(adapter);
 	}
@@ -2170,6 +2191,8 @@ e1000_clean_tx_irq(struct e1000_adapter 
 	unsigned int i, eop;
 	boolean_t cleaned = FALSE;
 
+	spin_lock(&adapter->tx_lock);
+
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
@@ -2214,6 +2237,8 @@ e1000_clean_tx_irq(struct e1000_adapter 
 	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
 		netif_wake_queue(netdev);
 
+	spin_unlock(&adapter->tx_lock);
+
 	return cleaned;
 }
 
@@ -2641,13 +2666,13 @@ e1000_write_pci_cfg(struct e1000_hw *hw,
 }
 
 uint32_t
-e1000_io_read(struct e1000_hw *hw, uint32_t port)
+e1000_io_read(struct e1000_hw *hw, unsigned long port)
 {
 	return inl(port);
 }
 
 void
-e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value)
+e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
 {
 	outl(value, port);
 }
@@ -2664,8 +2689,6 @@ e1000_vlan_rx_register(struct net_device
 	if(grp) {
 		/* enable VLAN tag insert/strip */
 
-		E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
-
 		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 		ctrl |= E1000_CTRL_VME;
 		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
@@ -2899,4 +2922,20 @@ e1000_resume(struct pci_dev *pdev)
 }
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void e1000_netpoll (struct net_device *dev)
+{
+	struct e1000_adapter *adapter = dev->priv;
+	disable_irq(adapter->pdev->irq);
+	e1000_intr (adapter->pdev->irq, dev, NULL);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
+
 /* e1000_main.c */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000_osdep.h linux-2.4.26-pre6/drivers/net/e1000/e1000_osdep.h
--- linux-2.4.25/drivers/net/e1000/e1000_osdep.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000_osdep.h	2004-03-25 00:18:36.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/e1000/e1000_param.c linux-2.4.26-pre6/drivers/net/e1000/e1000_param.c
--- linux-2.4.25/drivers/net/e1000/e1000_param.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/e1000/e1000_param.c	2004-03-25 00:17:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   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 
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(X, S);
 /* Transmit Descriptor Count
  *
  * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
- * Valid Range: 80-4096 for 82544
+ * Valid Range: 80-4096 for 82544 and newer
  *
  * Default Value: 256
  */
@@ -73,7 +73,7 @@ E1000_PARAM(TxDescriptors, "Number of tr
 /* Receive Descriptor Count
  *
  * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
- * Valid Range: 80-4096 for 82544
+ * Valid Range: 80-4096 for 82544 and newer
  *
  * Default Value: 256
  */
@@ -196,16 +196,6 @@ E1000_PARAM(InterruptThrottleRate, "Inte
 #define AUTONEG_ADV_MASK     0x2F
 #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
 
-#define DEFAULT_TXD                  256
-#define MAX_TXD                      256
-#define MIN_TXD                       80
-#define MAX_82544_TXD               4096
-
-#define DEFAULT_RXD                  256
-#define MAX_RXD                      256
-#define MIN_RXD                       80
-#define MAX_82544_RXD               4096
-
 #define DEFAULT_RDTR                   0
 #define MAX_RXDELAY               0xFFFF
 #define MIN_RXDELAY                    0
@@ -299,7 +289,7 @@ static void e1000_check_copper_options(s
  * e1000_check_options - Range Checking for Command Line Parameters
  * @adapter: board private structure
  *
- * This routine checks all command line paramters for valid user
+ * This routine checks all command line parameters for valid user
  * input.  If an invalid value is given, or if no user specified
  * value exists, a default value is used.  The final value is stored
  * in a variable in the adapter structure.
@@ -320,14 +310,15 @@ e1000_check_options(struct e1000_adapter
 		struct e1000_option opt = {
 			.type = range_option,
 			.name = "Transmit Descriptors",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_TXD),
-			.def  = DEFAULT_TXD,
-			.arg  = { .r = { .min = MIN_TXD }}
+			.err  = "using default of "
+				__MODULE_STRING(E1000_DEFAULT_TXD),
+			.def  = E1000_DEFAULT_TXD,
+			.arg  = { .r = { .min = E1000_MIN_TXD }}
 		};
 		struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 		e1000_mac_type mac_type = adapter->hw.mac_type;
 		opt.arg.r.max = mac_type < e1000_82544 ?
-			MAX_TXD : MAX_82544_TXD;
+			E1000_MAX_TXD : E1000_MAX_82544_TXD;
 
 		tx_ring->count = TxDescriptors[bd];
 		e1000_validate_option(&tx_ring->count, &opt);
@@ -337,13 +328,15 @@ e1000_check_options(struct e1000_adapter
 		struct e1000_option opt = {
 			.type = range_option,
 			.name = "Receive Descriptors",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_RXD),
-			.def  = DEFAULT_RXD,
-			.arg  = { .r = { .min = MIN_RXD }}
+			.err  = "using default of "
+				__MODULE_STRING(E1000_DEFAULT_RXD),
+			.def  = E1000_DEFAULT_RXD,
+			.arg  = { .r = { .min = E1000_MIN_RXD }}
 		};
 		struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 		e1000_mac_type mac_type = adapter->hw.mac_type;
-		opt.arg.r.max = mac_type < e1000_82544 ? MAX_RXD : MAX_82544_RXD;
+		opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
+			E1000_MAX_82544_RXD;
 
 		rx_ring->count = RxDescriptors[bd];
 		e1000_validate_option(&rx_ring->count, &opt);
@@ -446,13 +439,19 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		adapter->itr = InterruptThrottleRate[bd];
-		if(adapter->itr == 0) {
-			printk(KERN_INFO "%s turned off\n", opt.name);
-		} else if(adapter->itr == 1 || adapter->itr == -1) {
-			/* Dynamic mode */
+		switch(adapter->itr) {
+		case -1:
 			adapter->itr = 1;
-		} else {
+			break;
+		case 0:
+			printk(KERN_INFO "%s turned off\n", opt.name);
+			break;
+		case 1:
+			printk(KERN_INFO "%s set to dynamic mode\n", opt.name);
+			break;
+		default:
 			e1000_validate_option(&adapter->itr, &opt);
+			break;
 		}
 	}
 
@@ -490,9 +489,9 @@ e1000_check_fiber_options(struct e1000_a
 		printk(KERN_INFO "Duplex not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
-	if((AutoNeg[bd] != OPTION_UNSET)) {
-		printk(KERN_INFO "AutoNeg not valid for fiber adapters, "
-		       "parameter ignored\n");
+	if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
+		printk(KERN_INFO "AutoNeg other than Full/1000 is "
+		       "not valid for fiber adapters, parameter ignored\n");
 	}
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/forcedeth.c linux-2.4.26-pre6/drivers/net/forcedeth.c
--- linux-2.4.25/drivers/net/forcedeth.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/forcedeth.c	2004-03-25 00:17:22.000000000 +0000
@@ -0,0 +1,1623 @@
+/*
+ * forcedeth: Ethernet driver for NVIDIA nForce media access controllers.
+ *
+ * Note: This driver is a cleanroom reimplementation based on reverse
+ *      engineered documentation written by Carl-Daniel Hailfinger
+ *      and Andrew de Quincey. It's neither supported nor endorsed
+ *      by NVIDIA Corp. Use at your own risk.
+ *
+ * NVIDIA, nForce and other NVIDIA marks are trademarks or registered
+ * trademarks of NVIDIA Corporation in the United States and other
+ * countries.
+ *
+ * Copyright (C) 2003 Manfred Spraul
+ * Copyright (C) 2004 Andrew de Quincey (wol support)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ * 	0.01: 05 Oct 2003: First release that compiles without warnings.
+ * 	0.02: 05 Oct 2003: Fix bug for nv_drain_tx: do not try to free NULL skbs.
+ * 			   Check all PCI BARs for the register window.
+ * 			   udelay added to mii_rw.
+ * 	0.03: 06 Oct 2003: Initialize dev->irq.
+ * 	0.04: 07 Oct 2003: Initialize np->lock, reduce handled irqs, add printks.
+ * 	0.05: 09 Oct 2003: printk removed again, irq status print tx_timeout.
+ * 	0.06: 10 Oct 2003: MAC Address read updated, pff flag generation updated,
+ * 			   irq mask updated
+ * 	0.07: 14 Oct 2003: Further irq mask updates.
+ * 	0.08: 20 Oct 2003: rx_desc.Length initialization added, nv_alloc_rx refill
+ * 			   added into irq handler, NULL check for drain_ring.
+ * 	0.09: 20 Oct 2003: Basic link speed irq implementation. Only handle the
+ * 			   requested interrupt sources.
+ * 	0.10: 20 Oct 2003: First cleanup for release.
+ * 	0.11: 21 Oct 2003: hexdump for tx added, rx buffer sizes increased.
+ * 			   MAC Address init fix, set_multicast cleanup.
+ * 	0.12: 23 Oct 2003: Cleanups for release.
+ * 	0.13: 25 Oct 2003: Limit for concurrent tx packets increased to 10.
+ * 			   Set link speed correctly. start rx before starting
+ * 			   tx (nv_start_rx sets the link speed).
+ * 	0.14: 25 Oct 2003: Nic dependant irq mask.
+ * 	0.15: 08 Nov 2003: fix smp deadlock with set_multicast_list during
+ * 			   open.
+ * 	0.16: 15 Nov 2003: include file cleanup for ppc64, rx buffer size
+ * 			   increased to 1628 bytes.
+ * 	0.17: 16 Nov 2003: undo rx buffer size increase. Substract 1 from
+ * 			   the tx length.
+ * 	0.18: 17 Nov 2003: fix oops due to late initialization of dev_stats
+ * 	0.19: 29 Nov 2003: Handle RxNoBuf, detect & handle invalid mac
+ * 			   addresses, really stop rx if already running
+ * 			   in nv_start_rx, clean up a bit.
+ * 				(C) Carl-Daniel Hailfinger
+ * 	0.20: 07 Dec 2003: alloc fixes
+ * 	0.21: 12 Jan 2004: additional alloc fix, nic polling fix.
+ *	0.22: 19 Jan 2004: reprogram timer to a sane rate, avoid lockup
+ * 			   on close.
+ * 				(C) Carl-Daniel Hailfinger, Manfred Spraul
+ *	0.23: 26 Jan 2004: various small cleanups
+ *	0.24: 27 Feb 2004: make driver even less anonymous in backtraces
+ *	0.25: 09 Mar 2004: wol support
+ *
+ * Known bugs:
+ * We suspect that on some hardware no TX done interrupts are generated.
+ * This means recovery from netif_stop_queue only happens if the hw timer
+ * interrupt fires (100 times/second, configurable with NVREG_POLL_DEFAULT)
+ * and the timer is active in the IRQMask, or if a rx packet arrives by chance.
+ * If your hardware reliably generates tx done interrupts, then you can remove
+ * DEV_NEED_TIMERIRQ from the driver_data flags.
+ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
+ * superfluous timer interrupts from the nic.
+ */
+#define FORCEDETH_VERSION		"0.25"
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/mii.h>
+#include <linux/random.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#if 0
+#define dprintk			printk
+#else
+#define dprintk(x...)		do { } while (0)
+#endif
+
+
+/*
+ * Hardware access:
+ */
+
+#define DEV_NEED_LASTPACKET1	0x0001
+#define DEV_IRQMASK_1		0x0002
+#define DEV_IRQMASK_2		0x0004
+#define DEV_NEED_TIMERIRQ	0x0008
+
+enum {
+	NvRegIrqStatus = 0x000,
+#define NVREG_IRQSTAT_MIIEVENT	0x040
+#define NVREG_IRQSTAT_MASK		0x1ff
+	NvRegIrqMask = 0x004,
+#define NVREG_IRQ_RX			0x0002
+#define NVREG_IRQ_RX_NOBUF		0x0004
+#define NVREG_IRQ_TX_ERR		0x0008
+#define NVREG_IRQ_TX2			0x0010
+#define NVREG_IRQ_TIMER			0x0020
+#define NVREG_IRQ_LINK			0x0040
+#define NVREG_IRQ_TX1			0x0100
+#define NVREG_IRQMASK_WANTED_1		0x005f
+#define NVREG_IRQMASK_WANTED_2		0x0147
+#define NVREG_IRQ_UNKNOWN		(~(NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
+
+	NvRegUnknownSetupReg6 = 0x008,
+#define NVREG_UNKSETUP6_VAL		3
+
+/*
+ * NVREG_POLL_DEFAULT is the interval length of the timer source on the nic
+ * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
+ */
+	NvRegPollingInterval = 0x00c,
+#define NVREG_POLL_DEFAULT	970
+	NvRegMisc1 = 0x080,
+#define NVREG_MISC1_HD		0x02
+#define NVREG_MISC1_FORCE	0x3b0f3c
+
+	NvRegTransmitterControl = 0x084,
+#define NVREG_XMITCTL_START	0x01
+	NvRegTransmitterStatus = 0x088,
+#define NVREG_XMITSTAT_BUSY	0x01
+
+	NvRegPacketFilterFlags = 0x8c,
+#define NVREG_PFF_ALWAYS	0x7F0008
+#define NVREG_PFF_PROMISC	0x80
+#define NVREG_PFF_MYADDR	0x20
+
+	NvRegOffloadConfig = 0x90,
+#define NVREG_OFFLOAD_HOMEPHY	0x601
+#define NVREG_OFFLOAD_NORMAL	0x5ee
+	NvRegReceiverControl = 0x094,
+#define NVREG_RCVCTL_START	0x01
+	NvRegReceiverStatus = 0x98,
+#define NVREG_RCVSTAT_BUSY	0x01
+
+	NvRegRandomSeed = 0x9c,
+#define NVREG_RNDSEED_MASK	0x00ff
+#define NVREG_RNDSEED_FORCE	0x7f00
+
+	NvRegUnknownSetupReg1 = 0xA0,
+#define NVREG_UNKSETUP1_VAL	0x16070f
+	NvRegUnknownSetupReg2 = 0xA4,
+#define NVREG_UNKSETUP2_VAL	0x16
+	NvRegMacAddrA = 0xA8,
+	NvRegMacAddrB = 0xAC,
+	NvRegMulticastAddrA = 0xB0,
+#define NVREG_MCASTADDRA_FORCE	0x01
+	NvRegMulticastAddrB = 0xB4,
+	NvRegMulticastMaskA = 0xB8,
+	NvRegMulticastMaskB = 0xBC,
+
+	NvRegTxRingPhysAddr = 0x100,
+	NvRegRxRingPhysAddr = 0x104,
+	NvRegRingSizes = 0x108,
+#define NVREG_RINGSZ_TXSHIFT 0
+#define NVREG_RINGSZ_RXSHIFT 16
+	NvRegUnknownTransmitterReg = 0x10c,
+	NvRegLinkSpeed = 0x110,
+#define NVREG_LINKSPEED_FORCE 0x10000
+#define NVREG_LINKSPEED_10	10
+#define NVREG_LINKSPEED_100	100
+#define NVREG_LINKSPEED_1000	1000
+	NvRegUnknownSetupReg5 = 0x130,
+#define NVREG_UNKSETUP5_BIT31	(1<<31)
+	NvRegUnknownSetupReg3 = 0x134,
+#define NVREG_UNKSETUP3_VAL1	0x200010
+	NvRegTxRxControl = 0x144,
+#define NVREG_TXRXCTL_KICK	0x0001
+#define NVREG_TXRXCTL_BIT1	0x0002
+#define NVREG_TXRXCTL_BIT2	0x0004
+#define NVREG_TXRXCTL_IDLE	0x0008
+#define NVREG_TXRXCTL_RESET	0x0010
+	NvRegMIIStatus = 0x180,
+#define NVREG_MIISTAT_ERROR		0x0001
+#define NVREG_MIISTAT_LINKCHANGE	0x0008
+#define NVREG_MIISTAT_MASK		0x000f
+#define NVREG_MIISTAT_MASK2		0x000f
+	NvRegUnknownSetupReg4 = 0x184,
+#define NVREG_UNKSETUP4_VAL	8
+
+	NvRegAdapterControl = 0x188,
+#define NVREG_ADAPTCTL_START	0x02
+#define NVREG_ADAPTCTL_LINKUP	0x04
+#define NVREG_ADAPTCTL_PHYVALID	0x4000
+#define NVREG_ADAPTCTL_RUNNING	0x100000
+#define NVREG_ADAPTCTL_PHYSHIFT	24
+	NvRegMIISpeed = 0x18c,
+#define NVREG_MIISPEED_BIT8	(1<<8)
+#define NVREG_MIIDELAY	5
+	NvRegMIIControl = 0x190,
+#define NVREG_MIICTL_INUSE	0x10000
+#define NVREG_MIICTL_WRITE	0x08000
+#define NVREG_MIICTL_ADDRSHIFT	5
+	NvRegMIIData = 0x194,
+	NvRegWakeUpFlags = 0x200,
+#define NVREG_WAKEUPFLAGS_VAL		0x7770
+#define NVREG_WAKEUPFLAGS_BUSYSHIFT	24
+#define NVREG_WAKEUPFLAGS_ENABLESHIFT	16
+#define NVREG_WAKEUPFLAGS_D3SHIFT	12
+#define NVREG_WAKEUPFLAGS_D2SHIFT	8
+#define NVREG_WAKEUPFLAGS_D1SHIFT	4
+#define NVREG_WAKEUPFLAGS_D0SHIFT	0
+#define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT		0x01
+#define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT	0x02
+#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE	0x04
+#define NVREG_WAKEUPFLAGS_ENABLE	0x1111
+
+	NvRegPatternCRC = 0x204,
+	NvRegPatternMask = 0x208,
+	NvRegPowerCap = 0x268,
+#define NVREG_POWERCAP_D3SUPP	(1<<30)
+#define NVREG_POWERCAP_D2SUPP	(1<<26)
+#define NVREG_POWERCAP_D1SUPP	(1<<25)
+	NvRegPowerState = 0x26c,
+#define NVREG_POWERSTATE_POWEREDUP	0x8000
+#define NVREG_POWERSTATE_VALID		0x0100
+#define NVREG_POWERSTATE_MASK		0x0003
+#define NVREG_POWERSTATE_D0		0x0000
+#define NVREG_POWERSTATE_D1		0x0001
+#define NVREG_POWERSTATE_D2		0x0002
+#define NVREG_POWERSTATE_D3		0x0003
+};
+
+struct ring_desc {
+	u32 PacketBuffer;
+	u16 Length;
+	u16 Flags;
+};
+
+#define NV_TX_LASTPACKET	(1<<0)
+#define NV_TX_RETRYERROR	(1<<3)
+#define NV_TX_LASTPACKET1	(1<<8)
+#define NV_TX_DEFERRED		(1<<10)
+#define NV_TX_CARRIERLOST	(1<<11)
+#define NV_TX_LATECOLLISION	(1<<12)
+#define NV_TX_UNDERFLOW		(1<<13)
+#define NV_TX_ERROR		(1<<14)
+#define NV_TX_VALID		(1<<15)
+
+#define NV_RX_DESCRIPTORVALID	(1<<0)
+#define NV_RX_MISSEDFRAME	(1<<1)
+#define NV_RX_SUBSTRACT1	(1<<3)
+#define NV_RX_ERROR1		(1<<7)
+#define NV_RX_ERROR2		(1<<8)
+#define NV_RX_ERROR3		(1<<9)
+#define NV_RX_ERROR4		(1<<10)
+#define NV_RX_CRCERR		(1<<11)
+#define NV_RX_OVERFLOW		(1<<12)
+#define NV_RX_FRAMINGERR	(1<<13)
+#define NV_RX_ERROR		(1<<14)
+#define NV_RX_AVAIL		(1<<15)
+
+/* Miscelaneous hardware related defines: */
+#define NV_PCI_REGSZ		0x270
+
+/* various timeout delays: all in usec */
+#define NV_TXRX_RESET_DELAY	4
+#define NV_TXSTOP_DELAY1	10
+#define NV_TXSTOP_DELAY1MAX	500000
+#define NV_TXSTOP_DELAY2	100
+#define NV_RXSTOP_DELAY1	10
+#define NV_RXSTOP_DELAY1MAX	500000
+#define NV_RXSTOP_DELAY2	100
+#define NV_SETUP5_DELAY		5
+#define NV_SETUP5_DELAYMAX	50000
+#define NV_POWERUP_DELAY	5
+#define NV_POWERUP_DELAYMAX	5000
+#define NV_MIIBUSY_DELAY	50
+#define NV_MIIPHY_DELAY	10
+#define NV_MIIPHY_DELAYMAX	10000
+
+#define NV_WAKEUPPATTERNS	5
+#define NV_WAKEUPMASKENTRIES	4
+
+/* General driver defaults */
+#define NV_WATCHDOG_TIMEO	(5*HZ)
+#define DEFAULT_MTU		1500	/* also maximum supported, at least for now */
+
+#define RX_RING		128
+#define TX_RING		16
+/* limited to 1 packet until we understand NV_TX_LASTPACKET */
+#define TX_LIMIT_STOP	10
+#define TX_LIMIT_START	5
+
+/* rx/tx mac addr + type + vlan + align + slack*/
+#define RX_NIC_BUFSIZE		(DEFAULT_MTU + 64)
+/* even more slack */
+#define RX_ALLOC_BUFSIZE	(DEFAULT_MTU + 128)
+
+#define OOM_REFILL	(1+HZ/20)
+#define POLL_WAIT	(1+HZ/100)
+
+/*
+ * SMP locking:
+ * All hardware access under dev->priv->lock, except the performance
+ * critical parts:
+ * - rx is (pseudo-) lockless: it relies on the single-threading provided
+ * 	by the arch code for interrupts.
+ * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
+ *	needs dev->priv->lock :-(
+ * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
+ */
+
+/* in dev: base, irq */
+struct fe_priv {
+	spinlock_t lock;
+
+	/* General data:
+	 * Locking: spin_lock(&np->lock); */
+	struct net_device_stats stats;
+	int in_shutdown;
+	u32 linkspeed;
+	int duplex;
+	int phyaddr;
+	int wolenabled;
+
+	/* General data: RO fields */
+	dma_addr_t ring_addr;
+	struct pci_dev *pci_dev;
+	u32 orig_mac[2];
+	u32 irqmask;
+
+	/* rx specific fields.
+	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
+	 */
+	struct ring_desc *rx_ring;
+	unsigned int cur_rx, refill_rx;
+	struct sk_buff *rx_skbuff[RX_RING];
+	dma_addr_t rx_dma[RX_RING];
+	unsigned int rx_buf_sz;
+	struct timer_list oom_kick;
+	struct timer_list nic_poll;
+
+	/*
+	 * tx specific fields.
+	 */
+	struct ring_desc *tx_ring;
+	unsigned int next_tx, nic_tx;
+	struct sk_buff *tx_skbuff[TX_RING];
+	dma_addr_t tx_dma[TX_RING];
+	u16 tx_flags;
+};
+
+/*
+ * Maximum number of loops until we assume that a bit in the irq mask
+ * is stuck. Overridable with module param.
+ */
+static int max_interrupt_work = 5;
+
+static inline struct fe_priv *get_nvpriv(struct net_device *dev)
+{
+	return (struct fe_priv *) dev->priv;
+}
+
+static inline u8 *get_hwbase(struct net_device *dev)
+{
+	return (u8 *) dev->base_addr;
+}
+
+static inline void pci_push(u8 * base)
+{
+	/* force out pending posted writes */
+	readl(base);
+}
+
+static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
+				int delay, int delaymax, const char *msg)
+{
+	u8 *base = get_hwbase(dev);
+
+	pci_push(base);
+	do {
+		udelay(delay);
+		delaymax -= delay;
+		if (delaymax < 0) {
+			if (msg)
+				printk(msg);
+			return 1;
+		}
+	} while ((readl(base + offset) & mask) != target);
+	return 0;
+}
+
+#define MII_READ	(-1)
+/* mii_rw: read/write a register on the PHY.
+ *
+ * Caller must guarantee serialization
+ */
+static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
+{
+	u8 *base = get_hwbase(dev);
+	int was_running;
+	u32 reg;
+	int retval;
+
+	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+	was_running = 0;
+	reg = readl(base + NvRegAdapterControl);
+	if (reg & NVREG_ADAPTCTL_RUNNING) {
+		was_running = 1;
+		writel(reg & ~NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
+	}
+	reg = readl(base + NvRegMIIControl);
+	if (reg & NVREG_MIICTL_INUSE) {
+		writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl);
+		udelay(NV_MIIBUSY_DELAY);
+	}
+
+	reg = NVREG_MIICTL_INUSE | (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;
+	if (value != MII_READ) {
+		writel(value, base + NvRegMIIData);
+		reg |= NVREG_MIICTL_WRITE;
+	}
+	writel(reg, base + NvRegMIIControl);
+
+	if (reg_delay(dev, NvRegMIIControl, NVREG_MIICTL_INUSE, 0,
+			NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) {
+		dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d timed out.\n",
+				dev->name, miireg, addr);
+		retval = -1;
+	} else if (value != MII_READ) {
+		/* it was a write operation - fewer failures are detectable */
+		dprintk(KERN_DEBUG "%s: mii_rw wrote 0x%x to reg %d at PHY %d\n",
+				dev->name, value, miireg, addr);
+		retval = 0;
+	} else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) {
+		dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d failed.\n",
+				dev->name, miireg, addr);
+		retval = -1;
+	} else {
+		/* FIXME: why is that required? */
+		udelay(50);
+		retval = readl(base + NvRegMIIData);
+		dprintk(KERN_DEBUG "%s: mii_rw read from reg %d at PHY %d: 0x%x.\n",
+				dev->name, miireg, addr, retval);
+	}
+	if (was_running) {
+		reg = readl(base + NvRegAdapterControl);
+		writel(reg | NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
+	}
+	return retval;
+}
+
+static void nv_start_rx(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
+	/* Already running? Stop it. */
+	if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
+		writel(0, base + NvRegReceiverControl);
+		pci_push(base);
+	}
+	writel(np->linkspeed, base + NvRegLinkSpeed);
+	pci_push(base);
+	writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
+	pci_push(base);
+}
+
+static void nv_stop_rx(struct net_device *dev)
+{
+	u8 *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: nv_stop_rx\n", dev->name);
+	writel(0, base + NvRegReceiverControl);
+	reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
+		       NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
+		       KERN_INFO "nv_stop_rx: ReceiverStatus remained busy");
+
+	udelay(NV_RXSTOP_DELAY2);
+	writel(0, base + NvRegLinkSpeed);
+}
+
+static void nv_start_tx(struct net_device *dev)
+{
+	u8 *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: nv_start_tx\n", dev->name);
+	writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl);
+	pci_push(base);
+}
+
+static void nv_stop_tx(struct net_device *dev)
+{
+	u8 *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: nv_stop_tx\n", dev->name);
+	writel(0, base + NvRegTransmitterControl);
+	reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
+		       NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
+		       KERN_INFO "nv_stop_tx: TransmitterStatus remained busy");
+
+	udelay(NV_TXSTOP_DELAY2);
+	writel(0, base + NvRegUnknownTransmitterReg);
+}
+
+static void nv_txrx_reset(struct net_device *dev)
+{
+	u8 *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
+	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET, base + NvRegTxRxControl);
+	pci_push(base);
+	udelay(NV_TXRX_RESET_DELAY);
+	writel(NVREG_TXRXCTL_BIT2, base + NvRegTxRxControl);
+	pci_push(base);
+}
+
+/*
+ * nv_get_stats: dev->get_stats function
+ * Get latest stats value from the nic.
+ * Called with read_lock(&dev_base_lock) held for read -
+ * only synchronized against unregister_netdevice.
+ */
+static struct net_device_stats *nv_get_stats(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+
+	/* It seems that the nic always generates interrupts and doesn't
+	 * accumulate errors internally. Thus the current values in np->stats
+	 * are already up to date.
+	 */
+	return &np->stats;
+}
+
+static int nv_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+	u32 ethcmd;
+
+	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO:
+	{
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy(info.driver, "forcedeth");
+		strcpy(info.version, FORCEDETH_VERSION);
+		strcpy(info.bus_info, pci_name(np->pci_dev));
+		if (copy_to_user(useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GLINK:
+	{
+		struct ethtool_value edata = { ETHTOOL_GLINK };
+
+		edata.data = !!netif_carrier_ok(dev);
+
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GWOL:
+	{
+		struct ethtool_wolinfo wolinfo;
+		memset(&wolinfo, 0, sizeof(wolinfo));
+		wolinfo.supported = WAKE_MAGIC;
+
+		spin_lock_irq(&np->lock);
+		if (np->wolenabled)
+			wolinfo.wolopts = WAKE_MAGIC;
+		spin_unlock_irq(&np->lock);
+
+		if (copy_to_user(useraddr, &wolinfo, sizeof(wolinfo)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SWOL:
+	{
+		struct ethtool_wolinfo wolinfo;
+		if (copy_from_user(&wolinfo, useraddr, sizeof(wolinfo)))
+			return -EFAULT;
+
+		spin_lock_irq(&np->lock);
+		if (wolinfo.wolopts == 0) {
+			writel(0, base + NvRegWakeUpFlags);
+			np->wolenabled = 0;
+		}
+		if (wolinfo.wolopts & WAKE_MAGIC) {
+			writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
+			np->wolenabled = 1;
+		}
+		spin_unlock_irq(&np->lock);
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+/*
+ * nv_ioctl: dev->do_ioctl function
+ * Called with rtnl_lock held.
+ */
+static int nv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	switch(cmd) {
+	case SIOCETHTOOL:
+		return nv_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/*
+ * nv_alloc_rx: fill rx ring entries.
+ * Return 1 if the allocations for the skbs failed and the
+ * rx engine is without Available descriptors
+ */
+static int nv_alloc_rx(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	unsigned int refill_rx = np->refill_rx;
+
+	while (np->cur_rx != refill_rx) {
+		int nr = refill_rx % RX_RING;
+		struct sk_buff *skb;
+
+		if (np->rx_skbuff[nr] == NULL) {
+
+			skb = dev_alloc_skb(RX_ALLOC_BUFSIZE);
+			if (!skb)
+				break;
+
+			skb->dev = dev;
+			np->rx_skbuff[nr] = skb;
+		} else {
+			skb = np->rx_skbuff[nr];
+		}
+		np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len,
+						PCI_DMA_FROMDEVICE);
+		np->rx_ring[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
+		np->rx_ring[nr].Length = cpu_to_le16(RX_NIC_BUFSIZE);
+		wmb();
+		np->rx_ring[nr].Flags = cpu_to_le16(NV_RX_AVAIL);
+		dprintk(KERN_DEBUG "%s: nv_alloc_rx: Packet  %d marked as Available\n",
+					dev->name, refill_rx);
+		refill_rx++;
+	}
+	np->refill_rx = refill_rx;
+	if (np->cur_rx - refill_rx == RX_RING)
+		return 1;
+	return 0;
+}
+
+static void nv_do_rx_refill(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct fe_priv *np = get_nvpriv(dev);
+
+	disable_irq(dev->irq);
+	if (nv_alloc_rx(dev)) {
+		spin_lock(&np->lock);
+		if (!np->in_shutdown)
+			mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+		spin_unlock(&np->lock);
+	}
+	enable_irq(dev->irq);
+}
+
+static int nv_init_ring(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	int i;
+
+	np->next_tx = np->nic_tx = 0;
+	for (i = 0; i < TX_RING; i++) {
+		np->tx_ring[i].Flags = 0;
+	}
+
+	np->cur_rx = RX_RING;
+	np->refill_rx = 0;
+	for (i = 0; i < RX_RING; i++) {
+		np->rx_ring[i].Flags = 0;
+	}
+	return nv_alloc_rx(dev);
+}
+
+static void nv_drain_tx(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	int i;
+	for (i = 0; i < TX_RING; i++) {
+		np->tx_ring[i].Flags = 0;
+		if (np->tx_skbuff[i]) {
+			pci_unmap_single(np->pci_dev, np->tx_dma[i],
+						np->tx_skbuff[i]->len,
+						PCI_DMA_TODEVICE);
+			dev_kfree_skb(np->tx_skbuff[i]);
+			np->tx_skbuff[i] = NULL;
+			np->stats.tx_dropped++;
+		}
+	}
+}
+
+static void nv_drain_rx(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	int i;
+	for (i = 0; i < RX_RING; i++) {
+		np->rx_ring[i].Flags = 0;
+		wmb();
+		if (np->rx_skbuff[i]) {
+			pci_unmap_single(np->pci_dev, np->rx_dma[i],
+						np->rx_skbuff[i]->len,
+						PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(np->rx_skbuff[i]);
+			np->rx_skbuff[i] = NULL;
+		}
+	}
+}
+
+static void drain_ring(struct net_device *dev)
+{
+	nv_drain_tx(dev);
+	nv_drain_rx(dev);
+}
+
+/*
+ * nv_start_xmit: dev->hard_start_xmit function
+ * Called with dev->xmit_lock held.
+ */
+static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	int nr = np->next_tx % TX_RING;
+
+	np->tx_skbuff[nr] = skb;
+	np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
+					PCI_DMA_TODEVICE);
+
+	np->tx_ring[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+	np->tx_ring[nr].Length = cpu_to_le16(skb->len-1);
+
+	spin_lock_irq(&np->lock);
+	wmb();
+	np->tx_ring[nr].Flags = np->tx_flags;
+	dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
+				dev->name, np->next_tx);
+	{
+		int j;
+		for (j=0; j<64; j++) {
+			if ((j%16) == 0)
+				dprintk("\n%03x:", j);
+			dprintk(" %02x", ((unsigned char*)skb->data)[j]);
+		}
+		dprintk("\n");
+	}
+
+	np->next_tx++;
+
+	dev->trans_start = jiffies;
+	if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
+		netif_stop_queue(dev);
+	spin_unlock_irq(&np->lock);
+	writel(NVREG_TXRXCTL_KICK, get_hwbase(dev) + NvRegTxRxControl);
+	pci_push(get_hwbase(dev));
+	return 0;
+}
+
+/*
+ * nv_tx_done: check for completed packets, release the skbs.
+ *
+ * Caller must own np->lock.
+ */
+static void nv_tx_done(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+
+	while (np->nic_tx < np->next_tx) {
+		struct ring_desc *prd;
+		int i = np->nic_tx % TX_RING;
+
+		prd = &np->tx_ring[i];
+
+		dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, Flags 0x%x.\n",
+					dev->name, np->nic_tx, prd->Flags);
+		if (prd->Flags & cpu_to_le16(NV_TX_VALID))
+			break;
+		if (prd->Flags & cpu_to_le16(NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+						NV_TX_UNDERFLOW|NV_TX_ERROR)) {
+			if (prd->Flags & cpu_to_le16(NV_TX_UNDERFLOW))
+				np->stats.tx_fifo_errors++;
+			if (prd->Flags & cpu_to_le16(NV_TX_CARRIERLOST))
+				np->stats.tx_carrier_errors++;
+			np->stats.tx_errors++;
+		} else {
+			np->stats.tx_packets++;
+			np->stats.tx_bytes += np->tx_skbuff[i]->len;
+		}
+		pci_unmap_single(np->pci_dev, np->tx_dma[i],
+					np->tx_skbuff[i]->len,
+					PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(np->tx_skbuff[i]);
+		np->tx_skbuff[i] = NULL;
+		np->nic_tx++;
+	}
+	if (np->next_tx - np->nic_tx < TX_LIMIT_START)
+		netif_wake_queue(dev);
+}
+
+/*
+ * nv_tx_timeout: dev->tx_timeout function
+ * Called with dev->xmit_lock held.
+ */
+static void nv_tx_timeout(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: Got tx_timeout. irq: %08x\n", dev->name,
+			readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK);
+
+	spin_lock_irq(&np->lock);
+
+	/* 1) stop tx engine */
+	nv_stop_tx(dev);
+
+	/* 2) check that the packets were not sent already: */
+	nv_tx_done(dev);
+
+	/* 3) if there are dead entries: clear everything */
+	if (np->next_tx != np->nic_tx) {
+		printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name);
+		nv_drain_tx(dev);
+		np->next_tx = np->nic_tx = 0;
+		writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+		netif_wake_queue(dev);
+	}
+
+	/* 4) restart tx engine */
+	nv_start_tx(dev);
+	spin_unlock_irq(&np->lock);
+}
+
+static void nv_rx_process(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+
+	for (;;) {
+		struct ring_desc *prd;
+		struct sk_buff *skb;
+		int len;
+		int i;
+		if (np->cur_rx - np->refill_rx >= RX_RING)
+			break;	/* we scanned the whole ring - do not continue */
+
+		i = np->cur_rx % RX_RING;
+		prd = &np->rx_ring[i];
+		dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
+					dev->name, np->cur_rx, prd->Flags);
+
+		if (prd->Flags & cpu_to_le16(NV_RX_AVAIL))
+			break;	/* still owned by hardware, */
+
+		/*
+		 * the packet is for us - immediately tear down the pci mapping.
+		 * TODO: check if a prefetch of the first cacheline improves
+		 * the performance.
+		 */
+		pci_unmap_single(np->pci_dev, np->rx_dma[i],
+				np->rx_skbuff[i]->len,
+				PCI_DMA_FROMDEVICE);
+
+		{
+			int j;
+			dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",prd->Flags);
+			for (j=0; j<64; j++) {
+				if ((j%16) == 0)
+					dprintk("\n%03x:", j);
+				dprintk(" %02x", ((unsigned char*)np->rx_skbuff[i]->data)[j]);
+			}
+			dprintk("\n");
+		}
+		/* look at what we actually got: */
+		if (!(prd->Flags & cpu_to_le16(NV_RX_DESCRIPTORVALID)))
+			goto next_pkt;
+
+
+		len = le16_to_cpu(prd->Length);
+
+		if (prd->Flags & cpu_to_le16(NV_RX_MISSEDFRAME)) {
+			np->stats.rx_missed_errors++;
+			np->stats.rx_errors++;
+			goto next_pkt;
+		}
+		if (prd->Flags & cpu_to_le16(NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3|NV_RX_ERROR4)) {
+			np->stats.rx_errors++;
+			goto next_pkt;
+		}
+		if (prd->Flags & cpu_to_le16(NV_RX_CRCERR)) {
+			np->stats.rx_crc_errors++;
+			np->stats.rx_errors++;
+			goto next_pkt;
+		}
+		if (prd->Flags & cpu_to_le16(NV_RX_OVERFLOW)) {
+			np->stats.rx_over_errors++;
+			np->stats.rx_errors++;
+			goto next_pkt;
+		}
+		if (prd->Flags & cpu_to_le16(NV_RX_ERROR)) {
+			/* framing errors are soft errors, the rest is fatal. */
+			if (prd->Flags & cpu_to_le16(NV_RX_FRAMINGERR)) {
+				if (prd->Flags & cpu_to_le16(NV_RX_SUBSTRACT1)) {
+					len--;
+				}
+			} else {
+				np->stats.rx_errors++;
+				goto next_pkt;
+			}
+		}
+		/* got a valid packet - forward it to the network core */
+		skb = np->rx_skbuff[i];
+		np->rx_skbuff[i] = NULL;
+
+		skb_put(skb, len);
+		skb->protocol = eth_type_trans(skb, dev);
+		dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n",
+					dev->name, np->cur_rx, len, skb->protocol);
+		netif_rx(skb);
+		dev->last_rx = jiffies;
+		np->stats.rx_packets++;
+		np->stats.rx_bytes += len;
+next_pkt:
+		np->cur_rx++;
+	}
+}
+
+/*
+ * nv_change_mtu: dev->change_mtu function
+ * Called with dev_base_lock held for read.
+ */
+static int nv_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if (new_mtu > DEFAULT_MTU)
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+/*
+ * nv_set_multicast: dev->set_multicast function
+ * Called with dev->xmit_lock held.
+ */
+static void nv_set_multicast(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+	u32 addr[2];
+	u32 mask[2];
+	u32 pff;
+
+	memset(addr, 0, sizeof(addr));
+	memset(mask, 0, sizeof(mask));
+
+	if (dev->flags & IFF_PROMISC) {
+		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
+		pff = NVREG_PFF_PROMISC;
+	} else {
+		pff = NVREG_PFF_MYADDR;
+
+		if (dev->flags & IFF_ALLMULTI || dev->mc_list) {
+			u32 alwaysOff[2];
+			u32 alwaysOn[2];
+
+			alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0xffffffff;
+			if (dev->flags & IFF_ALLMULTI) {
+				alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
+			} else {
+				struct dev_mc_list *walk;
+
+				walk = dev->mc_list;
+				while (walk != NULL) {
+					u32 a, b;
+					a = le32_to_cpu(*(u32 *) walk->dmi_addr);
+					b = le16_to_cpu(*(u16 *) (&walk->dmi_addr[4]));
+					alwaysOn[0] &= a;
+					alwaysOff[0] &= ~a;
+					alwaysOn[1] &= b;
+					alwaysOff[1] &= ~b;
+					walk = walk->next;
+				}
+			}
+			addr[0] = alwaysOn[0];
+			addr[1] = alwaysOn[1];
+			mask[0] = alwaysOn[0] | alwaysOff[0];
+			mask[1] = alwaysOn[1] | alwaysOff[1];
+		}
+	}
+	addr[0] |= NVREG_MCASTADDRA_FORCE;
+	pff |= NVREG_PFF_ALWAYS;
+	spin_lock_irq(&np->lock);
+	nv_stop_rx(dev);
+	writel(addr[0], base + NvRegMulticastAddrA);
+	writel(addr[1], base + NvRegMulticastAddrB);
+	writel(mask[0], base + NvRegMulticastMaskA);
+	writel(mask[1], base + NvRegMulticastMaskB);
+	writel(pff, base + NvRegPacketFilterFlags);
+	nv_start_rx(dev);
+	spin_unlock_irq(&np->lock);
+}
+
+static int nv_update_linkspeed(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	int adv, lpa, newls, newdup;
+
+	adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+	lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
+	dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
+				dev->name, adv, lpa);
+
+	/* FIXME: handle parallel detection properly, handle gigabit ethernet */
+	lpa = lpa & adv;
+	if (lpa  & LPA_100FULL) {
+		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
+		newdup = 1;
+	} else if (lpa & LPA_100HALF) {
+		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
+		newdup = 0;
+	} else if (lpa & LPA_10FULL) {
+		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+		newdup = 1;
+	} else if (lpa & LPA_10HALF) {
+		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+		newdup = 0;
+	} else {
+		dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa);
+		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+		newdup = 0;
+	}
+	if (np->duplex != newdup || np->linkspeed != newls) {
+		np->duplex = newdup;
+		np->linkspeed = newls;
+		return 1;
+	}
+	return 0;
+}
+
+static void nv_link_irq(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+	u32 miistat;
+	int miival;
+
+	miistat = readl(base + NvRegMIIStatus);
+	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+	printk(KERN_DEBUG "%s: link change notification, status 0x%x.\n", dev->name, miistat);
+
+	miival = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+	if (miival & BMSR_ANEGCOMPLETE) {
+		nv_update_linkspeed(dev);
+
+		if (netif_carrier_ok(dev)) {
+			nv_stop_rx(dev);
+		} else {
+			netif_carrier_on(dev);
+			printk(KERN_INFO "%s: link up.\n", dev->name);
+		}
+		writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD),
+					base + NvRegMisc1);
+		nv_start_rx(dev);
+	} else {
+		if (netif_carrier_ok(dev)) {
+			netif_carrier_off(dev);
+			printk(KERN_INFO "%s: link down.\n", dev->name);
+			nv_stop_rx(dev);
+		}
+		writel(np->linkspeed, base + NvRegLinkSpeed);
+		pci_push(base);
+	}
+}
+
+static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+	u32 events;
+	int i;
+
+	dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name);
+
+	for (i=0; ; i++) {
+		events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
+		writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+		pci_push(base);
+		dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
+		if (!(events & np->irqmask))
+			break;
+
+		if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX2|NVREG_IRQ_TX_ERR)) {
+			spin_lock(&np->lock);
+			nv_tx_done(dev);
+			spin_unlock(&np->lock);
+		}
+
+		if (events & (NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)) {
+			nv_rx_process(dev);
+			if (nv_alloc_rx(dev)) {
+				spin_lock(&np->lock);
+				if (!np->in_shutdown)
+					mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+				spin_unlock(&np->lock);
+			}
+		}
+
+		if (events & NVREG_IRQ_LINK) {
+			spin_lock(&np->lock);
+			nv_link_irq(dev);
+			spin_unlock(&np->lock);
+		}
+		if (events & (NVREG_IRQ_TX_ERR)) {
+			dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
+						dev->name, events);
+		}
+		if (events & (NVREG_IRQ_UNKNOWN)) {
+			printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
+						dev->name, events);
+ 		}
+		if (i > max_interrupt_work) {
+			spin_lock(&np->lock);
+			/* disable interrupts on the nic */
+			writel(0, base + NvRegIrqMask);
+			pci_push(base);
+
+			if (!np->in_shutdown)
+				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i);
+			spin_unlock(&np->lock);
+			break;
+		}
+
+	}
+	dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name);
+
+	return IRQ_RETVAL(i);
+}
+
+static void nv_do_nic_poll(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+
+	disable_irq(dev->irq);
+	/* FIXME: Do we need synchronize_irq(dev->irq) here? */
+	/*
+	 * reenable interrupts on the nic, we have to do this before calling
+	 * nv_nic_irq because that may decide to do otherwise
+	 */
+	writel(np->irqmask, base + NvRegIrqMask);
+	pci_push(base);
+	nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
+	enable_irq(dev->irq);
+}
+
+static int nv_open(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+	int ret, oom, i;
+
+	dprintk(KERN_DEBUG "nv_open: begin\n");
+
+	/* 1) erase previous misconfiguration */
+	/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
+	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
+	writel(0, base + NvRegMulticastAddrB);
+	writel(0, base + NvRegMulticastMaskA);
+	writel(0, base + NvRegMulticastMaskB);
+	writel(0, base + NvRegPacketFilterFlags);
+	writel(0, base + NvRegAdapterControl);
+	writel(0, base + NvRegLinkSpeed);
+	writel(0, base + NvRegUnknownTransmitterReg);
+	nv_txrx_reset(dev);
+	writel(0, base + NvRegUnknownSetupReg6);
+
+	/* 2) initialize descriptor rings */
+	np->in_shutdown = 0;
+	oom = nv_init_ring(dev);
+
+	/* 3) set mac address */
+	{
+		u32 mac[2];
+
+		mac[0] = (dev->dev_addr[0] <<  0) + (dev->dev_addr[1] <<  8) +
+				(dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
+		mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
+
+		writel(mac[0], base + NvRegMacAddrA);
+		writel(mac[1], base + NvRegMacAddrB);
+	}
+
+	/* 4) continue setup */
+	np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+	np->duplex = 0;
+	writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
+	writel(0, base + NvRegTxRxControl);
+	pci_push(base);
+	writel(NVREG_TXRXCTL_BIT1, base + NvRegTxRxControl);
+	reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
+			NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
+			KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
+	writel(0, base + NvRegUnknownSetupReg4);
+
+	/* 5) Find a suitable PHY */
+	writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);
+	for (i = 1; i < 32; i++) {
+		int id1, id2;
+
+		spin_lock_irq(&np->lock);
+		id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ);
+		spin_unlock_irq(&np->lock);
+		if (id1 < 0 || id1 == 0xffff)
+			continue;
+		spin_lock_irq(&np->lock);
+		id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ);
+		spin_unlock_irq(&np->lock);
+		if (id2 < 0 || id2 == 0xffff)
+			continue;
+		dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",
+				dev->name, id1, id2, i);
+		np->phyaddr = i;
+
+		spin_lock_irq(&np->lock);
+		nv_update_linkspeed(dev);
+		spin_unlock_irq(&np->lock);
+
+		break;
+	}
+	if (i == 32) {
+		printk(KERN_INFO "%s: open: failing due to lack of suitable PHY.\n",
+				dev->name);
+		ret = -EINVAL;
+		goto out_drain;
+	}
+
+	/* 6) continue setup */
+	writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD),
+				base + NvRegMisc1);
+	writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
+	writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
+	writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
+
+	writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
+	get_random_bytes(&i, sizeof(i));
+	writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
+	writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
+	writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
+	writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);
+	writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
+	writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID,
+			base + NvRegAdapterControl);
+	writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
+	writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
+
+	/* 7) start packet processing */
+	writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
+	writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+	writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+			base + NvRegRingSizes);
+
+	i = readl(base + NvRegPowerState);
+	if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)
+		writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState);
+
+	pci_push(base);
+	udelay(10);
+	writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
+	writel(NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
+
+
+	writel(0, base + NvRegIrqMask);
+	pci_push(base);
+	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+	pci_push(base);
+	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
+	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+	pci_push(base);
+
+	ret = request_irq(dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev);
+	if (ret)
+		goto out_drain;
+
+	writel(np->irqmask, base + NvRegIrqMask);
+
+	spin_lock_irq(&np->lock);
+	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
+	writel(0, base + NvRegMulticastAddrB);
+	writel(0, base + NvRegMulticastMaskA);
+	writel(0, base + NvRegMulticastMaskB);
+	writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
+	nv_start_rx(dev);
+	nv_start_tx(dev);
+	netif_start_queue(dev);
+	if (oom)
+		mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+	if (mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ) & BMSR_ANEGCOMPLETE) {
+		netif_carrier_on(dev);
+	} else {
+		printk("%s: no link during initialization.\n", dev->name);
+		netif_carrier_off(dev);
+	}
+
+	spin_unlock_irq(&np->lock);
+
+	return 0;
+out_drain:
+	drain_ring(dev);
+	return ret;
+}
+
+static int nv_close(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base;
+
+	spin_lock_irq(&np->lock);
+	np->in_shutdown = 1;
+	spin_unlock_irq(&np->lock);
+	synchronize_irq();
+
+	del_timer_sync(&np->oom_kick);
+	del_timer_sync(&np->nic_poll);
+
+	netif_stop_queue(dev);
+	spin_lock_irq(&np->lock);
+	nv_stop_tx(dev);
+	nv_stop_rx(dev);
+	base = get_hwbase(dev);
+
+	/* disable interrupts on the nic or we will lock up */
+	writel(0, base + NvRegIrqMask);
+	pci_push(base);
+	dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
+
+	spin_unlock_irq(&np->lock);
+
+	free_irq(dev->irq, dev);
+
+	drain_ring(dev);
+
+	if (np->wolenabled)
+		nv_start_rx(dev);
+
+	/* FIXME: power down nic */
+
+	return 0;
+}
+
+static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+{
+	struct net_device *dev;
+	struct fe_priv *np;
+	unsigned long addr;
+	u8 *base;
+	int err, i;
+
+	dev = alloc_etherdev(sizeof(struct fe_priv));
+	err = -ENOMEM;
+	if (!dev)
+		goto out;
+
+	np = get_nvpriv(dev);
+	np->pci_dev = pci_dev;
+	spin_lock_init(&np->lock);
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pci_dev->dev);
+
+	init_timer(&np->oom_kick);
+	np->oom_kick.data = (unsigned long) dev;
+	np->oom_kick.function = &nv_do_rx_refill;	/* timer handler */
+	init_timer(&np->nic_poll);
+	np->nic_poll.data = (unsigned long) dev;
+	np->nic_poll.function = &nv_do_nic_poll;	/* timer handler */
+
+	err = pci_enable_device(pci_dev);
+	if (err) {
+		printk(KERN_INFO "forcedeth: pci_enable_dev failed (%d) for device %s\n",
+				err, pci_name(pci_dev));
+		goto out_free;
+	}
+
+	pci_set_master(pci_dev);
+
+	err = pci_request_regions(pci_dev, dev->name);
+	if (err < 0)
+		goto out_disable;
+
+	err = -EINVAL;
+	addr = 0;
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		dprintk(KERN_DEBUG "%s: resource %d start %p len %ld flags 0x%08lx.\n",
+				pci_name(pci_dev), i, (void*)pci_resource_start(pci_dev, i),
+				pci_resource_len(pci_dev, i),
+				pci_resource_flags(pci_dev, i));
+		if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM &&
+				pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) {
+			addr = pci_resource_start(pci_dev, i);
+			break;
+		}
+	}
+	if (i == DEVICE_COUNT_RESOURCE) {
+		printk(KERN_INFO "forcedeth: Couldn't find register window for device %s.\n",
+					pci_name(pci_dev));
+		goto out_relreg;
+	}
+
+	err = -ENOMEM;
+	dev->base_addr = (unsigned long) ioremap(addr, NV_PCI_REGSZ);
+	if (!dev->base_addr)
+		goto out_relreg;
+	dev->irq = pci_dev->irq;
+	np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
+						&np->ring_addr);
+	if (!np->rx_ring)
+		goto out_unmap;
+	np->tx_ring = &np->rx_ring[RX_RING];
+
+	dev->open = nv_open;
+	dev->stop = nv_close;
+	dev->hard_start_xmit = nv_start_xmit;
+	dev->get_stats = nv_get_stats;
+	dev->change_mtu = nv_change_mtu;
+	dev->set_multicast_list = nv_set_multicast;
+	dev->do_ioctl = nv_ioctl;
+	dev->tx_timeout = nv_tx_timeout;
+	dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
+
+	pci_set_drvdata(pci_dev, dev);
+
+	/* read the mac address */
+	base = get_hwbase(dev);
+	np->orig_mac[0] = readl(base + NvRegMacAddrA);
+	np->orig_mac[1] = readl(base + NvRegMacAddrB);
+
+	dev->dev_addr[0] = (np->orig_mac[1] >>  8) & 0xff;
+	dev->dev_addr[1] = (np->orig_mac[1] >>  0) & 0xff;
+	dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
+	dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
+	dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
+	dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		/*
+		 * Bad mac address. At least one bios sets the mac address
+		 * to 01:23:45:67:89:ab
+		 */
+		printk(KERN_ERR "%s: Invalid Mac address detected: %02x:%02x:%02x:%02x:%02x:%02x\n",
+			pci_name(pci_dev),
+			dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+			dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+		printk(KERN_ERR "Please complain to your hardware vendor. Switching to a random MAC.\n");
+		dev->dev_addr[0] = 0x00;
+		dev->dev_addr[1] = 0x00;
+		dev->dev_addr[2] = 0x6c;
+		get_random_bytes(&dev->dev_addr[3], 3);
+	}
+
+	dprintk(KERN_DEBUG "%s: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", pci_name(pci_dev),
+			dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+			dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+	/* disable WOL */
+	writel(0, base + NvRegWakeUpFlags);
+	np->wolenabled = 0;
+
+	np->tx_flags = cpu_to_le16(NV_TX_LASTPACKET|NV_TX_LASTPACKET1|NV_TX_VALID);
+	if (id->driver_data & DEV_NEED_LASTPACKET1)
+		np->tx_flags |= cpu_to_le16(NV_TX_LASTPACKET1);
+	if (id->driver_data & DEV_IRQMASK_1)
+		np->irqmask = NVREG_IRQMASK_WANTED_1;
+	if (id->driver_data & DEV_IRQMASK_2)
+		np->irqmask = NVREG_IRQMASK_WANTED_2;
+	if (id->driver_data & DEV_NEED_TIMERIRQ)
+		np->irqmask |= NVREG_IRQ_TIMER;
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);
+		goto out_freering;
+	}
+	printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n",
+			dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+			pci_name(pci_dev));
+
+	return 0;
+
+out_freering:
+	pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
+				np->rx_ring, np->ring_addr);
+	pci_set_drvdata(pci_dev, NULL);
+out_unmap:
+	iounmap(get_hwbase(dev));
+out_relreg:
+	pci_release_regions(pci_dev);
+out_disable:
+	pci_disable_device(pci_dev);
+out_free:
+	free_netdev(dev);
+out:
+	return err;
+}
+
+static void __devexit nv_remove(struct pci_dev *pci_dev)
+{
+	struct net_device *dev = pci_get_drvdata(pci_dev);
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
+
+	unregister_netdev(dev);
+
+	/* special op: write back the misordered MAC address - otherwise
+	 * the next nv_probe would see a wrong address.
+	 */
+	writel(np->orig_mac[0], base + NvRegMacAddrA);
+	writel(np->orig_mac[1], base + NvRegMacAddrB);
+
+	/* free all structures */
+	pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring, np->ring_addr);
+	iounmap(get_hwbase(dev));
+	pci_release_regions(pci_dev);
+	pci_disable_device(pci_dev);
+	free_netdev(dev);
+	pci_set_drvdata(pci_dev, NULL);
+}
+
+static struct pci_device_id pci_tbl[] = {
+	{	/* nForce Ethernet Controller */
+		.vendor = PCI_VENDOR_ID_NVIDIA,
+		.device = 0x1C3,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ,
+	},
+	{	/* nForce2 Ethernet Controller */
+		.vendor = PCI_VENDOR_ID_NVIDIA,
+		.device = 0x0066,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
+	},
+	{	/* nForce3 Ethernet Controller */
+		.vendor = PCI_VENDOR_ID_NVIDIA,
+		.device = 0x00D6,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
+	},
+	{0,},
+};
+
+static struct pci_driver driver = {
+	.name = "forcedeth",
+	.id_table = pci_tbl,
+	.probe = nv_probe,
+	.remove = __devexit_p(nv_remove),
+};
+
+
+static int __init init_nic(void)
+{
+	printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);
+	return pci_module_init(&driver);
+}
+
+static void __exit exit_nic(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt");
+ 
+MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
+MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+module_init(init_nic);
+module_exit(exit_nic);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/ibm_emac/ibm_emac.h linux-2.4.26-pre6/drivers/net/ibm_emac/ibm_emac.h
--- linux-2.4.25/drivers/net/ibm_emac/ibm_emac.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/ibm_emac/ibm_emac.h	2004-03-25 00:20:07.000000000 +0000
@@ -58,8 +58,8 @@ typedef struct emac_regs {
 	u32 em0gaht2;
 	u32 em0gaht3;
 	u32 em0gaht4;
-	u32 em0lsal;
 	u32 em0lsah;
+	u32 em0lsal;
 	u32 em0ipgvr;
 	u32 em0stacr;
 	u32 em0trtr;
@@ -99,8 +99,8 @@ typedef struct emac_regs {
 #define EMAC_M1_TX_FIFO_1K              0x00010000
 #define EMAC_M1_TX_MWSW                 0x00001000	/* 0 wait for status */
 #define EMAC_M1_JUMBO_ENABLE            0x00000800	/* Upt to 9Kr status */
-#define EMAC_M1_OPB_CLK_66              0x00000010	/* 66Mhz */
-#define EMAC_M1_OPB_CLK_83              0x00000008	/* 83hz */
+#define EMAC_M1_OPB_CLK_66              0x00000008	/* 66Mhz */
+#define EMAC_M1_OPB_CLK_83              0x00000010	/* 83Mhz */
 #define EMAC_M1_OPB_CLK_100             0x00000018	/* 100Mhz */
 #define EMAC_M1_OPB_CLK_100P            0x00000020	/* 100Mhz+ */
 #else /* CONFIG_IBM_EMAC4 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/ibm_emac/ibm_ocp_enet.c linux-2.4.26-pre6/drivers/net/ibm_emac/ibm_ocp_enet.c
--- linux-2.4.25/drivers/net/ibm_emac/ibm_ocp_enet.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/ibm_emac/ibm_ocp_enet.c	2004-03-25 00:17:19.000000000 +0000
@@ -743,19 +743,19 @@ __emac_set_multicast_list(struct net_dev
 {
 	struct ocp_enet_private *fep = dev->priv;
 	volatile emac_t *emacp = fep->emacp;
-
+	u32 rmr = in_be32(&emacp->em0rmr);
+	
+	/* First clear all special bits, they can be set later */
+	rmr &= ~(EMAC_RMR_PME | EMAC_RMR_PMME | EMAC_RMR_MAE);
+	
 	if (dev->flags & IFF_PROMISC) {
-
-		/* If promiscuous mode is set then we do not need anything else */
-		out_be32(&emacp->em0rmr, EMAC_RMR_PME);
+		rmr |= EMAC_RMR_PME;
 
 	} else if (dev->flags & IFF_ALLMULTI || 32 < dev->mc_count) {
-
 		/* Must be setting up to use multicast.  Now check for promiscuous
 		 * multicast
 		 */
-		out_be32(&emacp->em0rmr,
-			 EMAC_RMR_IAE | EMAC_RMR_BAE | EMAC_RMR_PMME);
+		rmr |= EMAC_RMR_PMME;
 	} else if (dev->flags & IFF_MULTICAST && 0 < dev->mc_count) {
 
 		unsigned short em0gaht[4] = { 0, 0, 0, 0 };
@@ -777,16 +777,10 @@ __emac_set_multicast_list(struct net_dev
 		emacp->em0gaht4 = em0gaht[3];
 
 		/* Turn on multicast addressing */
-		out_be32(&emacp->em0rmr,
-			 EMAC_RMR_IAE | EMAC_RMR_BAE | EMAC_RMR_MAE);
-
-	} else {
-		/* If multicast mode is not set then we are 
-		 * turning it off at this point 
-		 */
-		out_be32(&emacp->em0rmr, EMAC_RMR_IAE | EMAC_RMR_BAE);
-
+		rmr |= EMAC_RMR_MAE;
 	}
+	
+	out_be32(&emacp->em0rmr, rmr);
 }
 
 static void
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/ibm_emac/ibm_ocp_mal.c linux-2.4.26-pre6/drivers/net/ibm_emac/ibm_ocp_mal.c
--- linux-2.4.25/drivers/net/ibm_emac/ibm_ocp_mal.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/ibm_emac/ibm_ocp_mal.c	2004-03-25 00:19:19.000000000 +0000
@@ -62,7 +62,7 @@ mal_register_commac(struct ibm_ocp_mal *
 	/* Don't let multiple commacs claim the same channel */
 	if ( (mal->tx_chan_mask & commac->tx_chan_mask) ||
 	     (mal->rx_chan_mask & commac->rx_chan_mask) ) {
-	     	write_unlock(&mal_list_lock);
+	     	write_unlock_irqrestore(&mal_list_lock, flags);
 		return -EBUSY;
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/natsemi.c linux-2.4.26-pre6/drivers/net/natsemi.c
--- linux-2.4.25/drivers/net/natsemi.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/natsemi.c	2004-03-25 00:17:18.000000000 +0000
@@ -175,6 +175,8 @@
 #define DRV_VERSION	"1.07+LK1.0.17"
 #define DRV_RELDATE	"Sep 27, 2002"
 
+#define RX_OFFSET	2
+
 /* Updated to recommendations in pci-skeleton v2.03. */
 
 /* The user-configurable values.
@@ -1466,13 +1468,14 @@ static void refill_rx(struct net_device 
 		struct sk_buff *skb;
 		int entry = np->dirty_rx % RX_RING_SIZE;
 		if (np->rx_skbuff[entry] == NULL) {
-			skb = dev_alloc_skb(np->rx_buf_sz);
+			unsigned int buflen = np->rx_buf_sz + RX_OFFSET;
+			skb = dev_alloc_skb(buflen);
 			np->rx_skbuff[entry] = skb;
 			if (skb == NULL)
 				break; /* Better luck next round. */
 			skb->dev = dev; /* Mark as being used by this device. */
 			np->rx_dma[entry] = pci_map_single(np->pci_dev,
-				skb->data, skb->len, PCI_DMA_FROMDEVICE);
+				skb->tail, buflen, PCI_DMA_FROMDEVICE);
 			np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
 		}
 		np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz);
@@ -1542,6 +1545,7 @@ static void drain_tx(struct net_device *
 static void drain_ring(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
+	unsigned int buflen = np->rx_buf_sz + RX_OFFSET;
 	int i;
 
 	/* Free all the skbuffs in the Rx queue. */
@@ -1550,7 +1554,7 @@ static void drain_ring(struct net_device
 		np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
 		if (np->rx_skbuff[i]) {
 			pci_unmap_single(np->pci_dev,
-				np->rx_dma[i], np->rx_skbuff[i]->len,
+				np->rx_dma[i], buflen,
 				PCI_DMA_FROMDEVICE);
 			dev_kfree_skb(np->rx_skbuff[i]);
 		}
@@ -1746,6 +1750,7 @@ static void netdev_rx(struct net_device 
 	int entry = np->cur_rx % RX_RING_SIZE;
 	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
 	s32 desc_status = le32_to_cpu(np->rx_head_desc->cmd_status);
+	unsigned int buflen = np->rx_buf_sz + RX_OFFSET;
 
 	/* If the driver owns the next entry it's a new packet. Send it up. */
 	while (desc_status < 0) { /* e.g. & DescOwn */
@@ -1784,13 +1789,13 @@ static void netdev_rx(struct net_device 
 			/* Check if the packet is long enough to accept
 			 * without copying to a minimally-sized skbuff. */
 			if (pkt_len < rx_copybreak
-			    && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+			    && (skb = dev_alloc_skb(pkt_len + RX_OFFSET)) != NULL) {
 				skb->dev = dev;
 				/* 16 byte align the IP header */
-				skb_reserve(skb, 2);
+				skb_reserve(skb, RX_OFFSET);
 				pci_dma_sync_single(np->pci_dev,
 					np->rx_dma[entry],
-					np->rx_skbuff[entry]->len,
+					buflen,
 					PCI_DMA_FROMDEVICE);
 #if HAS_IP_COPYSUM
 				eth_copy_and_sum(skb,
@@ -1802,8 +1807,7 @@ static void netdev_rx(struct net_device 
 #endif
 			} else {
 				pci_unmap_single(np->pci_dev, np->rx_dma[entry],
-					np->rx_skbuff[entry]->len,
-					PCI_DMA_FROMDEVICE);
+					buflen, PCI_DMA_FROMDEVICE);
 				skb_put(skb = np->rx_skbuff[entry], pkt_len);
 				np->rx_skbuff[entry] = NULL;
 			}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/ne2k-pci.c linux-2.4.26-pre6/drivers/net/ne2k-pci.c
--- linux-2.4.25/drivers/net/ne2k-pci.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/ne2k-pci.c	2004-03-25 00:18:11.000000000 +0000
@@ -116,6 +116,7 @@ enum ne2k_pci_chipsets {
 	CH_Winbond_W89C940F,
 	CH_Holtek_HT80232,
 	CH_Holtek_HT80229,
+	CH_Winbond_89C940_8c4a,
 };
 
 
@@ -133,6 +134,7 @@ static struct {
 	{"Winbond W89C940F", 0},
 	{"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
 	{"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
+	{"Winbond W89C940(misprogrammed)", 0},
 	{0,}
 };
 
@@ -148,6 +150,7 @@ static struct pci_device_id ne2k_pci_tbl
 	{ 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F },
 	{ 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 },
 	{ 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 },
+	{ 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/pcnet32.c linux-2.4.26-pre6/drivers/net/pcnet32.c
--- linux-2.4.25/drivers/net/pcnet32.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/pcnet32.c	2004-03-25 00:18:36.000000000 +0000
@@ -22,8 +22,8 @@
  *************************************************************************/
 
 #define DRV_NAME	"pcnet32"
-#define DRV_VERSION	"1.27a"
-#define DRV_RELDATE	"10.02.2002"
+#define DRV_VERSION	"1.28"
+#define DRV_RELDATE	"02.20.2004"
 #define PFX		DRV_NAME ": "
 
 static const char *version =
@@ -61,12 +61,18 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELD
 static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = {
     { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
     { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+    /*
+     * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
+     * the incorrect vendor id.
+     */
+    { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID,
+	    PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0 },
     { 0, }
 };
 
 MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl);
 
-int cards_found __initdata;
+static int cards_found __devinitdata;
 
 /* 
  * VLB I/O addresses 
@@ -76,7 +82,7 @@ static unsigned int pcnet32_portlist[] _
 
 
 
-static int pcnet32_debug = 1;
+static int pcnet32_debug = 0;
 static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
 static int pcnet32vlb;	 /* check for VLB cards ? */
 
@@ -120,6 +126,11 @@ static unsigned char options_mapping[] =
     PCNET32_PORT_ASEL			   /* 15 not supported	  */
 };
 
+static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
+    "Loopback test  (offline)"
+};
+#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
+
 #define MAX_UNITS 8	/* More are supported, limit only on options */
 static int options[MAX_UNITS];
 static int full_duplex[MAX_UNITS];
@@ -212,6 +223,13 @@ static int full_duplex[MAX_UNITS];
  *	   fix pci probe not increment cards_found
  *	   FD auto negotiate error workaround for xSeries250
  *	   clean up and using new mii module
+ * v1.28   20 Feb 2004 Don Fry <brazilnut@us.ibm.com>
+ *	   Jon Mason <jonmason@us.ibm.com>, Chinmay Albal <albal@in.ibm.com>
+ *	   Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl.
+ *	   Fixes bogus 'Bus master arbitration failure', pci_[un]map_single
+ *	   length errors, and transmit hangs.  Cleans up after errors in open.
+ *	   Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
+ *	   Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
  */
 
 
@@ -319,6 +337,7 @@ struct pcnet32_private {
 	mii:1;				/* mii port available */
     struct net_device	*next;
     struct mii_if_info mii_if;
+    u32			msg_enable;	/* debug message level */
 };
 
 static void pcnet32_probe_vlbus(void);
@@ -336,6 +355,10 @@ static void pcnet32_set_multicast_list(s
 static int  pcnet32_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *dev, int phy_id, int reg_num);
 static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val);
+static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
+static void pcnet32_ethtool_test(struct net_device *dev,
+	struct ethtool_test *eth_test, u64 *data);
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -389,13 +412,13 @@ static int pcnet32_wio_check (unsigned l
 }
 
 static struct pcnet32_access pcnet32_wio = {
-    read_csr:	pcnet32_wio_read_csr,
-    write_csr:	pcnet32_wio_write_csr,
-    read_bcr:	pcnet32_wio_read_bcr,
-    write_bcr:	pcnet32_wio_write_bcr,
-    read_rap:	pcnet32_wio_read_rap,
-    write_rap:	pcnet32_wio_write_rap,
-    reset:	pcnet32_wio_reset
+    .read_csr	= pcnet32_wio_read_csr,
+    .write_csr	= pcnet32_wio_write_csr,
+    .read_bcr	= pcnet32_wio_read_bcr,
+    .write_bcr	= pcnet32_wio_write_bcr,
+    .read_rap	= pcnet32_wio_read_rap,
+    .write_rap	= pcnet32_wio_write_rap,
+    .reset	= pcnet32_wio_reset
 };
 
 static u16 pcnet32_dwio_read_csr (unsigned long addr, int index)
@@ -444,17 +467,283 @@ static int pcnet32_dwio_check (unsigned 
 }
 
 static struct pcnet32_access pcnet32_dwio = {
-    read_csr:	pcnet32_dwio_read_csr,
-    write_csr:	pcnet32_dwio_write_csr,
-    read_bcr:	pcnet32_dwio_read_bcr,
-    write_bcr:	pcnet32_dwio_write_bcr,
-    read_rap:	pcnet32_dwio_read_rap,
-    write_rap:	pcnet32_dwio_write_rap,
-    reset:	pcnet32_dwio_reset
+    .read_csr	= pcnet32_dwio_read_csr,
+    .write_csr	= pcnet32_dwio_write_csr,
+    .read_bcr	= pcnet32_dwio_read_bcr,
+    .write_bcr	= pcnet32_dwio_write_bcr,
+    .read_rap	= pcnet32_dwio_read_rap,
+    .write_rap	= pcnet32_dwio_write_rap,
+    .reset	= pcnet32_dwio_reset
 };
 
 
 
+static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r = -EOPNOTSUPP;
+
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	mii_ethtool_gset(&lp->mii_if, cmd);
+	spin_unlock_irqrestore(&lp->lock, flags);
+	r = 0;
+    }
+    return r;
+}
+
+static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r = -EOPNOTSUPP;
+
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	r = mii_ethtool_sset(&lp->mii_if, cmd);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
+    return r;
+}
+
+static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct pcnet32_private *lp = dev->priv;
+  
+	strcpy (info->driver, DRV_NAME);
+	strcpy (info->version, DRV_VERSION);
+	if (lp->pci_dev)
+		strcpy (info->bus_info, pci_name(lp->pci_dev));
+	else
+		sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
+}
+
+static u32 pcnet32_get_link(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r;
+
+    spin_lock_irqsave(&lp->lock, flags);
+    if (lp->mii) {
+	r = mii_link_ok(&lp->mii_if);
+    } else {
+	ulong ioaddr = dev->base_addr;	/* card base I/O address */
+	r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    return r;
+}
+
+static u32 pcnet32_get_msglevel(struct net_device *dev)
+{
+	struct pcnet32_private *lp = dev->priv;
+	return lp->msg_enable;
+}
+  
+static void pcnet32_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct pcnet32_private *lp = dev->priv;
+	lp->msg_enable = value;
+}
+  
+static int pcnet32_nway_reset(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r = -EOPNOTSUPP;
+
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	r = mii_nway_restart(&lp->mii_if);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
+    return r;
+}
+
+static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+	struct pcnet32_private *lp = dev->priv;
+
+	ering->tx_max_pending = TX_RING_SIZE - 1;
+	ering->tx_pending = lp->cur_tx - lp->dirty_tx;
+	ering->rx_max_pending = RX_RING_SIZE - 1;
+	ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+}
+
+static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+    memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test));
+}
+
+static int pcnet32_self_test_count(struct net_device *dev)
+{
+    return PCNET32_TEST_LEN;
+}
+
+static void pcnet32_ethtool_test(struct net_device *dev,
+	struct ethtool_test *test, u64 *data)
+{
+    struct pcnet32_private *lp = dev->priv;
+    int rc;
+
+    if (test->flags == ETH_TEST_FL_OFFLINE) {
+	rc = pcnet32_loopback_test(dev, data);
+	if (rc) {
+	    if (netif_msg_hw(lp))
+		printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name);
+	    test->flags |= ETH_TEST_FL_FAILED;
+	} else if (netif_msg_hw(lp))
+	    printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name);
+    } else
+	printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).",	    dev->name);
+} /* end pcnet32_ethtool_test */
+
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
+{
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;	/* access to registers */
+    ulong ioaddr = dev->base_addr;	/* card base I/O address */
+    struct sk_buff *skb;		/* sk buff */
+    int x, y, i;			/* counters */
+    int numbuffs = 4;			/* number of TX/RX buffers and descs */
+    u16 status = 0x8300;		/* TX ring status */
+    int rc;				/* return code */
+    int size;				/* size of packets */
+    unsigned char *packet;		/* source packet data */
+    static int data_len = 60;		/* length of source packets */
+    unsigned long flags;
+
+    *data1 = 1;			/* status of test, default to fail */
+    rc = 1;			/* default to fail */
+
+    spin_lock_irqsave(&lp->lock, flags);
+    lp->a.write_csr(ioaddr, 0, 0x7904);
+
+    netif_stop_queue(dev);
+
+    /* purge & init rings but don't actually restart */
+    pcnet32_restart(dev, 0x0000);
+
+    lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */
+
+    x = a->read_bcr(ioaddr, 32);	/* set internal loopback in BSR32 */
+    x = x | 0x00000002;
+    a->write_bcr(ioaddr, 32, x);
+
+    /* Initialize Transmit buffers. */
+    size = data_len + 15;
+    for (x=0; x<numbuffs; x++) {
+	if (!(skb = dev_alloc_skb(size))) {
+	    if (netif_msg_hw(lp))
+		printk(KERN_DEBUG "%s: Cannot allocate skb at line: %d!\n",
+		    dev->name, __LINE__);
+	    goto clean_up;
+	} else {
+	    packet = skb->data;
+	    skb_put(skb, size);		/* create space for data */
+	    lp->tx_skbuff[x] = skb;
+	    lp->tx_ring[x].length = le16_to_cpu(-skb->len);
+	    lp->tx_ring[x].misc = 0x00000000;
+
+	    /* put DA and SA into the skb */
+	    for (i=0; i<12; i++)
+		*packet++ = 0xff;
+	    /* type */
+	    *packet++ = 0x08;
+	    *packet++ = 0x06;
+	    /* packet number */
+	    *packet++ = x;
+	    /* fill packet with data */
+	    for (y=0; y<data_len; y++)
+		*packet++ = y;
+
+	    lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data,
+		    skb->len, PCI_DMA_TODEVICE);
+	    lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]);
+	    wmb(); /* Make sure owner changes after all others are visible */
+	    lp->tx_ring[x].status = le16_to_cpu(status);
+	}
+    }
+
+    lp->a.write_csr(ioaddr, 0, 0x0002);	/* Set STRT bit */
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    mdelay(50);				/* wait a bit */
+
+    spin_lock_irqsave(&lp->lock, flags);
+    lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */
+
+    if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
+	printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
+
+	for (x=0; x<numbuffs; x++) {
+	    printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);
+	    skb=lp->rx_skbuff[x];
+	    for (i=0; i<size; i++) {
+		printk("%02x ", *(skb->data+i));
+	    }
+	    printk("\n");
+	}
+    }
+
+    x = 0;
+    rc = 0;
+    while (x<numbuffs && !rc) {
+	skb = lp->rx_skbuff[x];
+	packet = lp->tx_skbuff[x]->data;
+	for (i=0; i<size; i++) {
+	    if (*(skb->data+i) != packet[i]) {
+		if (netif_msg_hw(lp))
+		    printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n",
+			    dev->name, i, *(skb->data+i), packet[i]);
+		rc = 1;
+		break;
+	    }
+	}
+	x++;
+    }
+    if (!rc) {
+	*data1 = 0;
+    }
+
+clean_up:
+    x = a->read_csr(ioaddr, 15) & 0xFFFF;
+    a->write_csr(ioaddr, 15, (x & ~0x0044));	/* reset bits 6 and 2 */
+
+    x = a->read_bcr(ioaddr, 32);		/* reset internal loopback */
+    x = x & ~0x00000002;
+    a->write_bcr(ioaddr, 32, x);
+
+    pcnet32_restart(dev, 0x0042);		/* resume normal operation */
+
+    netif_wake_queue(dev);
+
+    /* Clear interrupts, and set interrupt enable. */
+    lp->a.write_csr(ioaddr, 0, 0x7940);
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    return(rc);
+} /* end pcnet32_loopback_test  */
+
+static struct ethtool_ops pcnet32_ethtool_ops = {
+    .get_settings	= pcnet32_get_settings,
+    .set_settings	= pcnet32_set_settings,
+    .get_drvinfo	= pcnet32_get_drvinfo,
+    .get_msglevel	= pcnet32_get_msglevel,
+    .set_msglevel	= pcnet32_set_msglevel,
+    .nway_reset		= pcnet32_nway_reset,
+    .get_link		= pcnet32_get_link,
+    .get_ringparam	= pcnet32_get_ringparam,
+    .get_tx_csum	= ethtool_op_get_tx_csum,
+    .get_sg		= ethtool_op_get_sg,
+    .get_strings	= pcnet32_get_strings,
+    .self_test_count	= pcnet32_self_test_count,
+    .self_test		= pcnet32_ethtool_test,
+};
+
 /* only probes for non-PCI devices, the rest are handled by 
  * pci_register_driver via pcnet32_probe_pci */
 
@@ -535,10 +824,12 @@ pcnet32_probe1(unsigned long ioaddr, uns
     }
 
     chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16);
-    if (pcnet32_debug > 2)
+    if (pcnet32_debug & NETIF_MSG_PROBE)
 	printk(KERN_INFO "  PCnet chip version is %#x.\n", chip_version);
-    if ((chip_version & 0xfff) != 0x003)
+    if ((chip_version & 0xfff) != 0x003) {
+	printk(KERN_INFO PFX "Unsupported chip version.\n");
 	return -ENODEV;
+    }
     
     /* initialize variables */
     fdx = mii = fset = dxsuflo = ltint = 0;
@@ -589,7 +880,7 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	media &= ~3;
 	media |= 1;
 #endif
-	if (pcnet32_debug > 2)
+	if (pcnet32_debug & NETIF_MSG_PROBE)
 	    printk(KERN_DEBUG PFX "media reset to %#x.\n",  media);
 	a->write_bcr(ioaddr, 49, media);
 	break;
@@ -619,8 +910,10 @@ pcnet32_probe1(unsigned long ioaddr, uns
     }
     
     dev = alloc_etherdev(0);
-    if(!dev)
+    if (!dev) {
+	printk(KERN_ERR PFX "Memory allocation failed.\n");
 	return -ENOMEM;
+    }
 
     printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
 
@@ -693,6 +986,7 @@ pcnet32_probe1(unsigned long ioaddr, uns
     
     /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
     if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {
+	printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
 	release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	return -ENOMEM;
     }
@@ -707,9 +1001,12 @@ pcnet32_probe1(unsigned long ioaddr, uns
     lp->name = chipname;
     lp->shared_irq = shared;
     lp->mii_if.full_duplex = fdx;
+    lp->mii_if.phy_id_mask = 0x1f;
+    lp->mii_if.reg_num_mask = 0x1f;
     lp->dxsuflo = dxsuflo;
     lp->ltint = ltint;
     lp->mii = mii;
+    lp->msg_enable = pcnet32_debug;
     if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping)))
 	lp->options = PCNET32_PORT_ASEL;
     else
@@ -778,6 +1075,9 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	}
     }
 
+    /* Set the mii phy_id so that we can query the link state */
+    if (lp->mii)
+	lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f;
     
     /* The PCNET32-specific entries in the device structure. */
     dev->open = &pcnet32_open;
@@ -786,11 +1086,16 @@ pcnet32_probe1(unsigned long ioaddr, uns
     dev->get_stats = &pcnet32_get_stats;
     dev->set_multicast_list = &pcnet32_set_multicast_list;
     dev->do_ioctl = &pcnet32_ioctl;
+    dev->ethtool_ops = &pcnet32_ethtool_ops;
     dev->tx_timeout = pcnet32_tx_timeout;
     dev->watchdog_timeo = (5*HZ);
 
-    lp->next = pcnet32_dev;
-    pcnet32_dev = dev;
+    if (pdev) {
+	pci_set_drvdata(pdev, dev);
+    } else {
+	lp->next = pcnet32_dev;
+	pcnet32_dev = dev;
+    }
 
     /* Fill in the generic fields of the device structure. */
     register_netdev(dev);
@@ -807,6 +1112,7 @@ pcnet32_open(struct net_device *dev)
     unsigned long ioaddr = dev->base_addr;
     u16 val;
     int i;
+    int rc;
 
     if (dev->irq == 0 ||
 	request_irq(dev->irq, &pcnet32_interrupt,
@@ -815,8 +1121,10 @@ pcnet32_open(struct net_device *dev)
     }
 
     /* Check for a valid station address */
-    if( !is_valid_ether_addr(dev->dev_addr) )
-	return -EINVAL;
+    if (!is_valid_ether_addr(dev->dev_addr)) {
+	rc = -EINVAL;
+	goto err_free_irq;
+    }
 
     /* Reset the PCNET32 */
     lp->a.reset (ioaddr);
@@ -824,7 +1132,7 @@ pcnet32_open(struct net_device *dev)
     /* switch pcnet32 to 32bit mode */
     lp->a.write_bcr (ioaddr, 20, 2);
 
-    if (pcnet32_debug > 1)
+    if (netif_msg_ifup(lp))
 	printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
 	       dev->name, dev->irq,
 	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
@@ -890,8 +1198,10 @@ pcnet32_open(struct net_device *dev)
     lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
     lp->init_block.filter[0] = 0x00000000;
     lp->init_block.filter[1] = 0x00000000;
-    if (pcnet32_init_ring(dev))
-	return -ENOMEM;
+    if (pcnet32_init_ring(dev)) {
+	rc = -ENOMEM;
+	goto err_free_ring;
+    }
     
     /* Re-initialize the PCNET32, and start it when done. */
     lp->a.write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) &0xffff);
@@ -912,7 +1222,7 @@ pcnet32_open(struct net_device *dev)
      */
     lp->a.write_csr (ioaddr, 0, 0x0042);
 
-    if (pcnet32_debug > 2)
+    if (netif_msg_ifup(lp))
 	printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n",
 	       dev->name, i, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)),
 	       lp->a.read_csr(ioaddr, 0));
@@ -921,6 +1231,28 @@ pcnet32_open(struct net_device *dev)
     MOD_INC_USE_COUNT;
     
     return 0;	/* Always succeed */
+
+err_free_ring:
+    /* free any allocated skbuffs */
+    for (i = 0; i < RX_RING_SIZE; i++) {
+	lp->rx_ring[i].status = 0;			    
+	if (lp->rx_skbuff[i]) {
+            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+		    PCI_DMA_FROMDEVICE);
+	    dev_kfree_skb(lp->rx_skbuff[i]);
+        }
+	lp->rx_skbuff[i] = NULL;
+        lp->rx_dma_addr[i] = 0;
+    }
+    /*
+     * Switch back to 16bit mode to avoid problems with dumb 
+     * DOS packet driver after a warm reboot
+     */
+    lp->a.write_bcr (ioaddr, 20, 4);
+
+err_free_irq:
+    free_irq(dev->irq, dev);
+    return rc;
 }
 
 /*
@@ -976,9 +1308,10 @@ pcnet32_init_ring(struct net_device *dev
 	}
 
 	if (lp->rx_dma_addr[i] == 0) 
-		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, rx_skbuff->len, PCI_DMA_FROMDEVICE);
+		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
+			rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 	lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]);
-	lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
 	lp->rx_ring[i].status = le16_to_cpu(0x8000);
     }
     /* The Tx buffer address is filled in as needed, but we do need to clear
@@ -988,6 +1321,7 @@ pcnet32_init_ring(struct net_device *dev
 	lp->tx_ring[i].status = 0;
         lp->tx_dma_addr[i] = 0;
     }
+    wmb(); /* Make sure all changes are visible */
 
     lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
     for (i = 0; i < 6; i++)
@@ -1031,7 +1365,7 @@ pcnet32_tx_timeout (struct net_device *d
 	       dev->name, lp->a.read_csr(ioaddr, 0));
 	lp->a.write_csr (ioaddr, 0, 0x0004);
 	lp->stats.tx_errors++;
-	if (pcnet32_debug > 2) {
+	if (netif_msg_tx_err(lp)) {
 	    int i;
 	    printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
 	       lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
@@ -1049,7 +1383,7 @@ pcnet32_tx_timeout (struct net_device *d
 	pcnet32_restart(dev, 0x0042);
 
 	dev->trans_start = jiffies;
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 
 	spin_unlock_irqrestore(&lp->lock, flags);
 }
@@ -1064,7 +1398,7 @@ pcnet32_start_xmit(struct sk_buff *skb, 
     int entry;
     unsigned long flags;
 
-    if (pcnet32_debug > 3) {
+    if (netif_msg_tx_queued(lp)) {
 	printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
 	       dev->name, lp->a.read_csr(ioaddr, 0));
     }
@@ -1075,12 +1409,14 @@ pcnet32_start_xmit(struct sk_buff *skb, 
      * interrupt when that option is available to us.
      */
     status = 0x8300;
+    entry = (lp->cur_tx - lp->dirty_tx) & TX_RING_MOD_MASK;
     if ((lp->ltint) &&
-	((lp->cur_tx - lp->dirty_tx == TX_RING_SIZE/2) ||
-	 (lp->cur_tx - lp->dirty_tx >= TX_RING_SIZE-2)))
+	((entry == TX_RING_SIZE/3) ||
+	 (entry == (TX_RING_SIZE*2)/3) ||
+	 (entry >= TX_RING_SIZE-2)))
     {
 	/* Enable Successful-TxDone interrupt if we have
-	 * 1/2 of, or nearly all of, our ring buffer Tx'd
+	 * 1/3, 2/3 or nearly all of, our ring buffer Tx'd
 	 * but not yet cleaned up.  Thus, most of the time,
 	 * we will not enable Successful-TxDone interrupts.
 	 */
@@ -1092,7 +1428,7 @@ pcnet32_start_xmit(struct sk_buff *skb, 
     /* Mask to ring buffer boundary. */
     entry = lp->cur_tx & TX_RING_MOD_MASK;
   
-    /* Caution: the write order is important here, set the base address
+    /* Caution: the write order is important here, set the status
        with the "ownership" bits last. */
 
     lp->tx_ring[entry].length = le16_to_cpu(-skb->len);
@@ -1113,9 +1449,7 @@ pcnet32_start_xmit(struct sk_buff *skb, 
 
     dev->trans_start = jiffies;
 
-    if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
-	netif_start_queue(dev);
-    else {
+    if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
 	lp->tx_full = 1;
 	netif_stop_queue(dev);
     }
@@ -1147,12 +1481,15 @@ pcnet32_interrupt(int irq, void *dev_id,
     
     rap = lp->a.read_rap(ioaddr);
     while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
+	if (csr0 == 0xffff) {
+	    break;			/* PCMCIA remove happened */
+	}
 	/* Acknowledge all of the current interrupt sources ASAP. */
 	lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f);
 
 	must_restart = 0;
 
-	if (pcnet32_debug > 5)
+	if (netif_msg_intr(lp))
 	    printk(KERN_DEBUG "%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",
 		   dev->name, csr0, lp->a.read_csr (ioaddr, 0));
 
@@ -1161,8 +1498,9 @@ pcnet32_interrupt(int irq, void *dev_id,
 
 	if (csr0 & 0x0200) {		/* Tx-done interrupt */
 	    unsigned int dirty_tx = lp->dirty_tx;
+	    int delta;
 
-	    while (dirty_tx < lp->cur_tx) {
+	    while (dirty_tx != lp->cur_tx) {
 		int entry = dirty_tx & TX_RING_MOD_MASK;
 		int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
 			
@@ -1216,15 +1554,17 @@ pcnet32_interrupt(int irq, void *dev_id,
 		dirty_tx++;
 	    }
 
-	    if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+	    delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
+	    if (delta >= TX_RING_SIZE) {
 		printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
 			dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
 		dirty_tx += TX_RING_SIZE;
+		delta -= TX_RING_SIZE;
 	    }
 
 	    if (lp->tx_full &&
 		netif_queue_stopped(dev) &&
-		dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+		delta < TX_RING_SIZE - 2) {
 		/* The ring is no longer full, clear tbusy. */
 		lp->tx_full = 0;
 		netif_wake_queue (dev);
@@ -1264,7 +1604,7 @@ pcnet32_interrupt(int irq, void *dev_id,
     lp->a.write_csr (ioaddr, 0, 0x7940);
     lp->a.write_rap (ioaddr,rap);
     
-    if (pcnet32_debug > 4)
+    if (netif_msg_intr(lp))
 	printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
 
@@ -1312,13 +1652,14 @@ pcnet32_rx(struct net_device *dev)
 		    if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) {
 			skb_reserve (newskb, 2);
 			skb = lp->rx_skbuff[entry];
-			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], skb->len, PCI_DMA_FROMDEVICE);
+			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry],
+				PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 			skb_put (skb, pkt_len);
 			lp->rx_skbuff[entry] = newskb;
 			newskb->dev = dev;
                         lp->rx_dma_addr[entry] = 
 				pci_map_single(lp->pci_dev, newskb->tail,
-					newskb->len, PCI_DMA_FROMDEVICE);
+					PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 			lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]);
 			rx_in_place = 1;
 		    } else
@@ -1347,7 +1688,7 @@ pcnet32_rx(struct net_device *dev)
 		    skb_put(skb,pkt_len);	/* Make room */
 		    pci_dma_sync_single(lp->pci_dev,
 		                        lp->rx_dma_addr[entry],
-		                        PKT_BUF_SZ,
+		                        PKT_BUF_SZ-2,
 		                        PCI_DMA_FROMDEVICE);
 		    eth_copy_and_sum(skb,
 				     (unsigned char *)(lp->rx_skbuff[entry]->tail),
@@ -1364,7 +1705,8 @@ pcnet32_rx(struct net_device *dev)
 	 * The docs say that the buffer length isn't touched, but Andrew Boyd
 	 * of QNX reports that some revs of the 79C965 clear it.
 	 */
-	lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
+	wmb(); /* Make sure owner changes after all others are visible */
 	lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
 	entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
     }
@@ -1383,7 +1725,7 @@ pcnet32_close(struct net_device *dev)
 
     lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
 
-    if (pcnet32_debug > 1)
+    if (netif_msg_ifdown(lp))
 	printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
 
@@ -1402,7 +1744,8 @@ pcnet32_close(struct net_device *dev)
     for (i = 0; i < RX_RING_SIZE; i++) {
 	lp->rx_ring[i].status = 0;			    
 	if (lp->rx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], lp->rx_skbuff[i]->len, PCI_DMA_FROMDEVICE);
+            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+		    PCI_DMA_FROMDEVICE);
 	    dev_kfree_skb(lp->rx_skbuff[i]);
         }
 	lp->rx_skbuff[i] = NULL;
@@ -1472,7 +1815,9 @@ static void pcnet32_load_multicast (stru
 	
 	crc = ether_crc_le(6, addrs);
 	crc = crc >> 26;
-	mcast_table [crc >> 4] |= cpu_to_le16(1 << (crc & 0xf));
+	mcast_table [crc >> 4] = le16_to_cpu(
+		le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf))
+	);
     }
     return;
 }
@@ -1537,136 +1882,49 @@ static void mdio_write(struct net_device
 	lp->a.write_bcr(ioaddr, 33, phyaddr);
 }
 
-static int pcnet32_ethtool_ioctl (struct net_device *dev, void *useraddr)
+static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct pcnet32_private *lp = dev->priv;
-	u32 ethcmd;
-	int phyaddr = 0;
-	int phy_id = 0;
-	unsigned long ioaddr = dev->base_addr;
-
-	if (lp->mii) {
-		phyaddr = lp->a.read_bcr (ioaddr, 33);
-		phy_id = (phyaddr >> 5) & 0x1f;
-		lp->mii_if.phy_id = phy_id;
-	}
-
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-		strcpy (info.driver, DRV_NAME);
-		strcpy (info.version, DRV_VERSION);
-		if (lp->pci_dev)
-			strcpy (info.bus_info, lp->pci_dev->slot_name);
-		else
-			sprintf(info.bus_info, "VLB 0x%lx", dev->base_addr);
-		if (copy_to_user (useraddr, &info, sizeof (info)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&lp->lock);
-		mii_ethtool_gset(&lp->mii_if, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int r;
-		struct ethtool_cmd ecmd;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&lp->lock);
-		r = mii_ethtool_sset(&lp->mii_if, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		return r;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		return mii_nway_restart(&lp->mii_if);
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		edata.data = mii_link_ok(&lp->mii_if);
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
+    struct pcnet32_private *lp = dev->priv;	 
+    struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
+    int rc;
+    unsigned long flags;
 
-	/* get message-level */
-	case ETHTOOL_GMSGLVL: {
-		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-		edata.data = pcnet32_debug;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL: {
-		struct ethtool_value edata;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		pcnet32_debug = edata.data;
-		return 0;
-	}
-	default:
-		break;
-	}
+    /* SIOC[GS]MIIxxx ioctls */
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    } else {
+	rc = -EOPNOTSUPP;
+    }
 
-	return -EOPNOTSUPP;
+    return rc;
 }
 
-static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
 {
-    unsigned long ioaddr = dev->base_addr;
-    struct pcnet32_private *lp = dev->priv;	 
-    struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
-    int phyaddr = lp->a.read_bcr (ioaddr, 33);
+    struct net_device *dev = pci_get_drvdata(pdev);
 
-    if (cmd == SIOCETHTOOL)
-	return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data);
+    if (dev) {
+	struct pcnet32_private *lp = dev->priv;
 
-    if (lp->mii) {
-	switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	    data->phy_id = (phyaddr >> 5) & 0x1f;
-	    /* Fall Through */
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
-	    data->val_out = lp->a.read_bcr (ioaddr, 34);
-	    lp->a.write_bcr (ioaddr, 33, phyaddr);
-	    return 0;
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-	    if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
-	    lp->a.write_bcr (ioaddr, 34, data->val_in);
-	    lp->a.write_bcr (ioaddr, 33, phyaddr);
-	    return 0;
-	default:
-	    return -EOPNOTSUPP;
-	}
+	unregister_netdev(dev);
+	release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
+	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
+	free_netdev(dev);
+	pci_set_drvdata(pdev, NULL);
     }
-    return -EOPNOTSUPP;
 }
 
 static struct pci_driver pcnet32_driver = {
-    name:	DRV_NAME,
-    probe:	pcnet32_probe_pci,
-    id_table:	pcnet32_pci_tbl,
+    .name	= DRV_NAME,
+    .probe	= pcnet32_probe_pci,
+    .remove	= __devexit_p(pcnet32_remove_one),
+    .id_table	= pcnet32_pci_tbl,
 };
 
 MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, DRV_NAME " debug level (0-6)");
+MODULE_PARM_DESC(debug, DRV_NAME " debug level");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt");  
 MODULE_PARM(rx_copybreak, "i");
@@ -1687,19 +1945,21 @@ MODULE_LICENSE("GPL");
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 static int tx_start_pt = -1;
+static int pcnet32_have_pci;
 
 static int __init pcnet32_init_module(void)
 {
     printk(KERN_INFO "%s", version);
 
-    if (debug > 0)
-	pcnet32_debug = debug;
+    if (debug >= 0 && debug < (sizeof(int) - 1))
+	pcnet32_debug = 1 << debug;
 
     if ((tx_start_pt >= 0) && (tx_start_pt <= 3))
 	tx_start = tx_start_pt;
 
     /* find the PCI devices */
-    pci_module_init(&pcnet32_driver);
+    if (!pci_module_init(&pcnet32_driver))
+	pcnet32_have_pci = 1;
 
     /* should we find any remaining VLbus devices ? */
     if (pcnet32vlb)
@@ -1708,7 +1968,7 @@ static int __init pcnet32_init_module(vo
     if (cards_found)
 	printk(KERN_INFO PFX "%d cards_found.\n", cards_found);
     
-    return cards_found ? 0 : -ENODEV;
+    return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
 }
 
 static void __exit pcnet32_cleanup_module(void)
@@ -1721,12 +1981,12 @@ static void __exit pcnet32_cleanup_modul
 	next_dev = lp->next;
 	unregister_netdev(pcnet32_dev);
 	release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
-	if (lp->pci_dev)
-	    pci_unregister_driver(&pcnet32_driver);
 	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
-	kfree(pcnet32_dev);
+	free_netdev(pcnet32_dev);
 	pcnet32_dev = next_dev;
     }
+    if (pcnet32_have_pci)
+	pci_unregister_driver(&pcnet32_driver);
 }
 
 module_init(pcnet32_init_module);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/r8169.c linux-2.4.26-pre6/drivers/net/r8169.c
--- linux-2.4.25/drivers/net/r8169.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/r8169.c	2004-03-25 00:18:10.000000000 +0000
@@ -874,7 +874,6 @@ rtl8169_tx_interrupt(struct net_device *
 		     void *ioaddr)
 {
 	unsigned long dirty_tx, tx_left = 0;
-	int entry = tp->cur_tx % NUM_TX_DESC;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -884,14 +883,18 @@ rtl8169_tx_interrupt(struct net_device *
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
+		int entry = dirty_tx % NUM_TX_DESC;
+
 		if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
-			dev_kfree_skb_irq(tp->
-					  Tx_skbuff[dirty_tx % NUM_TX_DESC]);
-			tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL;
+			struct sk_buff *skb = tp->Tx_skbuff[entry];
+
+			tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
+					      skb->len : ETH_ZLEN;
 			tp->stats.tx_packets++;
+			dev_kfree_skb_irq(skb);
+			tp->Tx_skbuff[entry] = NULL;
 			dirty_tx++;
 			tx_left--;
-			entry++;
 		}
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sis900.c linux-2.4.26-pre6/drivers/net/sis900.c
--- linux-2.4.25/drivers/net/sis900.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sis900.c	2004-03-25 00:19:28.000000000 +0000
@@ -2095,7 +2095,7 @@ static void set_rx_mode(struct net_devic
 		     i++, mclist = mclist->next) {
 			unsigned int bit_nr =
 				sis900_mcast_bitnr(mclist->dmi_addr, revision);
-			mc_filter[bit_nr >> 4] |= (1 << bit_nr);
+			mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
 		}
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/lm80.h linux-2.4.26-pre6/drivers/net/sk98lin/h/lm80.h
--- linux-2.4.25/drivers/net/sk98lin/h/lm80.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/lm80.h	2004-03-25 00:21:49.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	lm80.h	
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.6 $
- * Date:	$Date: 2003/05/13 17:26:52 $
  * Purpose:	Contains all defines for the LM80 Chip
  *		(National Semiconductor).
  *
@@ -23,32 +21,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *	$Log: lm80.h,v $
- *	Revision 1.6  2003/05/13 17:26:52  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.5  2003/03/31 07:15:18  mkarl
- *	Corrected Copyright.
- *	Editorial changes.
- *	
- *	Revision 1.4  2002/04/25 11:04:10  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.3  1999/11/22 13:41:19  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.2  1999/03/12 13:26:51  malthoff
- *	remove __STDC__.
- *	
- *	Revision 1.1  1998/06/19 09:28:31  malthoff
- *	created.
- *	
- *
- ******************************************************************************/
-
 #ifndef __INC_LM80_H
 #define __INC_LM80_H
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skaddr.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skaddr.h
--- linux-2.4.25/drivers/net/sk98lin/h/skaddr.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skaddr.h	2004-03-25 00:20:07.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skaddr.h
  * Project:	Gigabit Ethernet Adapters, ADDR-Modul
- * Version:	$Revision: 1.29 $
- * Date:	$Date: 2003/05/13 16:57:24 $
  * Purpose:	Header file for Address Management (MC, UC, Prom).
  *
  ******************************************************************************/
@@ -24,112 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skaddr.h,v $
- *	Revision 1.29  2003/05/13 16:57:24  mkarl
- *	Changes for SLIM driver.
- *	Editorial changes.
- *	
- *	Revision 1.28  2003/04/15 09:33:22  tschilli
- *	Copyright messages changed.
- *	
- *	Revision 1.27  2003/04/14 15:55:11  tschilli
- *	"#error C++ is not yet supported." removed.
- *	
- *	Revision 1.26  2002/11/15 07:24:42  tschilli
- *	SK_ADDR_EQUAL macro fixed.
- *	
- *	Revision 1.25  2002/06/10 13:55:18  tschilli
- *	Changes for handling YUKON.
- *	All changes are internally and not visible to the programmer
- *	using this module.
- *	
- *	Revision 1.24  2001/01/22 13:41:34  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.23  2000/08/10 11:27:50  rassmann
- *	Editorial changes.
- *	Preserving 32-bit alignment in structs for the adapter context.
- *	
- *	Revision 1.22  2000/08/07 11:10:40  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.21  2000/05/04 09:39:59  rassmann
- *	Editorial changes.
- *	Corrected multicast address hashing.
- *	
- *	Revision 1.20  1999/11/22 13:46:14  cgoos
- *	Changed license header to GPL.
- *	Allowing overwrite for SK_ADDR_EQUAL.
- *	
- *	Revision 1.19  1999/05/28 10:56:07  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.18  1999/04/06 17:22:04  rassmann
- *	Added private "ActivePort".
- *	
- *	Revision 1.17  1999/01/14 16:18:19  rassmann
- *	Corrected multicast initialization.
- *	
- *	Revision 1.16  1999/01/04 10:30:36  rassmann
- *	SkAddrOverride only possible after SK_INIT_IO phase.
- *	
- *	Revision 1.15  1998/12/29 13:13:11  rassmann
- *	An address override is now preserved in the SK_INIT_IO phase.
- *	All functions return an int now.
- *	Extended parameter checking.
- *	
- *	Revision 1.14  1998/11/24 12:39:45  rassmann
- *	Reserved multicast entry for BPDU address.
- *	13 multicast entries left for protocol.
- *	
- *	Revision 1.13  1998/11/13 17:24:32  rassmann
- *	Changed return value of SkAddrOverride to int.
- *	
- *	Revision 1.12  1998/11/13 16:56:19  rassmann
- *	Added macro SK_ADDR_COMPARE.
- *	Changed return type of SkAddrOverride to SK_BOOL.
- *	
- *	Revision 1.11  1998/10/28 18:16:35  rassmann
- *	Avoiding I/Os before SK_INIT_RUN level.
- *	Aligning InexactFilter.
- *	
- *	Revision 1.10  1998/10/22 11:39:10  rassmann
- *	Corrected signed/unsigned mismatches.
- *	
- *	Revision 1.9  1998/10/15 15:15:49  rassmann
- *	Changed Flags Parameters from SK_U8 to int.
- *	Checked with lint.
- *	
- *	Revision 1.8  1998/09/24 19:15:12  rassmann
- *	Code cleanup.
- *	
- *	Revision 1.7  1998/09/18 20:22:13  rassmann
- *	Added HW access.
- *	
- *	Revision 1.6  1998/09/04 19:40:20  rassmann
- *	Interface enhancements.
- *	
- *	Revision 1.5  1998/09/04 12:40:57  rassmann
- *	Interface cleanup.
- *	
- *	Revision 1.4  1998/09/04 12:14:13  rassmann
- *	Interface cleanup.
- *	
- *	Revision 1.3  1998/09/02 16:56:40  rassmann
- *	Updated interface.
- *	
- *	Revision 1.2  1998/08/27 14:26:09  rassmann
- *	Updated interface.
- *	
- *	Revision 1.1  1998/08/21 08:31:08  rassmann
- *	First public version.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This module is intended to manage multicast addresses and promiscuous mode
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skcsum.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skcsum.h
--- linux-2.4.25/drivers/net/sk98lin/h/skcsum.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skcsum.h	2004-03-25 00:17:21.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skcsum.h
  * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/08/20 13:59:57 $
  * Purpose:	Store/verify Internet checksum in send/receive packets.
  *
  ******************************************************************************/
@@ -23,52 +21,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skcsum.h,v $
- *	Revision 1.10  2003/08/20 13:59:57  mschmid
- *	Changed notation of #ifndef SkCsCalculateChecksum to
- *	#ifndef SK_CS_CALCULATE_CHECKSUM
- *	
- *	Revision 1.9  2001/02/06 11:21:39  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.8  2001/02/06 11:15:36  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.7  2000/06/29 13:17:05  rassmann
- *	Corrected reception of a packet with UDP checksum == 0 (which means there
- *	is no UDP checksum).
- *	
- *	Revision 1.6  2000/02/28 12:33:44  cgoos
- *	Changed C++ style comments to C style.
- *	
- *	Revision 1.5  2000/02/21 12:10:05  cgoos
- *	Fixed license comment.
- *	
- *	Revision 1.4  2000/02/21 11:08:37  cgoos
- *	Merged changes back into common source.
- *	
- *	Revision 1.1  1999/07/26 14:47:49  mkarl
- *	changed from common source to windows specific source
- *	added return SKCS_STATUS_IP_CSUM_ERROR_UDP and
- *	SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester
- *	changes for Tx csum offload
- *	
- *	Revision 1.2  1998/09/04 12:16:34  mhaveman
- *	Checked in for Stephan to allow compilation.
- *	-Added definition SK_CSUM_EVENT_CLEAR_PROTO_STATS to clear statistic
- *	-Added prototype for SkCsEvent()
- *	
- *	Revision 1.1  1998/09/01 15:36:53  swolf
- *	initial revision
- *
- *	01-Sep-1998 sw	Created.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * Public header file for the "GEnesis" common module "CSUM".
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skdebug.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skdebug.h
--- linux-2.4.25/drivers/net/sk98lin/h/skdebug.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skdebug.h	2004-03-25 00:20:04.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skdebug.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/05/13 17:26:00 $
  * Purpose:	SK specific DEBUG support
  *
  ******************************************************************************/
@@ -22,58 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *	$Log: skdebug.h,v $
- *	Revision 1.14  2003/05/13 17:26:00  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.13  2003/03/31 07:16:39  mkarl
- *	Corrected Copyright.
- *	
- *	Revision 1.12  2002/07/15 15:37:13  rschmidt
- *	Power Management support
- *	Editorial changes
- *	
- *	Revision 1.11  2002/04/25 11:04:39  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.10  1999/11/22 13:47:40  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.9  1999/09/14 14:02:43  rwahl
- *	Added SK_DBGMOD_PECP.
- *	
- *	Revision 1.8  1998/11/25 08:31:54  gklug
- *	fix: no C++ comments allowed in common sources
- *	
- *	Revision 1.7  1998/11/24 16:47:24  swolf
- *	Driver may now define its own SK_DBG_MSG() (eg. in "h/skdrv1st.h").
- *	
- *	Revision 1.6  1998/10/28 10:23:55  rassmann
- *	ADDED SK_DBGMOD_ADDR.
- *	
- *	Revision 1.5  1998/10/22 09:43:55  gklug
- *	add: CSUM module
- *	
- *	Revision 1.4  1998/10/01 07:54:44  gklug
- *	add: PNMI debug module
- *	
- *	Revision 1.3  1998/09/18 08:32:34  afischer
- *	Macros changed according ssr-spec.:
- *		SK_DBG_MODCHK -> SK_DBG_CHKMOD
- *		SK_DBG_CATCHK -> SK_DBG_CHKCAT
- *	
- *	Revision 1.2  1998/07/03 14:38:25  malthoff
- *	Add category SK_DBGCAT_FATAL.
- *	
- *	Revision 1.1  1998/06/19 13:39:01  malthoff
- *	created.
- *	
- *
- ******************************************************************************/
-
 #ifndef __INC_SKDEBUG_H
 #define __INC_SKDEBUG_H
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skdrv1st.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skdrv1st.h
--- linux-2.4.25/drivers/net/sk98lin/h/skdrv1st.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skdrv1st.h	2004-03-25 00:17:02.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skdrv1st.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.4 $
- * Date:	$Date: 2003/11/12 14:28:14 $
  * Purpose:	First header file for driver and all other modules
  *
  ******************************************************************************/
@@ -24,87 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skdrv1st.h,v $
- *	Revision 1.4  2003/11/12 14:28:14  rroesler
- *	Fix: use dedicated ip_fast_csum() on X86_64 systems
- *	
- *	Revision 1.3  2003/10/07 08:16:52  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.2  2003/09/29 12:05:59  mlindner
- *	Fix: Added define SK_CS_CALCULSTE_CHECKSUM
- *	
- *	Revision 1.1  2003/07/21 07:22:43  rroesler
- *	Fix: Re-Enter after CVS crash
- *	
- *	Revision 1.15  2003/07/17 14:54:09  rroesler
- *	Fix: Corrected SK_PNMI_READ macros to copy right amount of bytes
- *	
- *	Revision 1.14  2003/06/03 14:36:32  mlindner
- *	Add: Additions for SK_SLIM
- *	
- *	Revision 1.13  2003/05/26 14:03:06  mlindner
- *	Add: Support for SLIM skaddr
- *	
- *	Revision 1.12  2003/05/26 12:56:39  mlindner
- *	Add: Support for Kernel 2.5/2.6
- *	Add: New SkOsGetTimeCurrent function
- *	Add: SK_PNMI_HUNDREDS_SEC definition
- *	Fix: SK_TICKS_PER_SEC on Intel Itanium2
- *	
- *	Revision 1.11  2003/02/25 14:16:40  mlindner
- *	Fix: Copyright statement
- *	
- *	Revision 1.10  2002/10/02 12:46:02  mlindner
- *	Add: Support for Yukon
- *	
- *	Revision 1.9.2.2  2001/12/07 12:06:42  mlindner
- *	Fix: malloc -> slab changes
- *	
- *	Revision 1.9.2.1  2001/03/12 16:50:59  mlindner
- *	chg: kernel 2.4 adaption
- *	
- *	Revision 1.9  2001/01/22 14:16:04  mlindner
- *	added ProcFs functionality
- *	Dual Net functionality integrated
- *	Rlmt networks added
- *	
- *	Revision 1.8  2000/02/21 12:19:18  cgoos
- *	Added default for SK_DEBUG_CHKMOD/_CHKCAT
- *	
- *	Revision 1.7  1999/11/22 13:50:00  cgoos
- *	Changed license header to GPL.
- *	Added overwrite for several functions.
- *	Removed linux 2.0.x definitions.
- *	Removed PCI vendor ID definition (now in kernel).
- *	
- *	Revision 1.6  1999/07/27 08:03:33  cgoos
- *	Changed SK_IN/OUT macros to readX/writeX instead of memory
- *	accesses (necessary for ALPHA).
- *	
- *	Revision 1.5  1999/07/23 12:10:21  cgoos
- *	Removed SK_RLMT_SLOW_LOOKAHEAD define.
- *	
- *	Revision 1.4  1999/07/14 12:31:13  cgoos
- *	Added SK_RLMT_SLOW_LOOKAHEAD define.
- *	
- *	Revision 1.3  1999/04/07 10:12:54  cgoos
- *	Added check for KERNEL and OPTIMIZATION defines.
- *	
- *	Revision 1.2  1999/03/01 08:51:47  cgoos
- *	Fixed pcibios_read/write definitions.
- *	
- *	Revision 1.1  1999/02/16 07:40:49  cgoos
- *	First version.
- *	
- *	
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This is the first include file of the driver, which includes all
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skdrv2nd.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skdrv2nd.h
--- linux-2.4.25/drivers/net/sk98lin/h/skdrv2nd.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skdrv2nd.h	2004-03-25 00:22:23.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skdrv2nd.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/12/11 16:04:45 $
  * Purpose:	Second header file for driver and all other modules
  *
  ******************************************************************************/
@@ -24,122 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skdrv2nd.h,v $
- *	Revision 1.10  2003/12/11 16:04:45  mlindner
- *	Add: New pnmi data backup structure
- *	
- *	Revision 1.9  2003/11/10 09:31:37  rroesler
- *	Add: pnmiBackup structure for DIAG backup restore
- *	
- *	Revision 1.8  2003/10/22 14:18:32  rroesler
- *	Fix: DIAG handling for DualNet cards
- *	
- *	Revision 1.7  2003/10/07 09:34:59  mlindner
- *	Add: New defines for lower and upper range values (interrupt moderation)
- *	
- *	Revision 1.6  2003/10/07 08:16:51  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.5  2003/09/01 13:10:39  rroesler
- *	Add: Prototypes for DIAG Attach/Detach functions
- *	
- *	Revision 1.4  2003/09/01 12:33:38  rroesler
- *	Add: Defines for optimized DIAG interaction
- *	
- *	Revision 1.3  2003/08/12 16:51:18  mlindner
- *	Fix: UDP and TCP Proto checks
- *	Fix: UDP header offset
- *	
- *	Revision 1.2  2003/08/07 10:50:54  mlindner
- *	Add: Speed and HW-Csum support for Yukon Lite chipset
- *	
- *	Revision 1.1  2003/07/21 07:25:29  rroesler
- *	Fix: Re-Enter after CVS crash
- *	
- *	Revision 1.19  2003/07/07 09:53:10  rroesler
- *	Fix: Removed proprietary RxTx defines and used the ones from skgehw.h instead
- *	
- *	Revision 1.18  2003/06/12 07:54:14  mlindner
- *	Fix: Changed Descriptor Alignment to 64 Byte
- *	
- *	Revision 1.17  2003/05/26 12:56:39  mlindner
- *	Add: Support for Kernel 2.5/2.6
- *	Add: New SkOsGetTimeCurrent function
- *	Add: SK_PNMI_HUNDREDS_SEC definition
- *	Fix: SK_TICKS_PER_SEC on Intel Itanium2
- *	
- *	Revision 1.16  2003/03/21 14:56:18  rroesler
- *	Added code regarding interrupt moderation
- *	
- *	Revision 1.15  2003/02/25 14:16:40  mlindner
- *	Fix: Copyright statement
- *	
- *	Revision 1.14  2003/02/25 13:26:26  mlindner
- *	Add: Support for various vendors
- *	
- *	Revision 1.13  2002/10/02 12:46:02  mlindner
- *	Add: Support for Yukon
- *	
- *	Revision 1.12.2.2  2001/09/05 12:14:50  mlindner
- *	add: New hardware revision int
- *	
- *	Revision 1.12.2.1  2001/03/12 16:50:59  mlindner
- *	chg: kernel 2.4 adaption
- *	
- *	Revision 1.12  2001/03/01 12:52:15  mlindner
- *	Fixed ring size
- *
- *	Revision 1.11  2001/02/19 13:28:02  mlindner
- *	Changed PNMI parameter values
- *
- *	Revision 1.10  2001/01/22 14:16:04  mlindner
- *	added ProcFs functionality
- *	Dual Net functionality integrated
- *	Rlmt networks added
- *
- *	Revision 1.1  2000/10/05 19:46:50  phargrov
- *	Add directory src/vipk_devs_nonlbl/vipk_sk98lin/
- *	This is the SysKonnect SK-98xx Gigabit Ethernet driver,
- *	contributed by SysKonnect.
- *
- *	Revision 1.9  2000/02/21 10:39:55  cgoos
- *	Added flag for jumbo support usage.
- *
- *	Revision 1.8  1999/11/22 13:50:44  cgoos
- *	Changed license header to GPL.
- *	Fixed two comments.
- *
- *	Revision 1.7  1999/09/28 12:38:21  cgoos
- *	Added CheckQueue to SK_AC.
- *	
- *	Revision 1.6  1999/07/27 08:04:05  cgoos
- *	Added checksumming variables to SK_AC.
- *	
- *	Revision 1.5  1999/03/29 12:33:26  cgoos
- *	Rreversed to fine lock granularity.
- *	
- *	Revision 1.4  1999/03/15 12:14:02  cgoos
- *	Added DriverLock to SK_AC.
- *	Removed other locks.
- *	
- *	Revision 1.3  1999/03/01 08:52:27  cgoos
- *	Changed pAC->PciDev declaration.
- *	
- *	Revision 1.2  1999/02/18 10:57:14  cgoos
- *	Removed SkDrvTimeStamp prototype.
- *	Fixed SkGeOsGetTime prototype.
- *	
- *	Revision 1.1  1999/02/16 07:41:01  cgoos
- *	First version.
- *	
- *	
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This is the second include file of the driver, which includes all other
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skerror.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skerror.h
--- linux-2.4.25/drivers/net/sk98lin/h/skerror.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skerror.h	2004-03-25 00:19:54.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skerror.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/05/13 17:25:13 $
  * Purpose:	SK specific Error log support
  *
  ******************************************************************************/
@@ -22,38 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *	$Log: skerror.h,v $
- *	Revision 1.7  2003/05/13 17:25:13  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.6  2003/03/31 07:17:48  mkarl
- *	Corrected Copyright.
- *	
- *	Revision 1.5  2002/04/25 11:05:10  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.4  1999/11/22 13:51:59  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.3  1999/09/14 14:04:42  rwahl
- *	Added error base SK_ERRBASE_PECP.
- *	Changed error base for driver.
- *	
- *	Revision 1.2  1998/08/11 11:15:41  gklug
- *	chg: comments
- *	
- *	Revision 1.1  1998/08/11 11:09:38  gklug
- *	add: error bases
- *	add: error Classes
- *	first version
- *	
- *	
- *
- ******************************************************************************/
-
 #ifndef _INC_SKERROR_H_
 #define _INC_SKERROR_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgedrv.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgedrv.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgedrv.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgedrv.h	2004-03-25 00:20:41.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgedrv.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/07/04 12:25:01 $
  * Purpose:	Interface with the driver
  *
  ******************************************************************************/
@@ -22,47 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgedrv.h,v $
- *	Revision 1.10  2003/07/04 12:25:01  rschmidt
- *	Added event SK_DRV_DOWNSHIFT_DET for Downshift 4-Pair / 2-Pair
- *	
- *	Revision 1.9  2003/05/13 17:24:21  mkarl
- *	Added events SK_DRV_LINK_UP and SK_DRV_LINK_DOWN for drivers not using
- *	RLMT (SK_NO_RLMT).
- *	Editorial changes.
- *	
- *	Revision 1.8  2003/03/31 07:18:54  mkarl
- *	Corrected Copyright.
- *	
- *	Revision 1.7  2003/03/18 09:43:47  rroesler
- *	Added new event for timer
- *	
- *	Revision 1.6  2002/07/15 15:38:01  rschmidt
- *	Power Management support
- *	Editorial changes
- *	
- *	Revision 1.5  2002/04/25 11:05:47  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.4  1999/11/22 13:52:46  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.3  1998/12/01 13:31:39  cgoos
- *	SWITCH INTERN Event added.
- *	
- *	Revision 1.2  1998/11/25 08:28:38  gklug
- *	rmv: PORT SWITCH Event
- *	
- *	Revision 1.1  1998/09/29 06:14:07  gklug
- *	add: driver events (initial version)
- *	
- *
- ******************************************************************************/
-
 #ifndef __INC_SKGEDRV_H_
 #define __INC_SKGEDRV_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgehw.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgehw.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgehw.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgehw.h	2004-03-25 00:22:12.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgehw.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.56 $
- * Date:	$Date: 2003/09/23 09:01:00 $
  * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
  *
  ******************************************************************************/
@@ -22,236 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- * $Log: skgehw.h,v $
- * Revision 1.56  2003/09/23 09:01:00  malthoff
- * Minor change: Define I2C device size constants as long.
- *
- * Revision 1.55  2003/09/16 14:03:34  rschmidt
- * Added define for YUKON-Lite Rev. A1,A2 Chip Revision
- * Moved defines for PHY power down modes to skgeinit.h
- * Editorial changes
- *
- * Revision 1.54  2003/09/16 07:37:58  mschmid
- * Added defines for Marvell PHY low power modes
- *
- * Revision 1.53  2003/07/04 12:39:01  rschmidt
- * Added SK_FAR to pointers in XM_IN32() and GM_IN32() macros (for PXE)
- * Editorial changes
- *
- * Revision 1.52  2003/05/13 17:16:36  mkarl
- * Added SK_FAR for PXE.
- * Editorial changes.
- *
- * Revision 1.51  2003/04/08 16:31:50  rschmidt
- * Added defines for new Chip IDs (YUKON-Lite, YUKON-LP)
- * Editorial changes
- *
- * Revision 1.50  2003/03/31 07:29:45  mkarl
- * Corrected Copyright.
- * Editorial changes.
- *
- * Revision 1.49  2003/01/28 09:43:49  rschmidt
- * Added defines for PCI-Spec. 2.3 IRQ
- * Added defines for CLK_RUN (YUKON-Lite)
- * Editorial changes
- *
- * Revision 1.48  2002/12/05 10:25:11  rschmidt
- * Added defines for Half Duplex Burst Mode On/Off
- * Added defines for Rx GMAC FIFO Flush feature
- * Editorial changes
- *
- * Revision 1.47  2002/11/12 17:01:31  rschmidt
- * Added defines for WOL_CTL_DEFAULT
- * Editorial changes
- *
- * Revision 1.46  2002/10/14 14:47:57  rschmidt
- * Corrected bit mask for HW self test results
- * Added defines for WOL Registers
- * Editorial changes
- *
- * Revision 1.45  2002/10/11 09:25:22  mkarl
- * Added bit mask for HW self test results.
- *
- * Revision 1.44  2002/08/16 14:44:36  rschmidt
- * Added define GPC_HWCFG_GMII_FIB for YUKON Fiber
- *
- * Revision 1.43  2002/08/12 13:31:50  rschmidt
- * Corrected macros for GMAC Address Registers: GM_INADDR(),
- * GM_OUTADDR(), GM_INHASH, GM_OUTHASH.
- * Editorial changes
- *
- * Revision 1.42  2002/08/08 15:37:56  rschmidt
- * Added defines for Power Management Capabilities
- * Editorial changes
- *
- * Revision 1.41  2002/07/23 16:02:25  rschmidt
- * Added macro WOL_REG() to access WOL reg. (HW-Bug in YUKON 1st rev.)
- *
- * Revision 1.40  2002/07/15 15:41:37  rschmidt
- * Added new defines for Power Management Cap. & Control
- * Editorial changes
- *
- * Revision 1.39  2002/06/10 09:37:07  rschmidt
- * Added macros for the ADDR-Module
- *
- * Revision 1.38  2002/06/05 08:15:19  rschmidt
- * Added defines for WOL Registers
- * Editorial changes
- *
- * Revision 1.37  2002/04/25 11:39:23  rschmidt
- * Added new defines for PCI Our Register 1
- * Added new registers and defines for YUKON (Rx FIFO, Tx FIFO,
- * Time Stamp Timer, GMAC Control, GPHY Control,Link Control,
- * GMAC IRQ Source and Mask, Wake-up Frame Pattern Match);
- * Added new defines for Control/Status (VAUX available)
- * Added Chip ID for YUKON
- * Added define for descriptors with UDP ext. for YUKON
- * Added macros to access the GMAC
- * Added new Phy Type for Marvell 88E1011S (GPHY)
- * Editorial changes
- *
- * Revision 1.36  2000/11/09 12:32:49  rassmann
- * Renamed variables.
- *
- * Revision 1.35  2000/05/19 10:17:13  cgoos
- * Added inactivity check in PHY_READ (in DEBUG mode only).
- *
- * Revision 1.34  1999/11/22 13:53:40  cgoos
- * Changed license header to GPL.
- *
- * Revision 1.33  1999/08/27 11:17:10  malthoff
- * It's more savely to put brackets around macro parameters.
- * Brackets added for PHY_READ and PHY_WRITE.
- *
- * Revision 1.32  1999/05/19 07:31:01  cgoos
- * Changes for 1000Base-T.
- * Added HWAC_LINK_LED macro.
- *
- * Revision 1.31  1999/03/12 13:27:40  malthoff
- * Remove __STDC__.
- *
- * Revision 1.30  1999/02/09 09:28:20  malthoff
- * Add PCI_ERRBITS.
- *
- * Revision 1.29  1999/01/26 08:55:48  malthoff
- * Bugfix: The 16 bit field relations inside the descriptor are
- * 	endianess dependend if the descriptor reversal feature
- * 	(PCI_REV_DESC bit in PCI_OUR_REG_2) is enabled.
- * 	Drivers which use this feature has to set the define
- * 	SK_USE_REV_DESC.
- *
- * Revision 1.28  1998/12/10 11:10:22  malthoff
- * bug fix: IS_IRQ_STAT and IS_IRQ_MST_ERR has been twisted.
- *
- * Revision 1.27  1998/11/13 14:19:21  malthoff
- * Bug Fix: The bit definition of B3_PA_CTRL has completely
- * changed from HW Spec v1.3 to v1.5.
- *
- * Revision 1.26  1998/11/04 08:31:48  cgoos
- * Fixed byte ordering in XM_OUTADDR/XM_OUTHASH macros.
- *
- * Revision 1.25  1998/11/04 07:16:25  cgoos
- * Changed byte ordering in XM_INADDR/XM_INHASH again.
- *
- * Revision 1.24  1998/11/02 11:08:43  malthoff
- * RxCtrl and TxCtrl must be volatile.
- *
- * Revision 1.23  1998/10/28 13:50:45  malthoff
- * Fix: Endian support missing in XM_IN/OUT-ADDR/HASH macros.
- *
- * Revision 1.22  1998/10/26 08:01:36  malthoff
- * RX_MFF_CTRL1 is split up into RX_MFF_CTRL1,
- * RX_MFF_STAT_TO, and RX_MFF_TIST_TO.
- * TX_MFF_CTRL1 is split up TX_MFF_CTRL1 and TX_MFF_WAF.
- *
- * Revision 1.21  1998/10/20 07:43:10  malthoff
- * Fix: XM_IN/OUT/ADDR/HASH macros:
- * The pointer must be casted.
- *
- * Revision 1.20  1998/10/19 15:53:59  malthoff
- * Remove ML proto definitions.
- *
- * Revision 1.19  1998/10/16 14:40:17  gklug
- * fix: typo B0_XM_IMSK regs
- *
- * Revision 1.18  1998/10/16 09:46:54  malthoff
- * Remove temp defines for ML diag prototype.
- * Fix register definition for B0_XM1_PHY_DATA, B0_XM1_PHY_DATA
- * B0_XM2_PHY_DATA, B0_XM2_PHY_ADDR, B0_XA1_CSR, B0_XS1_CSR,
- * B0_XS2_CSR, and B0_XA2_CSR.
- *
- * Revision 1.17  1998/10/14 06:03:14  cgoos
- * Changed shifted constant to ULONG.
- *
- * Revision 1.16  1998/10/09 07:05:41  malthoff
- * Rename ALL_PA_ENA_TO to PA_ENA_TO_ALL.
- *
- * Revision 1.15  1998/10/05 07:54:23  malthoff
- * Split up RB_CTRL and it's bit definition into
- * RB_CTRL, RB_TST1, and RB_TST2.
- * Rename RB_RX_HTPP to RB_RX_LTPP.
- * Add ALL_PA_ENA_TO. Modify F_WATER_MARK
- * according to HW Spec. v1.5.
- * Add MFF_TX_CTRL_DEF.
- *
- * Revision 1.14  1998/09/28 13:31:16  malthoff
- * bug fix: B2_MAC_3 is 0x110 not 0x114
- *
- * Revision 1.13  1998/09/24 14:42:56  malthoff
- * Split the RX_MFF_TST into RX_MFF_CTRL2,
- * RX_MFF_TST1, and RX_MFF_TST2.
- * Rename RX_MFF_CTRL to RX_MFF_CTRL1.
- * Add BMU bit CSR_SV_IDLE.
- * Add macros PHY_READ() and PHY_WRITE().
- * Rename macro SK_ADDR() to SK_HW_ADDR()
- * because of conflicts with the Address Module.
- *
- * Revision 1.12  1998/09/16 07:25:33  malthoff
- * Change the parameter order in the XM_INxx and XM_OUTxx macros,
- * to have the IoC as first parameter.
- *
- * Revision 1.11  1998/09/03 09:58:41  malthoff
- * Rework the XM_xxx macros. Use {} instead of () to
- * be compatible with SK_xxx macros which are defined
- * with {}.
- *
- * Revision 1.10  1998/09/02 11:16:39  malthoff
- * Temporary modify B2_I2C_SW to make tests with
- * the GE/ML prototype.
- *
- * Revision 1.9  1998/08/19 09:11:49  gklug
- * fix: struct are removed from c-source (see CCC)
- * add: typedefs for all structs
- *
- * Revision 1.8  1998/08/18 08:27:27  malthoff
- * Add some temporary workarounds to test GE
- * sources with the ML.
- *
- * Revision 1.7  1998/07/03 14:42:26  malthoff
- * bug fix: Correct macro XMA().
- * Add temporary workaround to access the PCI config space over I/O
- *
- * Revision 1.6  1998/06/23 11:30:36  malthoff
- * Remove ';' with ',' in macors.
- *
- * Revision 1.5  1998/06/22 14:20:57  malthoff
- * Add macro SK_ADDR(Base,Addr).
- *
- * Revision 1.4  1998/06/19 13:35:43  malthoff
- * change 'pGec' with 'pAC'
- *
- * Revision 1.3  1998/06/17 14:58:16  cvs
- * Lost keywords reinserted.
- *
- * Revision 1.1  1998/06/17 14:16:36  cvs
- * created
- *
- *
- ******************************************************************************/
-
 #ifndef __INC_SKGEHW_H
 #define __INC_SKGEHW_H
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgehwt.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgehwt.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgehwt.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgehwt.h	2004-03-25 00:19:06.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skhwt.h
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/09/16 12:55:08 $
  * Purpose:	Defines for the hardware timer functions
  *
  ******************************************************************************/
@@ -22,34 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgehwt.h,v $
- *	Revision 1.7  2003/09/16 12:55:08  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.6  2003/05/13 17:57:48  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.5  1999/11/22 13:54:24  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.4  1998/08/19 09:50:58  gklug
- *	fix: remove struct keyword from C-code (see CCC) add typedefs
- *	
- *	Revision 1.3  1998/08/14 07:09:29  gklug
- *	fix: chg pAc -> pAC
- *	
- *	Revision 1.2  1998/08/07 12:54:21  gklug
- *	fix: first compiled version
- *	
- *	Revision 1.1  1998/08/07 09:32:58  gklug
- *	first version
- *
- ******************************************************************************/
-
 /*
  * SKGEHWT.H	contains all defines and types for the timer functions
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgei2c.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgei2c.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgei2c.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgei2c.h	2004-03-25 00:21:12.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgei2c.h
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.25 $
- * Date:	$Date: 2003/10/20 09:06:05 $
  * Purpose:	Special defines for TWSI
  *
  ******************************************************************************/
@@ -22,100 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgei2c.h,v $
- *	Revision 1.25  2003/10/20 09:06:05  rschmidt
- *	Editorial changes.
- *	
- *	Revision 1.24  2003/09/23 09:31:15  malthoff
- *	Parameter dev_size added to macro definition of SK_I2C_CTL.
- *	
- *	Revision 1.23  2002/12/19 14:34:27  rschmidt
- *	Added cast in macros SK_I2C_SET_BIT() and SK_I2C_CLR_BIT()
- *	Editorial changes (TWSI)
- *	
- *	Revision 1.22  2002/10/14 16:45:56  rschmidt
- *	Editorial changes (TWSI)
- *	
- *	Revision 1.21  2002/08/13 08:42:24  rschmidt
- *	Changed define for SK_MIN_SENSORS back to 5
- *	Merged defines for PHY PLL 3V3 voltage (A and B)
- *	Editorial changes
- *	
- *	Revision 1.20  2002/08/06 09:43:56  jschmalz
- *	Extensions and changes for Yukon
- *	
- *	Revision 1.19  2002/08/02 12:00:08  rschmidt
- *	Added defines for YUKON sensors
- *	Editorial changes
- *	
- *	Revision 1.18  2001/08/16 12:44:33  afischer
- *	LM80 sensor init values corrected
- *	
- *	Revision 1.17  1999/11/22 13:55:25  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.16  1999/11/12 08:24:10  malthoff
- *	Change voltage warning and error limits
- *	(warning +-5%, error +-10%).
- *	
- *	Revision 1.15  1999/09/14 14:14:43  malthoff
- *	The 1000BT Dual Link adapter has got only one Fan.
- *	The second Fan has been removed.
- *	
- *	Revision 1.14  1999/05/27 13:40:50  malthoff
- *	Fan Divisor = 1. Assuming fan with 6500 rpm.
- *	
- *	Revision 1.13  1999/05/20 14:56:55  malthoff
- *	Bug Fix: Missing brace in SK_LM80_FAN_FAKTOR.
- *	
- *	Revision 1.12  1999/05/20 09:22:00  cgoos
- *	Changes for 1000Base-T (Fan sensors).
- *	
- *	Revision 1.11  1998/10/14 05:57:22  cgoos
- *	Fixed compilation warnings.
- *	
- *	Revision 1.10  1998/09/04 08:37:00  malthoff
- *	bugfix: correct the SK_I2C_GET_CTL() macro.
- *	
- *	Revision 1.9  1998/08/25 06:10:03  gklug
- *	add: thresholds for all sensors
- *
- *	Revision 1.8  1998/08/20 11:37:42  gklug
- *	chg: change Ioc to IoC
- *	
- *	Revision 1.7  1998/08/20 08:53:11  gklug
- *	fix: compiler errors
- *	add: Threshold values
- *	
- *	Revision 1.6  1998/08/17 11:37:09  malthoff
- *	Bugfix in SK_I2C_CTL macro. The parameter 'dev'
- *	has to be shifted 9 bits.
- *	
- *	Revision 1.5  1998/08/17 06:52:21  malthoff
- *	Remove unrequired macros.
- *	Add macros for accessing TWSI SW register.
- *	
- *	Revision 1.4  1998/08/13 08:30:18  gklug
- *	add: conversion factors for read values
- *	add: new state SEN_VALEXT to read extension value of temperature sensor
- *
- *	Revision 1.3  1998/08/12 13:37:56  gklug
- *	rmv: error numbers and messages
- *
- *	Revision 1.2  1998/08/11 07:54:38  gklug
- *	add: sensor states for GE sensors
- *	add: Macro to access TWSI hardware register
- *	chg: Error messages for TWSI errors
- *
- *	Revision 1.1  1998/07/17 11:27:56  gklug
- *	Created.
- *
- ******************************************************************************/
-
 /*
  * SKGEI2C.H	contains all SK-98xx specific defines for the TWSI handling
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgeinit.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgeinit.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgeinit.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgeinit.h	2004-03-25 00:21:12.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgeinit.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.83 $
- * Date:	$Date: 2003/09/16 14:07:37 $
  * Purpose:	Structures and prototypes for the GE Init Module
  *
  ******************************************************************************/
@@ -22,353 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgeinit.h,v $
- *	Revision 1.83  2003/09/16 14:07:37  rschmidt
- *	Moved defines for PHY power down modes from skgehw.h
- *	Added prototypes for SkMacClearRst()
- *	Editorial changes
- *	
- *	Revision 1.82  2003/09/16 07:18:36  mschmid
- *	Added members to port structure for MAC control
- *	- PMacColThres
- *	- PMacJamLen
- *	- PMacJamIpgVal
- *	- PMacJamIpgData
- *	- PMacIpgData
- *	- PMacLimit4
- *	Added PHY power state to port structure
- *	- PPhyPowerState
- *	Added function prototypes to enter and leave low power modes
- *	
- *	Revision 1.81  2003/07/04 12:30:38  rschmidt
- *	Added SK_FAR to pointers in MAC statistic functions (for PXE)
- *	Editorial changes
- *	
- *	Revision 1.80  2003/05/28 15:25:30  rschmidt
- *	Added SK_FAR to pointers in MAC/PHY read functions (for PXE)
- *	Minor changes to avoid LINT warnings
- *	Editorial changes
- *
- *	Revision 1.79  2003/05/06 12:02:33  rschmidt
- *	Added entry GIYukon in s_GeInit structure
- *	Editorial changes
- *
- *	Revision 1.78  2003/04/28 08:59:57  rschmidt
- *	Added entries GIValIrqMask and GITimeStampCnt in s_GeInit structure
- *
- *	Revision 1.77  2003/04/08 16:27:02  rschmidt
- *	Added entry GILedBlinkCtrl in s_GeInit structure
- *	Added defines for LED Blink Control
- *
- *	Revision 1.76  2003/03/31 07:21:01  mkarl
- *	Added PGmANegAdv to SK_GEPORT.
- *	Corrected Copyright.
- *
- *	Revision 1.75  2003/02/05 13:36:39  rschmidt
- *	Added define SK_FACT_78	for YUKON's Host Clock of 78.12 MHz
- *	Editorial changes
- *
- *	Revision 1.74  2003/01/28 09:39:16  rschmidt
- *	Added entry GIYukonLite in s_GeInit structure
- *	Editorial changes
- *
- *	Revision 1.73  2002/11/15 12:47:25  rschmidt
- *	Replaced error message SKERR_HWI_E024 for Cable Diagnostic with
- *	Rx queue error in SkGeStopPort().
- *
- *	Revision 1.72  2002/11/12 17:08:35  rschmidt
- *	Added entries for Cable Diagnostic to Port structure
- *	Added entries GIPciSlot64 and GIPciClock66 in s_GeInit structure
- *	Added error message for Cable Diagnostic
- *	Added prototypes for SkGmCableDiagStatus()
- *	Editorial changes
- *
- *	Revision 1.71  2002/10/21 11:26:10  mkarl
- *	Changed interface of SkGeInitAssignRamToQueues().
- *
- *	Revision 1.70  2002/10/14 08:21:32  rschmidt
- *	Changed type of GICopperType, GIVauxAvail to SK_BOOL
- *	Added entry PRxOverCnt to Port structure
- *	Added entry GIYukon32Bit in s_GeInit structure
- *	Editorial changes
- *
- *	Revision 1.69  2002/10/09 16:57:15  mkarl
- *	Added some constants and macros for SkGeInitAssignRamToQueues().
- *
- *	Revision 1.68  2002/09/12 08:58:51  rwahl
- *	Retrieve counters needed for XMAC errata workarounds directly because
- *	PNMI returns corrected counter values (e.g. #10620).
- *
- *	Revision 1.67  2002/08/16 14:40:30  rschmidt
- *	Added entries GIGenesis and GICopperType in s_GeInit structure
- *	Added prototypes for SkMacHashing()
- *	Editorial changes
- *
- *	Revision 1.66  2002/08/12 13:27:21  rschmidt
- *	Added defines for Link speed capabilities
- *	Added entry PLinkSpeedCap to Port structure
- *	Added entry GIVauxAvail in s_GeInit structure
- *	Added prototypes for SkMacPromiscMode()
- *	Editorial changes
- *
- *	Revision 1.65  2002/08/08 15:46:18  rschmidt
- *	Added define SK_PHY_ACC_TO for PHY access timeout
- *	Added define SK_XM_RX_HI_WM for XMAC Rx High Watermark
- *	Added define SK_MIN_TXQ_SIZE for Min RAM Buffer Tx Queue Size
- *	Added entry PhyId1 to Port structure
- *
- *	Revision 1.64  2002/07/23 16:02:56  rschmidt
- *	Added entry GIWolOffs in s_GeInit struct (HW-Bug in YUKON 1st rev.)
- *	Added prototypes for: SkGePhyRead(), SkGePhyWrite()
- *
- *	Revision 1.63  2002/07/18 08:17:38  rwahl
- *	Corrected definitions for SK_LSPEED_xxx & SK_LSPEED_STAT_xxx.
- *
- *	Revision 1.62  2002/07/17 18:21:55  rwahl
- *	Added SK_LSPEED_INDETERMINATED define.
- *
- *	Revision 1.61  2002/07/17 17:16:03  rwahl
- *	- MacType now member of GIni struct.
- *	- Struct alignment to 32bit.
- *	- Editorial change.
- *
- *	Revision 1.60  2002/07/15 18:23:39  rwahl
- *	Added GeMacFunc to GE Init structure.
- *	Added prototypes for SkXmUpdateStats(), SkGmUpdateStats(),
- *	  SkXmMacStatistic(), SkGmMacStatistic(), SkXmResetCounter(),
- *	  SkGmResetCounter(), SkXmOverflowStatus(), SkGmOverflowStatus().
- *	Added defines for current link speed state.
- *	Added ERRMSG defintions for MacUpdateStat() & MacStatistics().
- *
- *	Revision 1.59  2002/07/15 15:40:22  rschmidt
- *	Added entry PLinkSpeedUsed to Port structure
- *	Editorial changes
- *
- *	Revision 1.58  2002/06/10 09:36:30  rschmidt
- *	Editorial changes.
- *
- *	Revision 1.57  2002/06/05 08:18:00  rschmidt
- *	Corrected alignment in Port Structure
- *	Added new prototypes for GMAC
- *	Editorial changes
- *
- *	Revision 1.56  2002/04/25 11:38:12  rschmidt
- *	Added defines for Link speed values
- *	Added defines for Loopback parameters for MAC and PHY
- *	Removed entry PRxCmd from Port structure
- *	Added entry PLinkSpeed to Port structure
- *	Added entries GIChipId and GIChipRev to GE Init structure
- *	Removed entry GIAnyPortAct from GE Init structure
- *	Added prototypes for: SkMacInit(), SkMacInitPhy(),
- *	SkMacRxTxDisable(), SkMacSoftRst(), SkMacHardRst(), SkMacIrq(),
- *	SkMacIrqDisable(), SkMacFlushTxFifo(), SkMacFlushRxFifo(),
- *	SkMacAutoNegDone(), SkMacAutoNegLipaPhy(), SkMacSetRxTxEn(),
- *	SkXmPhyRead(), SkXmPhyRead(), SkGmPhyWrite(), SkGmPhyWrite();
- *	Removed prototypes for static functions in SkXmac2.c
- *	Editorial changes
- *
- *	Revision 1.55  2002/02/26 15:24:53  rwahl
- *	Fix: no link with manual configuration (#10673). The previous fix for
- *	#10639 was removed. So for RLMT mode = CLS the RLMT may switch to
- *	misconfigured port. It should not occur for the other RLMT modes.
- *
- *	Revision 1.54  2002/01/18 16:52:52  rwahl
- *	Editorial corrections.
- *
- *	Revision 1.53  2001/11/20 09:19:58  rwahl
- *	Reworked bugfix #10639 (no dependency to RLMT mode).
- *
- *	Revision 1.52  2001/10/26 07:52:23  afischer
- *	Port switching bug in `check local link` mode
- *
- *	Revision 1.51  2001/02/09 12:26:38  cgoos
- *	Inserted #ifdef DIAG for half duplex workaround timer.
- *
- *	Revision 1.50  2001/02/07 07:56:40  rassmann
- *	Corrected copyright.
- *
- *	Revision 1.49  2001/01/31 15:32:18  gklug
- *	fix: problem with autosensing an SR8800 switch
- *	add: counter for autoneg timeouts
- *
- *	Revision 1.48  2000/11/09 11:30:10  rassmann
- *	WA: Waiting after releasing reset until BCom chip is accessible.
- *
- *	Revision 1.47  2000/10/18 12:22:40  cgoos
- *	Added workaround for half duplex hangup.
- *
- *	Revision 1.46  2000/08/10 11:28:00  rassmann
- *	Editorial changes.
- *	Preserving 32-bit alignment in structs for the adapter context.
- *
- *	Revision 1.45  1999/11/22 13:56:19  cgoos
- *	Changed license header to GPL.
- *
- *	Revision 1.44  1999/10/26 07:34:15  malthoff
- *	The define SK_LNK_ON has been lost in v1.41.
- *
- *	Revision 1.43  1999/10/06 09:30:16  cgoos
- *	Changed SK_XM_THR_JUMBO.
- *
- *	Revision 1.42  1999/09/16 12:58:26  cgoos
- *	Changed SK_LED_STANDY macro to be independent of HW link sync.
- *
- *	Revision 1.41  1999/07/30 06:56:14  malthoff
- *	Correct comment for SK_MS_STAT_UNSET.
- *
- *	Revision 1.40  1999/05/27 13:38:46  cgoos
- *	Added SK_BMU_TX_WM.
- *	Made SK_BMU_TX_WM and SK_BMU_RX_WM user-definable.
- *	Changed XMAC Tx treshold to max. values.
- *
- *	Revision 1.39  1999/05/20 14:35:26  malthoff
- *	Remove prototypes for SkGeLinkLED().
- *
- *	Revision 1.38  1999/05/19 11:59:12  cgoos
- *	Added SK_MS_CAP_INDETERMINATED define.
- *
- *	Revision 1.37  1999/05/19 07:32:33  cgoos
- *	Changes for 1000Base-T.
- *	LED-defines for HWAC_LINK_LED macro.
- *
- *	Revision 1.36  1999/04/08 14:00:24  gklug
- *	add:Port struct field PLinkResCt
- *
- *	Revision 1.35  1999/03/25 07:43:07  malthoff
- *	Add error string for SKERR_HWI_E018MSG.
- *
- *	Revision 1.34  1999/03/12 16:25:57  malthoff
- *	Remove PPollRxD and PPollTxD.
- *	Add SKERR_HWI_E017MSG. and SK_DPOLL_MAX.
- *
- *	Revision 1.33  1999/03/12 13:34:41  malthoff
- *	Add Autonegotiation error codes.
- *	Change defines for parameter Mode in SkXmSetRxCmd().
- *	Replace __STDC__ by SK_KR_PROTO.
- *
- *	Revision 1.32  1999/01/25 14:40:20  mhaveman
- *	Added new return states for the virtual management port if multiple
- *	ports are active but differently configured.
- *
- *	Revision 1.31  1998/12/11 15:17:02  gklug
- *	add: Link partnet autoneg states : Unknown Manual and Auto-negotiation
- *
- *	Revision 1.30  1998/12/07 12:17:04  gklug
- *	add: Link Partner auto-negotiation flag
- *
- *	Revision 1.29  1998/12/01 10:54:42  gklug
- *	add: variables for XMAC Errata
- *
- *	Revision 1.28  1998/12/01 10:14:15  gklug
- *	add: PIsave saves the Interrupt status word
- *
- *	Revision 1.27  1998/11/26 15:24:52  mhaveman
- *	Added link status states SK_LMODE_STAT_AUTOHALF and
- *	SK_LMODE_STAT_AUTOFULL which are used by PNMI.
- *
- *	Revision 1.26  1998/11/26 14:53:01  gklug
- *	add:autoNeg Timeout variable
- *
- *	Revision 1.25  1998/11/26 08:58:50  gklug
- *	add: Link Mode configuration (AUTO Sense mode)
- *
- *	Revision 1.24  1998/11/24 13:30:27  gklug
- *	add: PCheckPar to port struct
- *
- *	Revision 1.23  1998/11/18 13:23:26  malthoff
- *	Add SK_PKT_TO_MAX.
- *
- *	Revision 1.22  1998/11/18 13:19:54  gklug
- *	add: PPrevShorts and PLinkBroken to port struct for WA XMAC Errata #C1
- *
- *	Revision 1.21  1998/10/26 08:02:57  malthoff
- *	Add GIRamOffs.
- *
- *	Revision 1.20  1998/10/19 07:28:37  malthoff
- *	Add prototype for SkGeInitRamIface().
- *
- *	Revision 1.19  1998/10/14 14:47:48  malthoff
- *	SK_TIMER should not be defined for Diagnostics.
- *	Add SKERR_HWI_E015MSG and SKERR_HWI_E016MSG.
- *
- *	Revision 1.18  1998/10/14 14:00:03  gklug
- *	add: timer to port struct for workaround of Errata #2
- *
- *	Revision 1.17  1998/10/14 11:23:09  malthoff
- *	Add prototype for SkXmAutoNegDone().
- *	Fix SkXmSetRxCmd() prototype statement.
- *
- *	Revision 1.16  1998/10/14 05:42:29  gklug
- *	add: HWLinkUp flag to Port struct
- *
- *	Revision 1.15  1998/10/09 08:26:33  malthoff
- *	Rename SK_RB_ULPP_B to SK_RB_LLPP_B.
- *
- *	Revision 1.14  1998/10/09 07:11:13  malthoff
- *	bug fix: SK_FACT_53 is 85 not 117.
- *	Rework time out init values.
- *	Add GIPortUsage and corresponding defines.
- *	Add some error log messages.
- *
- *	Revision 1.13  1998/10/06 14:13:14  malthoff
- *	Add prototype for SkGeLoadLnkSyncCnt().
- *
- *	Revision 1.12  1998/10/05 11:29:53  malthoff
- *	bug fix: A comment was not closed.
- *
- *	Revision 1.11  1998/10/05 08:01:59  malthoff
- *	Add default Timeout- Threshold- and
- *	Watermark constants. Add QRam start and end
- *	variables. Also add vars to store the polling
- *	mode and receive command. Add new Error Log
- *	Messages and function prototypes.
- *
- *	Revision 1.10  1998/09/28 13:34:48  malthoff
- *	Add mode bits for LED functions.
- *	Move Autoneg and Flow Ctrl bits from shgesirq.h
- *	Add the required Error Log Entries
- *	and Function Prototypes.
- *
- *	Revision 1.9  1998/09/16 14:38:41  malthoff
- *	Rework the SK_LNK_xxx defines.
- *	Add error log message defines.
- *	Add prototypes for skxmac2.c
- *
- *	Revision 1.8  1998/09/11 05:29:18  gklug
- *	add: init state of a port
- *
- *	Revision 1.7  1998/09/08 08:35:52  gklug
- *	add: defines of the Init Levels
- *
- *	Revision 1.6  1998/09/03 13:48:42  gklug
- *	add: Link strati, capabilities to Port struct
- *
- *	Revision 1.5  1998/09/03 13:30:59  malthoff
- *	Add SK_LNK_BLINK and SK_LNK_PERM.
- *
- *	Revision 1.4  1998/09/03 09:55:31  malthoff
- *	Add constants for parameters Dir and RstMode
- *	when calling SkGeStopPort().
- *	Rework the prototype section.
- *	Add Queue Address offsets PRxQOff, PXsQOff, and PXaQOff.
- *	Remove Ioc with IoC.
- *
- *	Revision 1.3  1998/08/19 09:11:54  gklug
- *	fix: struct are removed from c-source (see CCC)
- *	add: typedefs for all structs
- *
- *	Revision 1.2  1998/07/28 12:38:26  malthoff
- *	The prototypes got the parameter 'IoC'.
- *
- *	Revision 1.1  1998/07/23 09:50:24  malthoff
- *	Created.
- *
- ******************************************************************************/
-
 #ifndef __INC_SKGEINIT_H_
 #define __INC_SKGEINIT_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgepnm2.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgepnm2.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgepnm2.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgepnm2.h	2004-03-25 00:20:46.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgepnm2.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.36 $
- * Date:	$Date: 2003/05/23 12:45:13 $
  * Purpose:	Defines for Private Network Management Interface
  *
  ****************************************************************************/
@@ -22,144 +20,6 @@
  *
  ******************************************************************************/
 
-/*****************************************************************************
- *
- * History:
- *
- *	$Log: skgepnm2.h,v $
- *	Revision 1.36  2003/05/23 12:45:13  tschilli
- *	#ifndef SK_PNMI_HUNDREDS_SEC added to SK_PNMI_HUNDREDS_SEC definition
- *	to allow own time macro defines.
- *	
- *	Revision 1.35  2003/03/27 11:27:48  tschilli
- *	Copyright messages changed.
- *	
- *	Revision 1.34  2002/12/16 09:05:18  tschilli
- *	Code for VCT handling added.
- *	
- *	Revision 1.33  2002/09/10 09:00:03  rwahl
- *	Adapted boolean definitions according sktypes.
- *	
- *	Revision 1.32  2002/08/09 09:47:01  rwahl
- *	Added write-only flag to oid access defines.
- *	Editorial changes.
- *	
- *	Revision 1.31  2002/07/17 19:23:18  rwahl
- *	- Replaced MAC counter definitions by enumeration.
- *	- Added definition SK_PNMI_MAC_TYPES.
- *	- Added chipset defnition for Yukon.
- *	
- *	Revision 1.30  2001/02/06 10:03:41  mkunz
- *	- Pnmi V4 dual net support added. Interface functions and macros extended
- *	- Vpd bug fixed
- *	- OID_SKGE_MTU added
- *	
- *	Revision 1.29  2001/01/22 13:41:37  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.28  2000/08/03 15:12:48  rwahl
- *	- Additional comment for MAC statistic data structure.
- *	
- *	Revision 1.27  2000/08/01 16:10:18  rwahl
- *	- Added mac statistic data structure for StatRxLongFrame counter.
- *	
- *	Revision 1.26  2000/03/31 13:51:34  rwahl
- *	Added SK_UPTR cast to offset calculation for PNMI struct fields;
- *	missing cast caused compiler warnings by Win64 compiler.
- *	
- *	Revision 1.25  1999/11/22 13:57:41  cgoos
- *	Changed license header to GPL.
- *	Allowing overwrite for SK_PNMI_STORE/_READ defines.
- *	
- *	Revision 1.24  1999/04/13 15:11:11  mhaveman
- *	Changed copyright.
- *	
- *	Revision 1.23  1999/01/28 15:07:12  mhaveman
- *	Changed default threshold for port switches per hour from 10
- *	to 240 which means 4 switches per minute. This fits better
- *	the granularity of 32 for the port switch estimate
- *	counter.
- *	
- *	Revision 1.22  1999/01/05 12:52:30  mhaveman
- *	Removed macro SK_PNMI_MICRO_SEC.
- *	
- *	Revision 1.21  1999/01/05 12:50:34  mhaveman
- *	Enlarged macro definition SK_PNMI_HUNDREDS_SEC() so that no 64-bit
- *	arithmetic is necessary if SK_TICKS_PER_SEC is 100.
- *	
- *	Revision 1.20  1998/12/09 14:02:53  mhaveman
- *	Defined macro SK_PNMI_DEF_RLMT_CHG_THRES for default port switch
- *	threshold.
- *	
- *	Revision 1.19  1998/12/03 11:28:41  mhaveman
- *	Removed SK_PNMI_CHECKPTR macro.
- *	
- *	Revision 1.18  1998/12/03 11:21:00  mhaveman
- *	-Added pointer check macro SK_PNMI_CHECKPTR
- *	-Added macros SK_PNMI_VPD_ARR_SIZE and SK_PNMI_VPD_STR_SIZE for
- *	 VPD key evaluation.
- *	
- *	Revision 1.17  1998/11/20 13:20:33  mhaveman
- *	Fixed bug in SK_PNMI_SET_STAT macro. ErrorStatus was not correctly set.
- *	
- *	Revision 1.16  1998/11/20 08:08:49  mhaveman
- *	Macro SK_PNMI_CHECKFLAGS has got a if clause.
- *	
- *	Revision 1.15  1998/11/03 13:53:40  mhaveman
- *	Fixed alignment problem in macor SK_PNMI_SET_STAT macro.
- *	
- *	Revision 1.14  1998/10/30 15:50:13  mhaveman
- *	Added macro SK_PNMI_MICRO_SEC()
- *	
- *	Revision 1.13  1998/10/30 12:32:20  mhaveman
- *	Added forgotten cast in SK_PNMI_READ_U32 macro.
- *
- *	Revision 1.12  1998/10/29 15:40:26  mhaveman
- *	-Changed SK_PNMI_TRAP_SENSOR_LEN because SensorDescr has now
- *	 variable string length.
- *	-Defined SK_PNMI_CHECKFLAGS macro
- *	
- *	Revision 1.11  1998/10/29 08:53:34  mhaveman
- *	Removed SK_PNMI_RLM_XXX table indexed because these counters need
- *	not been saved over XMAC resets.
- *	
- *	Revision 1.10  1998/10/28 08:48:20  mhaveman
- *	-Added macros for storage according to alignment
- *	-Changed type of Instance to SK_U32 because of VPD
- *	-Removed trap structures. Not needed because of alignment problem
- *	-Changed type of Action form SK_U8 to int
- *	
- *	Revision 1.9  1998/10/21 13:34:45  mhaveman
- *	Shit, mismatched calculation of SK_PNMI_HUNDREDS_SEC. Corrected.
- *	
- *	Revision 1.8  1998/10/21 13:24:58  mhaveman
- *	Changed calculation of hundreds of seconds.
- *	
- *	Revision 1.7  1998/10/20 07:31:41  mhaveman
- *	Made type changes to unsigned int where possible.
- *	
- *	Revision 1.6  1998/09/04 17:04:05  mhaveman
- *	Added Sync counters to offset storage to provided settled values on
- *	port switch.
- *	
- *	Revision 1.5  1998/09/04 12:45:35  mhaveman
- *	Removed dummies for SK_DRIVER_ macros. They should be added by driver
- *	writer in skdrv2nd.h.
- *	
- *	Revision 1.4  1998/09/04 11:59:50  mhaveman
- *	Everything compiles now. Driver Macros for counting still missing.
- *	
- *	Revision 1.3  1998/08/24 12:01:35  mhaveman
- *	Intermediate state.
- *	
- *	Revision 1.2  1998/08/17 07:51:40  mhaveman
- *	Intermediate state.
- *	
- *	Revision 1.1  1998/08/11 09:08:40  mhaveman
- *	Intermediate state.
- *	
- ****************************************************************************/
-
 #ifndef _SKGEPNM2_H_
 #define _SKGEPNM2_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgepnmi.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgepnmi.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgepnmi.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgepnmi.h	2004-03-25 00:17:30.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgepnmi.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.62 $
- * Date:	$Date: 2003/08/15 12:31:52 $
  * Purpose:	Defines for Private Network Management Interface
  *
  ****************************************************************************/
@@ -22,237 +20,6 @@
  *
  ******************************************************************************/
 
-/*****************************************************************************
- *
- * History:
- *
- *	$Log: skgepnmi.h,v $
- *	Revision 1.62  2003/08/15 12:31:52  tschilli
- *	Added new OIDs:
- *	OID_SKGE_DRIVER_RELDATE
- *	OID_SKGE_DRIVER_FILENAME
- *	OID_SKGE_CHIPID
- *	OID_SKGE_RAMSIZE
- *	OID_SKGE_VAUXAVAIL
- *	OID_SKGE_PHY_TYPE
- *	OID_SKGE_PHY_LP_MODE
- *	
- *	Added new define SK_DIAG_ATTACHED for OID_SKGE_DIAG_MODE handling.
- *	
- *	Revision 1.61  2003/05/23 12:53:52  tschilli
- *	Generic PNMI IOCTL subcommands added.
- *	Function prototype SkPnmiGenIoctl() added.
- *	OID_SKGE_BOARDLEVEL added.
- *	Return value SK_PNMI_ERR_NOT_SUPPORTED added.
- *	Editorial changes.
- *	
- *	Revision 1.60  2003/03/27 11:27:26  tschilli
- *	Copyright messages changed.
- *	
- *	Revision 1.59  2002/12/16 14:03:50  tschilli
- *	New defines for VCT added.
- *	
- *	Revision 1.58  2002/12/16 09:04:59  tschilli
- *	Code for VCT handling added.
- *	
- *	Revision 1.57  2002/09/26 12:41:05  tschilli
- *	SK_PNMI_PORT BufPort entry in struct SK_PNMI added.
- *	
- *	Revision 1.56  2002/08/16 11:10:41  rwahl
- *	- Replaced c++ comment.
- *	
- *	Revision 1.55  2002/08/09 15:40:21  rwahl
- *	Editorial change (renamed ConfSpeedCap).
- *	
- *	Revision 1.54  2002/08/09 11:06:07  rwahl
- *	Added OID_SKGE_SPEED_CAP.
- *	
- *	Revision 1.53  2002/08/09 09:45:28  rwahl
- *	Added support for NDIS OID_PNP_xxx.
- *	Editorial changes.
- *	
- *	Revision 1.52  2002/08/06 17:54:07  rwahl
- *	- Added speed cap to PNMI config struct.
- *	
- *	Revision 1.51  2002/07/17 19:19:26  rwahl
- *	- Added OID_SKGE_SPEED_MODE and OID_SKGE_SPEED_STATUS.
- *	- Added SK_PNMI_CNT_RX_PMACC_ERR() & SK_PNMI_CNT_RX_LONGFRAMES().
- *	- Added speed mode & status to PNMI config struct.
- *	- Editorial changes.
- *	
- *	Revision 1.50  2002/05/22 08:59:37  rwahl
- *	Added string definitions for error msgs.
- *	
- *	Revision 1.49  2001/11/20 09:23:50  rwahl
- *	- pnmi struct: reordered and aligned to 32bit.
- *	
- *	Revision 1.48  2001/02/23 14:34:24  mkunz
- *	Changed macro PHYS2INST. Added pAC to Interface
- *	
- *	Revision 1.47  2001/02/07 08:28:23  mkunz
- *	- Added Oids: 	OID_SKGE_DIAG_ACTION
- *					OID_SKGE_DIAG_RESULT
- *					OID_SKGE_MULTICAST_LIST
- *					OID_SKGE_CURRENT_PACKET_FILTER
- *					OID_SKGE_INTERMEDIATE_SUPPORT
- *	- Changed value of OID_SKGE_MTU
- *	
- *	Revision 1.46  2001/02/06 10:01:41  mkunz
- *	- Pnmi V4 dual net support added. Interface functions and macros extended
- *	- Vpd bug fixed
- *	- OID_SKGE_MTU added
- *	
- *	Revision 1.45  2001/01/22 13:41:37  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.44  2000/09/07 07:35:27  rwahl
- *	- removed NDIS counter specific data type.
- *	- fixed spelling for OID_SKGE_RLMT_PORT_PREFERRED.
- *	
- *	Revision 1.43  2000/08/04 11:41:08  rwahl
- *	- Fixed compiler warning (port is always >= 0) for macros
- *	  SK_PNMI_CNT_RX_LONGFRAMES & SK_PNMI_CNT_SYNC_OCTETS
- *	
- *	Revision 1.42  2000/08/03 15:14:07  rwahl
- *	- Corrected error in driver macros addressing a physical port.
- *	
- *	Revision 1.41  2000/08/01 16:22:29  rwahl
- *	- Changed MDB version to 3.1.
- *	- Added definitions for StatRxLongFrames counter.
- *	- Added macro to be used by driver to count long frames received.
- *	- Added directive to control width (default = 32bit) of NDIS statistic
- *	  counters (SK_NDIS_64BIT_CTR).
- *	
- *	Revision 1.40  2000/03/31 13:51:34  rwahl
- *	Added SK_UPTR cast to offset calculation for PNMI struct fields;
- *	missing cast caused compiler warnings by Win64 compiler.
- *
- *	Revision 1.39  1999/12/06 10:09:47  rwahl
- *	Added new error log message.
- *	
- *	Revision 1.38  1999/11/22 13:57:55  cgoos
- *	Changed license header to GPL.
- *
- *	Revision 1.37  1999/09/14 14:25:32  rwahl
- *	Set MDB version for 1000Base-T (sensors, Master/Slave) changes.
- *	
- *	Revision 1.36  1999/05/20 09:24:56  cgoos
- *	Changes for 1000Base-T (sensors, Master/Slave).
- *	
- *	Revision 1.35  1999/04/13 15:10:51  mhaveman
- *	Replaced RLMT macros SK_RLMT_CHECK_xxx again by those of PNMI to
- *	grant unified interface. But PNMI macros will store the same
- *	value as RLMT macros.
- *	
- *	Revision 1.34  1999/04/13 15:03:49  mhaveman
- *	-Changed copyright
- *	-Removed SK_PNMI_RLMT_MODE_CHK_xxx macros. Those of RLMT should be
- *	 used.
- *	
- *	Revision 1.33  1999/03/23 10:41:02  mhaveman
- *	Changed comments.
- *	
- *	Revision 1.32  1999/01/25 15:01:33  mhaveman
- *	Added support for multiple simultaniously active ports.
- *	
- *	Revision 1.31  1999/01/19 10:06:26  mhaveman
- *	Added new error log message.
- *	
- *	Revision 1.30  1999/01/05 10:34:49  mhaveman
- *	Fixed little error in RlmtChangeEstimate calculation.
- *	
- *	Revision 1.29  1999/01/05 09:59:41  mhaveman
- *	Redesigned port switch average calculation to avoid 64bit
- *	arithmetic.
- *	
- *	Revision 1.28  1998/12/08 10:05:48  mhaveman
- *	Defined macro SK_PNMI_MIN_STRUCT_SIZE.
- *	
- *	Revision 1.27  1998/12/03 14:39:35  mhaveman
- *	Fixed problem that LSTAT was enumerated wrong.
- *	
- *	Revision 1.26  1998/12/03 11:19:51  mhaveman
- *	Changed contents of errlog message SK_PNMI_ERR016MSG
- *	
- *	Revision 1.25  1998/12/01 10:40:04  mhaveman
- *	Changed size of SensorNumber, ChecksumNumber and RlmtPortNumber in
- *	SK_PNMI_STRUCT_DATA to be conform with OID definition.
- *	
- *	Revision 1.24  1998/11/20 08:09:27  mhaveman
- *	Added macros to convert between logical, physical port indexes and
- *	instances.
- *	
- *	Revision 1.23  1998/11/10 13:41:13  mhaveman
- *	Needed to change interface, because NT driver needs a return value
- *	of needed buffer space on TOO_SHORT errors. Therefore all
- *	SkPnmiGet/Preset/Set functions now have a pointer to the length
- *	parameter, where the needed space on error is returned.
- *	
- *	Revision 1.22  1998/11/03 12:05:51  mhaveman
- *	Added pAC parameter to counter macors.
- *
- *	Revision 1.21  1998/11/02 10:47:36  mhaveman
- *	Added syslog messages for internal errors.
- *	
- *	Revision 1.20  1998/10/30 15:49:36  mhaveman
- *	-Removed unused SK_PNMI_UTILIZATION_BASE and EstOldCnt.
- *	-Redefined SK_PNMI_CHG_EST_BASE to hundreds of seconds.
- *	
- *	Revision 1.19  1998/10/29 15:38:44  mhaveman
- *	Changed string lengths of PNMI_STRUCT_DATA structure because
- *	string OIDs are now encoded with leading length ocetet.
- *	
- *	Revision 1.18  1998/10/29 08:52:27  mhaveman
- *	-Added byte to strings in PNMI_STRUCT_DATA structure.
- *	-Shortened SK_PNMI_RLMT structure to SK_MAX_MACS elements.
- *	
- *	Revision 1.17  1998/10/28 08:49:50  mhaveman
- *	-Changed type of Instance back to SK_U32 because of VPD
- *	-Changed type from SK_U8 to char of PciBusSpeed, PciBusWidth, PMD,
- *	 and Connector.
- *	
- *	Revision 1.16  1998/10/22 10:42:31  mhaveman
- *	-Removed (SK_U32) casts for OIDs
- *	-excluded NDIS OIDs when they are already defined with ifndef _NDIS_
- *	
- *	Revision 1.15  1998/10/20 13:56:28  mhaveman
- *	Headerfile includes now directly other header files to comile correctly.
- *	
- *	Revision 1.14  1998/10/20 07:31:09  mhaveman
- *	Made type changes to unsigned int where possible.
- *	
- *	Revision 1.13  1998/10/19 10:53:13  mhaveman
- *	-Casted OID definitions to SK_U32
- *	-Renamed RlmtMAC... to RlmtPort...
- *	-Changed wrong type of VpdEntriesList from SK_U32 to char *
- *	
- *	Revision 1.12  1998/10/13 07:42:27  mhaveman
- *	-Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA
- *	-Removed old cvs history entries
- *	-Renamed MacNumber to PortNumber
- *	
- *	Revision 1.11  1998/10/07 10:55:24  mhaveman
- *	-Added OID_MDB_VERSION. Therefore was a renumbering of the VPD OIDs
- *	 necessary.
- *	-Added OID_GEN_ Ids to support the windows driver.
- *	
- *	Revision 1.10  1998/09/30 13:41:10  mhaveman
- *	Renamed some OIDs to reduce usage of 'MAC' which is replaced by 'PORT'.
- *	
- *	Revision 1.9  1998/09/04 17:06:17  mhaveman
- *	-Added SyncCounter as macro.
- *	-Renamed OID_SKGE_.._NO_DESCR_CTS to OID_SKGE_.._NO_BUF_CTS.
- *	-Added macros for driver description and version strings.
- *	
- *	Revision 1.8  1998/09/04 14:36:52  mhaveman
- *	Added OIDs and Structure to access value of macro counters which are
- *	counted by the driver.
- *	
- *	Revision 1.7  1998/09/04 11:59:36  mhaveman
- *	Everything compiles now. Driver Macros for counting still missing.
- *	
- ****************************************************************************/
-
 #ifndef _SKGEPNMI_H_
 #define _SKGEPNMI_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgesirq.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skgesirq.h
--- linux-2.4.25/drivers/net/sk98lin/h/skgesirq.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skgesirq.h	2004-03-25 00:22:01.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgesirq.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.30 $
- * Date:	$Date: 2003/07/04 12:34:13 $
  * Purpose:	SK specific Gigabit Ethernet special IRQ functions
  *
  ******************************************************************************/
@@ -22,111 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *	$Log: skgesirq.h,v $
- *	Revision 1.30  2003/07/04 12:34:13  rschmidt
- *	Added SKERR_SIRQ_E025 for Downshift detected (Yukon-Copper)
- *	
- *	Revision 1.29  2003/05/28 15:14:49  rschmidt
- *	Moved defines for return codes of SkGePortCheckUp() to header file.
- *	Minor changes to avoid LINT warnings.
- *	
- *	Revision 1.28  2003/05/13 17:22:43  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.27  2003/03/31 07:32:34  mkarl
- *	Corrected Copyright.
- *	Editorial changes.
- *	
- *	Revision 1.26  2002/10/14 09:52:36  rschmidt
- *	Added SKERR_SIRQ_E023 and SKERR_SIRQ_E024 for GPHY (Yukon)
- *	Editorial changes
- *	
- *	Revision 1.25  2002/07/15 18:15:52  rwahl
- *	Editorial changes.
- *	
- *	Revision 1.24  2002/07/15 15:39:21  rschmidt
- *	Corrected define for SKERR_SIRQ_E022
- *	Editorial changes
- *	
- *	Revision 1.23  2002/04/25 11:09:45  rschmidt
- *	Removed declarations for SkXmInitPhy(), SkXmRxTxEnable()
- *	Editorial changes
- *	
- *	Revision 1.22  2000/11/09 11:30:10  rassmann
- *	WA: Waiting after releasing reset until BCom chip is accessible.
- *	
- *	Revision 1.21  2000/10/18 12:22:40  cgoos
- *	Added workaround for half duplex hangup.
- *	
- *	Revision 1.20  1999/12/06 10:00:44  cgoos
- *	Added SET event for role.
- *	
- *	Revision 1.19  1999/11/22 13:58:26  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.18  1999/05/19 07:32:59  cgoos
- *	Changes for 1000Base-T.
- *	
- *	Revision 1.17  1999/03/12 13:29:31  malthoff
- *	Move Autonegotiation Error Codes to skgeinit.h.
- *	
- *	Revision 1.16  1999/03/08 10:11:28  gklug
- *	add: AutoNegDone return codes
- *	
- *	Revision 1.15  1998/11/18 13:20:53  gklug
- *	add: different timeouts for active and non-active links
- *	
- *	Revision 1.14  1998/11/04 07:18:14  cgoos
- *	Added prototype for SkXmRxTxEnable.
- *	
- *	Revision 1.13  1998/10/21 05:52:23  gklug
- *	add: parameter DoLoop to InitPhy function
- *	
- *	Revision 1.12  1998/10/19 06:45:03  cgoos
- *	Added prototype for SkXmInitPhy.
- *	
- *	Revision 1.11  1998/10/15 14:34:10  gklug
- *	add: WA_TIME is 500 msec
- *	
- *	Revision 1.10  1998/10/14 14:49:41  malthoff
- *	Remove err log defines E021 and E022. They are
- *	defined in skgeinit.h now.
- *
- *	Revision 1.9  1998/10/14 14:00:39  gklug
- *	add: error logs for init phys
- *	
- *	Revision 1.8  1998/10/14 05:44:05  gklug
- *	add: E020
- *	
- *	Revision 1.7  1998/10/02 06:24:58  gklug
- *	add: error messages
- *	
- *	Revision 1.6  1998/10/01 07:54:45  gklug
- *	add: PNMI debug module
- *	
- *	Revision 1.5  1998/09/28 13:36:31  malthoff
- *	Move the bit definitions for Autonegotiation
- *	and Flow Control to skgeinit.h.
- *	
- *	Revision 1.4  1998/09/15 12:29:34  gklug
- *	add: error logs
- *	
- *	Revision 1.3  1998/09/03 13:54:02  gklug
- *	add: function prototypes
- *	
- *	Revision 1.2  1998/09/03 10:24:36  gklug
- *	add: Events send by PNMI
- *	add: parameter definition for Flow Control etc.
- *	
- *	Revision 1.1  1998/08/27 11:50:27  gklug
- *	initial revision
- *	
- *
- ******************************************************************************/
-
 #ifndef _INC_SKGESIRQ_H_
 #define _INC_SKGESIRQ_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/ski2c.h linux-2.4.26-pre6/drivers/net/sk98lin/h/ski2c.h
--- linux-2.4.25/drivers/net/sk98lin/h/ski2c.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/ski2c.h	2004-03-25 00:18:40.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	ski2c.h
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.35 $
- * Date:	$Date: 2003/10/20 09:06:30 $
  * Purpose:	Defines to access Voltage and Temperature Sensor
  *
  ******************************************************************************/
@@ -22,128 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: ski2c.h,v $
- *	Revision 1.35  2003/10/20 09:06:30  rschmidt
- *	Added prototypes for SkI2cRead() and SkI2cWrite().
- *	Editorial changes.
- *	
- *	Revision 1.34  2003/01/28 09:11:21  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.33  2002/10/14 16:40:50  rschmidt
- *	Editorial changes (TWSI)
- *	
- *	Revision 1.32  2002/08/13 08:55:07  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.31  2002/08/06 09:44:22  jschmalz
- *	Extensions and changes for Yukon
- *	
- *	Revision 1.30  2001/04/05 11:38:09  rassmann
- *	Set SenState to idle in SkI2cWaitIrq().
- *	Changed error message in SkI2cWaitIrq().
- *	
- *	Revision 1.29  2000/08/03 14:28:17  rassmann
- *	- Added function to wait for I2C being ready before resetting the board.
- *	- Replaced one duplicate "out of range" message with correct one.
- *	
- *	Revision 1.28  1999/11/22 13:55:46  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.27  1999/05/20 09:23:10  cgoos
- *	Changes for 1000Base-T (Fan sensors).
- *	
- *	Revision 1.26  1998/12/01 13:45:47  gklug
- *	add: InitLevel to I2c struct
- *	
- *	Revision 1.25  1998/11/03 06:55:16  gklug
- *	add: Dummy Reads to I2c struct
- *	
- *	Revision 1.24  1998/10/02 14:28:59  cgoos
- *	Added prototype for SkI2cIsr.
- *	
- *	Revision 1.23  1998/09/08 12:20:11  gklug
- *	add: prototypes for init and read functions
- *	
- *	Revision 1.22  1998/09/08 07:37:56  gklug
- *	add: log error if PCI_IO voltage sensor could not be initialized
- *	
- *	Revision 1.21  1998/09/04 08:38:05  malthoff
- *	Change the values for I2C_READ and I2C_WRITE
- *	
- *	Revision 1.20  1998/08/25 07:52:22  gklug
- *	chg: Timestamps (last) added for logging
- *
- *	Revision 1.19  1998/08/25 06:09:00  gklug
- *	rmv: warning and error levels of the individual sensors.
- *	add: timing definitions for sending traps and logging errors
- *	
- *	Revision 1.18  1998/08/20 11:41:15  gklug
- *	chg: omit STRCPY macro by using char * as Sensor Description
- *	
- *	Revision 1.17  1998/08/20 11:37:43  gklug
- *	chg: change Ioc to IoC
- *	
- *	Revision 1.16  1998/08/20 11:30:38  gklug
- *	fix: SenRead declaration
- *	
- *	Revision 1.15  1998/08/20 11:27:53  gklug
- *	fix: Compile bugs with new awrning constants
- *	
- *	Revision 1.14  1998/08/20 08:53:12  gklug
- *	fix: compiler errors
- *	add: Threshold values
- *	
- *	Revision 1.13  1998/08/19 12:21:16  gklug
- *	fix: remove struct from C files (see CCC)
- *	add: typedefs for all structs
- *	
- *	Revision 1.12  1998/08/19 10:57:41  gklug
- *	add: Warning levels
- *	
- *	Revision 1.11  1998/08/18 08:37:02  malthoff
- *	Prototypes not required for SK_DIAG.
- *	
- *	Revision 1.10  1998/08/17 13:54:00  gklug
- *	fix: declaration of event function
- *	
- *	Revision 1.9  1998/08/17 06:48:39  malthoff
- *	Remove some unrequired macros.
- *	Fix the compiler errors.
- *	
- *	Revision 1.8  1998/08/14 06:47:19  gklug
- *	fix: Values are intergers
- *
- *	Revision 1.7  1998/08/14 06:26:05  gklug
- *	add: Init error message
- *
- *	Revision 1.6  1998/08/13 08:31:08  gklug
- *	add: Error message
- *
- *	Revision 1.5  1998/08/12 14:32:04  gklug
- *	add: new error code/message
- *
- *	Revision 1.4  1998/08/12 13:39:08  gklug
- *	chg: names of error messages
- *	add: defines for Sensor type and thresholds
- *
- *	Revision 1.3  1998/08/11 07:57:16  gklug
- *	add: sensor struct
- *	add: Timeout defines
- *	add: I2C control struct for pAC
- *
- *	Revision 1.2  1998/07/17 11:29:02  gklug
- *	rmv: Microwire and SMTPANIC
- *
- *	Revision 1.1  1998/06/19 14:30:10  malthoff
- *	Created. Sources taken from ML Project.
- *
- ******************************************************************************/
-
 /*
  * SKI2C.H	contains all I2C specific defines
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skqueue.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skqueue.h
--- linux-2.4.25/drivers/net/sk98lin/h/skqueue.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skqueue.h	2004-03-25 00:22:23.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skqueue.h
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.16 $
- * Date:	$Date: 2003/09/16 12:50:32 $
  * Purpose:	Defines for the Event queue
  *
  ******************************************************************************/
@@ -22,68 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skqueue.h,v $
- *	Revision 1.16  2003/09/16 12:50:32  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.15  2003/05/13 17:54:57  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.14  2002/03/15 10:52:13  mkunz
- *	Added event classes for link aggregation
- *	
- *	Revision 1.13  1999/11/22 13:59:05  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.12  1998/09/08 08:48:01  gklug
- *	add: init level handling
- *	
- *	Revision 1.11  1998/09/03 14:15:11  gklug
- *	add: CSUM and HWAC Eventclass and function.
- *	fix: pParaPtr according to CCC
- *	
- *	Revision 1.10  1998/08/20 12:43:03  gklug
- *	add: typedef SK_QUEUE
- *	
- *	Revision 1.9  1998/08/19 09:50:59  gklug
- *	fix: remove struct keyword from C-code (see CCC) add typedefs
- *	
- *	Revision 1.8  1998/08/18 07:00:01  gklug
- *	fix: SK_PTR not defined use void * instead.
- *	
- *	Revision 1.7  1998/08/17 13:43:19  gklug
- *	chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR
- *	
- *	Revision 1.6  1998/08/14 07:09:30  gklug
- *	fix: chg pAc -> pAC
- *	
- *	Revision 1.5  1998/08/11 14:26:44  gklug
- *	chg: Event Dispatcher returns now int.
- *	
- *	Revision 1.4  1998/08/11 12:15:21  gklug
- *	add: Error numbers of skqueue module
- *	
- *	Revision 1.3  1998/08/07 12:54:23  gklug
- *	fix: first compiled version
- *	
- *	Revision 1.2  1998/08/07 09:34:00  gklug
- *	adapt structure defs to CCC
- *	add: prototypes for functions
- *	
- *	Revision 1.1  1998/07/30 14:52:12  gklug
- *	Initial version.
- *	Defines Event Classes, Event structs and queue management variables.
- *
- ******************************************************************************/
-
-/*
- * SKQUEUE.H	contains all defines and types for the event queue
- */
-
 #ifndef _SKQUEUE_H_
 #define _SKQUEUE_H_
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skrlmt.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skrlmt.h
--- linux-2.4.25/drivers/net/sk98lin/h/skrlmt.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skrlmt.h	2004-03-25 00:22:36.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skrlmt.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/04/15 09:43:43 $
  * Purpose:	Header file for Redundant Link ManagemenT.
  *
  ******************************************************************************/
@@ -24,137 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skrlmt.h,v $
- *	Revision 1.37  2003/04/15 09:43:43  tschilli
- *	Copyright messages changed.
- *	
- *	Revision 1.36  2003/04/14 15:56:22  tschilli
- *	"#error C++ is not yet supported." removed.
- *	
- *	Revision 1.35  2003/01/31 14:12:41  mkunz
- *	single port adapter runs now with two identical MAC addresses
- *	
- *	Revision 1.34  2002/09/23 15:13:41  rwahl
- *	Editorial changes.
- *	
- *	Revision 1.33  2001/07/03 12:16:48  mkunz
- *	New Flag ChgBcPrio (Change priority of last broadcast received)
- *	
- *	Revision 1.32  2001/02/14 14:06:31  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.31  2001/02/05 14:25:26  rassmann
- *	Prepared RLMT for transparent operation.
- *	
- *	Revision 1.30  2001/01/22 13:41:39  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.29  2000/11/17 08:58:00  rassmann
- *	Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event.
- *	
- *	Revision 1.28  2000/11/09 12:24:34  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.27  1999/11/22 13:59:56  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.26  1999/10/04 14:01:19  rassmann
- *	Corrected reaction to reception of BPDU frames (#10441).
- *	
- *	Revision 1.25  1999/07/20 12:53:39  rassmann
- *	Fixed documentation errors for lookahead macros.
- *	
- *	Revision 1.24  1999/05/28 11:15:56  rassmann
- *	Changed behaviour to reflect Design Spec v1.2.
- *	Controlling Link LED(s).
- *	Introduced RLMT Packet Version field in RLMT Packet.
- *	Newstyle lookahead macros (checking meta-information before looking at
- *	  the packet).
- *	
- *	Revision 1.23  1999/01/28 12:50:42  rassmann
- *	Not using broadcast time stamps in CheckLinkState mode.
- *	
- *	Revision 1.22  1999/01/27 14:13:04  rassmann
- *	Monitoring broadcast traffic.
- *	Switching more reliably and not too early if switch is
- *	 configured for spanning tree.
- *	
- *	Revision 1.21  1998/12/08 13:11:25  rassmann
- *	Stopping SegTimer at RlmtStop.
- *	
- *	Revision 1.20  1998/11/24 12:37:33  rassmann
- *	Implemented segmentation check.
- *	
- *	Revision 1.19  1998/11/17 13:43:06  rassmann
- *	Handling (logical) tx failure.
- *	Sending packet on logical address after PORT_SWITCH.
- *	
- *	Revision 1.18  1998/11/13 16:56:56  rassmann
- *	Added macro version of SkRlmtLookaheadPacket.
- *	
- *	Revision 1.17  1998/11/06 18:06:05  rassmann
- *	Corrected timing when RLMT checks fail.
- *	Clearing tx counter earlier in periodical checks.
- *	
- *	Revision 1.16  1998/11/03 13:53:50  rassmann
- *	RLMT should switch now (at least in mode 3).
- *	
- *	Revision 1.15  1998/10/22 11:39:52  rassmann
- *	Corrected signed/unsigned mismatches.
- *	Corrected receive list handling and address recognition.
- *	
- *	Revision 1.14  1998/10/15 15:16:36  rassmann
- *	Finished Spanning Tree checking.
- *	Checked with lint.
- *	
- *	Revision 1.13  1998/09/24 19:16:08  rassmann
- *	Code cleanup.
- *	Introduced Timer for PORT_DOWN due to no RX.
- *	
- *	Revision 1.12  1998/09/16 11:09:52  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.11  1998/09/15 11:28:50  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.10  1998/09/14 17:07:38  rassmann
- *	Added code for port checking via LAN.
- *	Changed Mbuf definition.
- *	
- *	Revision 1.9  1998/09/07 11:14:15  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.8  1998/09/07 09:06:08  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.7  1998/09/04 19:41:34  rassmann
- *	Syntax corrections.
- *	Started entering code for checking local links.
- *	
- *	Revision 1.6  1998/09/04 12:14:28  rassmann
- *	Interface cleanup.
- *	
- *	Revision 1.5  1998/09/02 16:55:29  rassmann
- *	Updated to reflect new DRV/HWAC/RLMT interface.
- *	
- *	Revision 1.4  1998/09/02 07:26:02  afischer
- *	typedef for SK_RLMT_PORT
- *
- *	Revision 1.3  1998/08/27 14:29:03  rassmann
- *	Code cleanup.
- *	
- *	Revision 1.2  1998/08/27 14:26:25  rassmann
- *	Updated interface.
- *	
- *	Revision 1.1  1998/08/21 08:29:10  rassmann
- *	First public version.
- *	
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This is the header file for Redundant Link ManagemenT.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/sktimer.h linux-2.4.26-pre6/drivers/net/sk98lin/h/sktimer.h
--- linux-2.4.25/drivers/net/sk98lin/h/sktimer.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/sktimer.h	2004-03-25 00:18:00.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	sktimer.h
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/16 12:58:18 $
  * Purpose:	Defines for the timer functions
  *
  ******************************************************************************/
@@ -22,48 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: sktimer.h,v $
- *	Revision 1.11  2003/09/16 12:58:18  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.10  2003/05/13 17:56:44  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.9  1999/11/22 14:00:29  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.8  1998/09/08 08:48:02  gklug
- *	add: init level handling
- *	
- *	Revision 1.7  1998/08/20 12:31:29  gklug
- *	fix: SK_TIMCTRL needs to be defined
- *	
- *	Revision 1.6  1998/08/19 09:51:00  gklug
- *	fix: remove struct keyword from C-code (see CCC) add typedefs
- *	
- *	Revision 1.5  1998/08/17 13:43:21  gklug
- *	chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR
- *	
- *	Revision 1.4  1998/08/14 07:09:31  gklug
- *	fix: chg pAc -> pAC
- *	
- *	Revision 1.3  1998/08/07 12:54:24  gklug
- *	fix: first compiled version
- *	
- *	Revision 1.2  1998/08/07 09:35:29  gklug
- *	add: Timer control struct for Adapters context
- *	add: function prototypes
- *	
- *	Revision 1.1  1998/08/05 11:27:01  gklug
- *	First version: adapted from SMT
- *	
- *
- ******************************************************************************/
-
 /*
  * SKTIMER.H	contains all defines and types for the timer functions
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/sktypes.h linux-2.4.26-pre6/drivers/net/sk98lin/h/sktypes.h
--- linux-2.4.25/drivers/net/sk98lin/h/sktypes.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/sktypes.h	2004-03-25 00:22:28.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	sktypes.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.2 $
- * Date:	$Date: 2003/10/07 08:16:51 $
  * Purpose:	Define data types for Linux
  *
  ******************************************************************************/
@@ -22,31 +20,6 @@
  *
  ******************************************************************************/
  
- /*****************************************************************************
- *
- * History:
- *
- *	$Log: sktypes.h,v $
- *	Revision 1.2  2003/10/07 08:16:51  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.1  2003/07/21 07:26:01  rroesler
- *	Fix: Re-Enter after CVS crash
- *	
- *	Revision 1.3  2003/02/25 14:16:40  mlindner
- *	Fix: Copyright statement
- *	
- *	Revision 1.2  1999/11/22 14:01:58  cgoos
- *	Changed license header to GPL.
- *	Now using Linux' fixed size types instead of standard types.
- *	
- *	Revision 1.1  1999/02/16 07:41:40  cgoos
- *	First version.
- *	
- *	
- *
- *****************************************************************************/
-
 /******************************************************************************
  *
  * Description:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skversion.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skversion.h
--- linux-2.4.25/drivers/net/sk98lin/h/skversion.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skversion.h	2004-03-25 00:20:18.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	version.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/10/07 08:16:51 $
  * Purpose:	SK specific Error log support
  *
  ******************************************************************************/
@@ -22,42 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *	$Log: skversion.h,v $
- *	Revision 1.5  2003/10/07 08:16:51  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.4  2003/09/22 08:40:10  mlindner
- *	Add: Added DRIVER_FILE_NAME and DRIVER_REL_DATE
- *	
- *	Revision 1.3  2003/08/25 13:34:48  mlindner
- *	Fix: Lint changes
- *	
- *	Revision 1.2  2003/08/13 12:01:01  mlindner
- *	Add: Changes for Lint
- *	
- *	Revision 1.1  2003/07/24 09:29:56  rroesler
- *	Fix: Re-Enter after CVS crash
- *	
- *	Revision 1.4  2003/02/25 14:16:40  mlindner
- *	Fix: Copyright statement
- *	
- *	Revision 1.3  2003/02/25 13:30:18  mlindner
- *	Add: Support for various vendors
- *	
- *	Revision 1.1.2.1  2001/09/05 13:38:30  mlindner
- *	Removed FILE description
- *	
- *	Revision 1.1  2001/03/06 09:25:00  mlindner
- *	first version
- *	
- *	
- *
- ******************************************************************************/
- 
- 
 #ifdef	lint
 static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
 static const char SysKonnectBuildNumber[] =
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skvpd.h linux-2.4.26-pre6/drivers/net/sk98lin/h/skvpd.h
--- linux-2.4.25/drivers/net/sk98lin/h/skvpd.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/skvpd.h	2004-03-25 00:18:46.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skvpd.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/01/13 10:39:38 $
  * Purpose:	Defines and Macros for VPD handling
  *
  ******************************************************************************/
@@ -21,70 +19,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skvpd.h,v $
- *	Revision 1.15  2003/01/13 10:39:38  rschmidt
- *	Replaced define for PCI device Id for YUKON with GENESIS
- *	Editorial changes
- *	
- *	Revision 1.14  2002/11/14 15:18:10  gheinig
- *	Added const specifier to key and buf parameters for VpdPara,VpdRead
- *	and VpdWrite. This is necessary for the Diag 7 GUI API
- *	
- *	Revision 1.13  2002/10/14 15:58:18  rschmidt
- *	Added entry in rom_size struct s_vpd
- *	Editorial changes
- *	
- *	Revision 1.12  2002/09/09 14:43:51  mkarl
- *	added PCI Id of Yukon for reading VPD in diag before the adapter has
- *	been initialized
- *	editorial changes
- *	
- *	Revision 1.11  2002/07/26 13:19:16  mkarl
- *	added support for Yukon
- *	added vpd_size to VPD struct
- *	
- *	Revision 1.10  2000/08/10 11:29:07  rassmann
- *	Editorial changes.
- *	Preserving 32-bit alignment in structs for the adapter context.
- *	Removed unused function VpdWriteDword() (#if 0).
- *	Made VpdReadKeyword() available for SKDIAG only.
- *	
- *	Revision 1.9  1999/11/22 14:02:27  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.8  1999/03/11 14:26:40  malthoff
- *	Replace __STDC__ with SK_KR_PROTO.
- *	
- *	Revision 1.7  1998/10/28 07:27:17  gklug
- *	rmv: SWAP macros
- *	add: VPD_IN/OUT8 macros
- *	chg: interface definition
- *	
- *	Revision 1.6  1998/10/22 10:03:44  gklug
- *	fix: use SK_OUT16 instead of SK_OUTW
- *	
- *	Revision 1.5  1998/10/14 07:05:31  cgoos
- *	Changed constants in SK_SWAP_32 to UL.
- *	
- *	Revision 1.4  1998/08/19 08:14:09  gklug
- *	fix: remove struct keyword as much as possible from the C-code (see CCC)
- *	
- *	Revision 1.3  1998/08/18 08:18:56  malthoff
- *	Modify VPD in and out macros for SK_DIAG
- *	
- *	Revision 1.2  1998/07/03 14:49:08  malthoff
- *	Add VPD_INxx() and VPD_OUTxx() macros for the Diagnostics tool.
- *	
- *	Revision 1.1  1998/06/19 14:08:03  malthoff
- *	Created.
- *	
- *
- ******************************************************************************/
-
 /*
  * skvpd.h	contains Diagnostic specific defines for VPD handling
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/xmac_ii.h linux-2.4.26-pre6/drivers/net/sk98lin/h/xmac_ii.h
--- linux-2.4.25/drivers/net/sk98lin/h/xmac_ii.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/h/xmac_ii.h	2004-03-25 00:21:36.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	xmac_ii.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/10/02 16:35:50 $
  * Purpose:	Defines and Macros for Gigabit Ethernet Controller
  *
  ******************************************************************************/
@@ -22,207 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: xmac_ii.h,v $
- *	Revision 1.52  2003/10/02 16:35:50  rschmidt
- *	Added defines for default values of GMAC parameters
- *	Changed defines for setting GMAC parameters
- *	Editorial changes
- *	
- *	Revision 1.51  2003/09/23 09:04:27  malthoff
- *	Add bit definitions for PHY_MARV_EXT_P_STAT.
- *	
- *	Revision 1.50  2003/09/16 14:15:07  rschmidt
- *	Added defines for Extended PHY Specific Control
- *	Editorial changes
- *	
- *	Revision 1.49  2003/09/16 07:22:46  mschmid
- *	Added defines for Marvell PHY energy detect modes
- *	Added macros for MAC parameter setting in port structure
- *	
- *	Revision 1.48  2003/05/13 17:17:55  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.47  2003/03/31 07:37:25  mkarl
- *	Corrected Copyright.
- *	Editorial changes.
- *	
- *	Revision 1.46  2003/01/28 09:47:45  rschmidt
- *	Added defines for copper MDI/MDIX configuration
- *	Added defines for LED Control Register
- *	Editorial changes
- *	
- *	Revision 1.45  2002/12/10 14:35:13  rschmidt
- *	Corrected defines for Extended PHY Specific Control
- *	Added defines for Ext. PHY Specific Ctrl 2 Reg. (Fiber specific)
- *	
- *	Revision 1.44  2002/12/09 14:58:41  rschmidt
- *	Added defines for Ext. PHY Specific Ctrl Reg. (downshift feature)
- *	Added 'GMR_FS_UN_SIZE'-Bit to Rx GMAC FIFO Flush Mask
- *	
- *	Revision 1.43  2002/12/05 10:14:45  rschmidt
- *	Added define for GMAC's Half Duplex Burst Mode
- *	Added define for Rx GMAC FIFO Flush Mask (default)
- *	
- *	Revision 1.42  2002/11/12 16:48:19  rschmidt
- *	Added defines for Cable Diagnostic Register (GPHY)
- *	Editorial changes
- *	
- *	Revision 1.41  2002/10/21 11:20:22  rschmidt
- *	Added bit GMR_FS_GOOD_FC to GMR_FS_ANY_ERR
- *	Editorial changes
- *	
- *	Revision 1.40  2002/10/14 14:54:14  rschmidt
- *	Added defines for GPHY Specific Status and GPHY Interrupt Status
- *	Added bits PHY_M_IS_AN_ERROR and PHY_M_IS_FIFO_ERROR to PHY_M_DEF_MSK
- *	Editorial changes
- *	
- *	Revision 1.39  2002/10/10 15:53:44  mkarl
- *	added some bit definitions for link speed status and LED's
- *	
- *	Revision 1.38  2002/08/21 16:23:46  rschmidt
- *	Added defines for PHY Specific Ctrl Reg
- *	Editorial changes
- *	
- *	Revision 1.37  2002/08/16 14:50:33  rschmidt
- *	Added defines for Auto-Neg. Advertisement YUKON Fiber (88E1011S only)
- *	Changed define PHY_M_DEF_MSK for GPHY IRQ Mask
- *	Editorial changes
- *	
- *	Revision 1.36  2002/08/12 13:21:10  rschmidt
- *	Added defines for different Broadcom PHY Ids
- *	
- *	Revision 1.35  2002/08/08 15:58:01  rschmidt
- *	Added defines for Manual LED Override register (YUKON)
- *	Editorial changes
- *	
- *	Revision 1.34  2002/07/31 17:23:36  rwahl
- *	Added define GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR).
- *	
- *	Revision 1.33  2002/07/23 16:03:37  rschmidt
- *	Added defines for GPHY registers
- *	Editorial changes
- *	
- *	Revision 1.32  2002/07/15 18:14:37  rwahl
- *	Added GMAC MIB counters definitions.
- *	Editorial changes.
- *	
- *	Revision 1.31  2002/07/15 15:42:50  rschmidt
- *	Removed defines from PHY specific reg. which are
- *	common to all PHYs
- *	Added defines for GMAC MIB Counters
- *	Editorial changes
- *	
- *	Revision 1.30  2002/06/05 08:22:12  rschmidt
- *	Changed defines for GMAC Rx Control Register and Rx Status
- *	Editorial changes
- *	
- *	Revision 1.29  2002/04/25 11:43:56  rschmidt
- *	Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res.
- *	Added new registers and defines for YUKON (GMAC, GPHY)
- *	Added Receive Frame Status Encoding for YUKON
- *	Editorial changes
- *	
- *	Revision 1.28  2000/11/09 12:32:49  rassmann
- *	Renamed variables.
- *	
- *	Revision 1.27  2000/05/17 11:00:46  malthoff
- *	Add bit for enable/disable power management in BCOM chip.
- *	
- *	Revision 1.26  1999/11/22 14:03:00  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.25  1999/08/12 19:19:38  malthoff
- *	Add PHY_B_AC_TX_TST bit according to BCOM A1 errata sheet.
- *	
- *	Revision 1.24  1999/07/30 11:27:21  cgoos
- *	Fixed a missing end-of-comment.
- *	
- *	Revision 1.23  1999/07/30 07:03:31  malthoff
- *	Cut some long comments.
- *	Correct the XMAC PHY ID definitions.
- *	
- *	Revision 1.22  1999/05/19 07:33:18  cgoos
- *	Changes for 1000Base-T.
- *	
- *	Revision 1.21  1999/03/25 07:46:11  malthoff
- *	Add XM_HW_CFG, XM_TS_READ, and XM_TS_LOAD registers.
- *	
- *	Revision 1.20  1999/03/12 13:36:09  malthoff
- *	Remove __STDC__.
- *
- *	Revision 1.19  1998/12/10 12:22:54  gklug
- *	fix: RX_PAGE must be in interrupt mask
- *
- *	Revision 1.18  1998/12/10 10:36:36  gklug
- *	fix: swap of pause bits
- *
- *	Revision 1.17  1998/11/18 13:21:45  gklug
- *	fix: Default interrupt mask
- *
- *	Revision 1.16  1998/10/29 15:53:21  gklug
- *	fix: Default mask uses ASS (GP0) signal
- *
- *	Revision 1.15  1998/10/28 13:52:52  malthoff
- *	Add new bits in RX_CMD register.
- *
- *	Revision 1.14  1998/10/19 15:34:53  gklug
- *	fix: typos
- *
- *	Revision 1.13  1998/10/14 07:19:03  malthoff
- *	bug fix: Every define which describes bit 31
- *	must be declared as unsigned long 'UL'.
- *	fix bit definitions of PHY_AN_RFB and PHY_AN_PAUSE.
- *	Remove ANP defines. Rework the RFB defines.
- *
- *	Revision 1.12  1998/10/14 06:22:44  cgoos
- *	Changed shifted constant to ULONG.
- *
- *	Revision 1.11  1998/10/14 05:43:26  gklug
- *	add: shift pause coding
- *	fix: PAUSE bits definition
- *
- *	Revision 1.10  1998/10/13 09:19:21  malthoff
- *	Again change XMR_FS_ANY_ERR because of new info from XaQti.
- *
- *	Revision 1.9  1998/10/09 07:58:30  malthoff
- *	Add XMR_FS_FCS_ERR to XMR_FS_ANY_ERR.
- *
- *	Revision 1.8  1998/10/09 07:18:17  malthoff
- *	bug fix of a bug fix: XM_PAUSE_MODE and XM_DEF_MODE
- *	are not inverted! Bug XM_DEF_MSK is inverted.
- *
- *	Revision 1.7  1998/10/05 08:04:32  malthoff
- *	bug fix: XM_PAUSE_MODE and XM_DEF_MODE
- *	must be inverted declarations.
- *
- *	Revision 1.6  1998/09/28 13:38:18  malthoff
- *	Add default modes and masks XM_DEF_MSK,
- *	XM_PAUSE_MODE and XM_DEF_MODE
- *
- *	Revision 1.5  1998/09/16 14:42:04  malthoff
- *	Bug Fix: XM_GP_PORT is a 32 bit (not a 16 bit) register.
- *
- *	Revision 1.4  1998/08/20 14:59:47  malthoff
- *	Rework this file after reading the XaQti data sheet
- *	"Differences between Rev. B2 & Rev. C XMAC II".
- *	This file is now 100% XMAC II Rev. C complained.
- *
- *	Revision 1.3  1998/06/29 12:18:23  malthoff
- *	Correct XMR_FS_ANY_ERR definition.
- *
- *	Revision 1.2  1998/06/29 12:10:56  malthoff
- *	Add define XMR_FS_ANY_ERR.
- *
- *	Revision 1.1  1998/06/19 13:37:17  malthoff
- *	created.
- *
- *
- ******************************************************************************/
-
 #ifndef __INC_XMAC_H
 #define __INC_XMAC_H
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skaddr.c linux-2.4.26-pre6/drivers/net/sk98lin/skaddr.c
--- linux-2.4.25/drivers/net/sk98lin/skaddr.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skaddr.c	2004-03-25 00:20:29.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skaddr.c
  * Project:	Gigabit Ethernet Adapters, ADDR-Module
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/06/02 13:46:15 $
  * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
  *
  ******************************************************************************/
@@ -24,203 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skaddr.c,v $
- *	Revision 1.52  2003/06/02 13:46:15  tschilli
- *	Editorial changes.
- *	
- *	Revision 1.51  2003/05/13 17:12:43  mkarl
- *	Changes for SLIM Driver via SK_SLIM.
- *	Changes for driver not using RLMT via SK_NO_RLMT.
- *	Changes for driver not supporting MAC address override via SK_NO_MAO.
- *	Separeted GENESIS and YUKON only code to reduce code size.
- *	Editorial changes.
- *	
- *	Revision 1.50  2003/05/08 12:29:31  rschmidt
- *	Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
- *	Changed initialisation for Next0[SK_MAX_MACS] to avoid
- *	compiler errors when SK_MAX_MACS=1.
- *	Editorial changes.
- *	
- *	Revision 1.49  2003/04/15 09:30:51  tschilli
- *	Copyright messages changed.
- *	"#error C++ is not yet supported." removed.
- *	
- *	Revision 1.48  2003/02/12 17:09:37  tschilli
- *	Fix in SkAddrOverride() to set both (physical and logical) MAC addresses
- *	in case that both addresses are identical.
- *	
- *	Revision 1.47  2002/09/17 06:31:10  tschilli
- *	Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate()
- *	and SkAddrGmacPromiscuousChange() fixed.
- *	Editorial changes.
- *	
- *	Revision 1.46  2002/08/22 07:55:41  tschilli
- *	New function SkGmacMcHash() for GMAC multicast hashing algorithm added.
- *	Editorial changes.
- *	
- *	Revision 1.45  2002/08/15 12:29:35  tschilli
- *	SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed.
- *	
- *	Revision 1.44  2002/08/14 12:18:03  rschmidt
- *	Replaced direct handling of MAC Hashing (XMAC and GMAC)
- *	with routine SkMacHashing().
- *	Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode().
- *	
- *	Revision 1.43  2002/08/13 09:37:43  rschmidt
- *	Corrected some SK_DBG_MSG outputs.
- *	Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode().
- *	Editorial changes.
- *	
- *	Revision 1.42  2002/08/12 11:24:36  rschmidt
- *	Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit().
- *	Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC)
- *	with routine SkMacPromiscMode().
- *	Editorial changes.
- *	
- *	Revision 1.41  2002/06/10 13:52:18  tschilli
- *	Changes for handling YUKON.
- *	All changes are internally and not visible to the programmer
- *	using this module.
- *	
- *	Revision 1.40  2001/02/14 14:04:59  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.39  2001/01/30 10:30:04  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.38  2001/01/25 16:26:52  rassmann
- *	Ensured that logical address overrides are done on net's active port.
- *	
- *	Revision 1.37  2001/01/22 13:41:34  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.36  2000/08/07 11:10:39  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.35  2000/05/04 09:38:41  rassmann
- *	Editorial changes.
- *	Corrected multicast address hashing.
- *	
- *	Revision 1.34  1999/11/22 13:23:44  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.33  1999/05/28 10:56:06  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.32  1999/03/31 10:59:20  rassmann
- *	Returning Success instead of DupAddr if address shall be overridden
- *	with same value.
- *	
- *	Revision 1.31  1999/01/14 16:18:17  rassmann
- *	Corrected multicast initialization.
- *	
- *	Revision 1.30  1999/01/04 10:30:35  rassmann
- *	SkAddrOverride only possible after SK_INIT_IO phase.
- *	
- *	Revision 1.29  1998/12/29 13:13:10  rassmann
- *	An address override is now preserved in the SK_INIT_IO phase.
- *	All functions return an int now.
- *	Extended parameter checking.
- *	
- *	Revision 1.28  1998/12/01 11:45:53  rassmann
- *	Code cleanup.
- *	
- *	Revision 1.27  1998/12/01 09:22:49  rassmann
- *	SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT
- *	too often.
- *	
- *	Revision 1.26  1998/11/24 12:39:44  rassmann
- *	Reserved multicast entry for BPDU address.
- *	13 multicast entries left for protocol.
- *	
- *	Revision 1.25  1998/11/17 16:54:23  rassmann
- *	Using exact match for up to 14 multicast addresses.
- *	Still receiving all multicasts if more addresses are added.
- *	
- *	Revision 1.24  1998/11/13 17:24:31  rassmann
- *	Changed return value of SkAddrOverride to int.
- *	
- *	Revision 1.23  1998/11/13 16:56:18  rassmann
- *	Added macro SK_ADDR_COMPARE.
- *	Changed return type of SkAddrOverride to SK_BOOL.
- *	
- *	Revision 1.22  1998/11/04 17:06:17  rassmann
- *	Corrected McUpdate and PromiscuousChange functions.
- *	
- *	Revision 1.21  1998/10/29 14:34:04  rassmann
- *	Clearing SK_ADDR struct at startup.
- *	
- *	Revision 1.20  1998/10/28 18:16:34  rassmann
- *	Avoiding I/Os before SK_INIT_RUN level.
- *	Aligning InexactFilter.
- *	
- *	Revision 1.19  1998/10/28 11:29:28  rassmann
- *	Programming physical address in SkAddrMcUpdate.
- *	Corrected programming of exact match entries.
- *	
- *	Revision 1.18  1998/10/28 10:34:48  rassmann
- *	Corrected reading of physical addresses.
- *	
- *	Revision 1.17  1998/10/28 10:26:13  rassmann
- *	Getting ports' current MAC addresses from EPROM now.
- *	Added debug output.
- *	
- *	Revision 1.16  1998/10/27 16:20:12  rassmann
- *	Reading MAC address byte by byte.
- *	
- *	Revision 1.15  1998/10/22 11:39:09  rassmann
- *	Corrected signed/unsigned mismatches.
- *	
- *	Revision 1.14  1998/10/19 17:12:35  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.13  1998/10/19 17:02:19  rassmann
- *	Now reading permanent MAC addresses from CRF.
- *	
- *	Revision 1.12  1998/10/15 15:15:48  rassmann
- *	Changed Flags Parameters from SK_U8 to int.
- *	Checked with lint.
- *	
- *	Revision 1.11  1998/09/24 19:15:12  rassmann
- *	Code cleanup.
- *	
- *	Revision 1.10  1998/09/18 20:18:54  rassmann
- *	Added HW access.
- *	Implemented swapping.
- *	
- *	Revision 1.9  1998/09/16 11:32:00  rassmann
- *	Including skdrv1st.h again. :(
- *	
- *	Revision 1.8  1998/09/16 11:09:34  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.7  1998/09/14 17:06:34  rassmann
- *	Minor changes.
- *	
- *	Revision 1.6  1998/09/07 08:45:41  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.5  1998/09/04 19:40:19  rassmann
- *	Interface enhancements.
- *	
- *	Revision 1.4  1998/09/04 12:14:12  rassmann
- *	Interface cleanup.
- *	
- *	Revision 1.3  1998/09/02 16:56:40  rassmann
- *	Updated interface.
- *	
- *	Revision 1.2  1998/08/27 14:26:09  rassmann
- *	Updated interface.
- *	
- *	Revision 1.1  1998/08/21 08:30:22  rassmann
- *	First public version.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This module is intended to manage multicast addresses, address override,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skcsum.c linux-2.4.26-pre6/drivers/net/sk98lin/skcsum.c
--- linux-2.4.25/drivers/net/sk98lin/skcsum.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skcsum.c	2004-03-25 00:17:10.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skcsum.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.12 $
- * Date:	$Date: 2003/08/20 13:55:53 $
  * Purpose:	Store/verify Internet checksum in send/receive packets.
  *
  ******************************************************************************/
@@ -21,63 +19,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skcsum.c,v $
- *	Revision 1.12  2003/08/20 13:55:53  mschmid
- *	Changed notation of #ifndef SkCsCalculateChecksum to
- *	#ifndef SK_CS_CALCULATE_CHECKSUM
- *	
- *	Revision 1.11  2003/03/11 14:05:55  rschmidt
- *	Replaced memset() by macro SK_MEMSET()
- *	Editorial changes
- *	
- *	Revision 1.10  2002/04/11 10:02:04  rwahl
- *	Fix in SkCsGetSendInfo():
- *	- function did not return ProtocolFlags in every case.
- *	- pseudo header csum calculated wrong for big endian.
- *	
- *	Revision 1.9  2001/06/13 07:42:08  gklug
- *	fix: NetNumber was wrong in CLEAR_STAT event
- *	add: check for good NetNumber in Clear STAT
- *	
- *	Revision 1.8  2001/02/06 11:15:36  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.7  2000/06/29 13:17:05  rassmann
- *	Corrected reception of a packet with UDP checksum == 0 (which means there
- *	is no UDP checksum).
- *	
- *	Revision 1.6  2000/02/21 12:35:10  cgoos
- *	Fixed license header comment.
- *	
- *	Revision 1.5  2000/02/21 11:05:19  cgoos
- *	Merged changes back to common source.
- *	Fixed rx path for BIG ENDIAN architecture.
- *	
- *	Revision 1.1  1999/07/26 15:28:12  mkarl
- *	added return SKCS_STATUS_IP_CSUM_ERROR_UDP and
- *	SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester
- *	changed from common source to windows specific source
- *	therefore restarting with v1.0
- *	
- *	Revision 1.3  1999/05/10 08:39:33  mkarl
- *	prevent overflows in SKCS_HTON16
- *	fixed a bug in pseudo header checksum calculation
- *	added some comments
- *	
- *	Revision 1.2  1998/10/22 11:53:28  swolf
- *	Now using SK_DBG_MSG.
- *	
- *	Revision 1.1  1998/09/01 15:35:41  swolf
- *	initial revision
- *
- *	13-May-1998 sw	Created.
- *
- ******************************************************************************/
-
 #ifdef SK_USE_CSUM	/* Check if CSUM is to be used. */
 
 #ifndef lint
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skdim.c linux-2.4.26-pre6/drivers/net/sk98lin/skdim.c
--- linux-2.4.25/drivers/net/sk98lin/skdim.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skdim.c	2004-03-25 00:21:58.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skdim.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/11/28 12:55:40 $
  * Purpose:	All functions to maintain interrupt moderation
  *
  ******************************************************************************/
@@ -24,40 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *	
- *	$Log: skdim.c,v $
- *	Revision 1.5  2003/11/28 12:55:40  rroesler
- *	Fix: support for new process timing interface added
- *	
- *	Revision 1.4  2003/10/10 10:58:56  mlindner
- *	Fix: CPU detection under the kernel 2.6
- *	
- *	Revision 1.3  2003/10/07 08:17:08  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.2  2003/08/21 12:35:05  mlindner
- *	Fix: Corrected CPU detection and compile errors on single CPU machines
- *	
- *	Revision 1.1  2003/07/18 13:39:55  rroesler
- *	Fix: Re-enter after CVS crash
- *	
- *	Revision 1.4  2003/07/07 09:45:47  rroesler
- *	Fix: Compiler warnings corrected
- *	
- *	Revision 1.3  2003/06/10 09:16:40  rroesler
- *	Adapt GetCurrentSystemLoad() to NOT access the kernels
- *	kstat-structure in kernel 2.5/2.6. This must be done
- *	due to a not exported symbol. Instead of evaluating the
- *	SystemLoad directly, the nbr of interrupts is used as
- *	a rough basis for the load.
- *	
- *
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This module is intended to manage the dynamic interrupt moderation on both   
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skge.c linux-2.4.26-pre6/drivers/net/sk98lin/skge.c
--- linux-2.4.25/drivers/net/sk98lin/skge.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skge.c	2004-03-25 00:17:51.000000000 +0000
@@ -38,423 +38,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skge.c,v $
- *	Revision 1.43  2004/01/29 15:47:07  mlindner
- *	Fix: Reset Xmac when stopping the port
- *	
- *	Revision 1.42  2003/12/12 10:05:43  mlindner
- *	Fix: Format of error message corrected
- *	
- *	Revision 1.41  2003/12/11 16:03:57  mlindner
- *	Fix: Create backup from pnmi data structure
- *	
- *	Revision 1.40  2003/12/11 12:14:48  mlindner
- *	Fix: Initalize Board before network configuration
- *	Fix: Change device names to driver name
- *	
- *	Revision 1.39  2003/12/10 08:57:38  rroesler
- *	Fix: Modifications regarding try_module_get() and capable()
- *	
- *	Revision 1.38  2003/12/01 17:16:50  mlindner
- *	Fix: Remove useless register_netdev
- *	
- *	Revision 1.37  2003/12/01 17:11:30  mlindner
- *	Fix: Register net device before SkGeBoardInit
- *	
- *	Revision 1.36  2003/11/28 13:04:27  rroesler
- *	Fix: do not print interface status in case DIAG is used
- *	
- *	Revision 1.35  2003/11/17 14:41:06  mlindner
- *	Fix: Endif command
- *	
- *	Revision 1.34  2003/11/17 13:29:05  mlindner
- *	Fix: Editorial changes
- *	
- *	Revision 1.33  2003/11/14 14:56:54  rroesler
- *	Fix: corrected compilation warnings kernel 2.2
- *	
- *	Revision 1.32  2003/11/13 14:18:47  rroesler
- *	Fix: added latest changes regarding the use of the proc system
- *	
- *	Revision 1.31  2003/11/13 09:28:35  rroesler
- *	Fix: removed kernel warning 'driver changed get_stats after register'
- *	
- *	Revision 1.30  2003/11/11 13:15:27  rroesler
- *	Fix: use suitables kernel usage count macros when using the diag
- *	
- *	Revision 1.29  2003/11/10 09:38:26  rroesler
- *	Fix: restore PNMI structure backup for DIAG actions
- *	
- *	Revision 1.28  2003/11/07 17:28:45  rroesler
- *	Fix: Additions for the LeaveDiagMode
- *	
- *	Revision 1.27  2003/11/03 13:21:14  mlindner
- *	Add: SkGeBuffPad function for padding to ensure the trailing bytes exist
- *	
- *	Revision 1.26  2003/10/30 09:20:40  mlindner
- *	Fix: Control bit check
- *	
- *	Revision 1.25  2003/10/29 07:43:37  rroesler
- *	Fix: Implemented full None values handling for parameter Moderation
- *	
- *	Revision 1.24  2003/10/22 14:18:12  rroesler
- *	Fix: DIAG handling for DualNet cards
- *	
- *	Revision 1.23  2003/10/17 10:05:13  mlindner
- *	Add: New blinkmode for Morvell cards
- *	
- *	Revision 1.22  2003/10/15 12:31:25  rroesler
- *	Fix: Corrected bugreport #10954 (Linux System crash when using vlans)
- *	
- *	Revision 1.21  2003/10/07 12:32:28  mlindner
- *	Fix: Editorial changes
- *	
- *	Revision 1.20  2003/10/07 12:22:40  mlindner
- *	Fix: Compiler warnings
- *	
- *	Revision 1.19  2003/10/07 09:33:40  mlindner
- *	Fix: No warnings for illegal values of Mod and IntsPerSec
- *	Fix: Speed 100 in Half Duplex not allowed for Yukon
- *	Fix: PrefPort=B not allowed on single NICs
- *	
- *	Revision 1.18  2003/10/07 08:17:08  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.17  2003/09/29 12:06:59  mlindner
- *	*** empty log message ***
- *	
- *	Revision 1.16  2003/09/23 11:07:35  mlindner
- *	Fix: IO-control return race condition
- *	Fix: Interrupt moderation value check
- *	
- *	Revision 1.15  2003/09/22 08:40:05  mlindner
- *	Add: Added DRIVER_FILE_NAME and DRIVER_REL_DATE
- *	
- *	Revision 1.14  2003/09/22 08:11:10  mlindner
- *	Add: New function for PCI initialization (SkGeInitPCI)
- *	Add: Yukon Plus changes (ChipID, PCI...)
- *	Fix: TCP and UDP Checksum calculation
- *	
- *	Revision 1.13  2003/09/01 13:30:08  rroesler
- *	Fix: Corrected missing defines
- *	
- *	Revision 1.12  2003/09/01 13:12:02  rroesler
- *	Add: Code for improved DIAG Attach/Detach interface
- *	
- *	Revision 1.11  2003/08/26 16:05:19  mlindner
- *	Fix: Compiler warnings (void *)
- *	
- *	Revision 1.10  2003/08/25 09:24:08  mlindner
- *	Add: Dynamic Interrupt Moderation (DIM) port up message
- *	
- *	Revision 1.9  2003/08/21 14:09:43  mlindner
- *	Fix: Disable Half Duplex with Gigabit-Speed (Yukon). Enable Full Duplex.
- *	
- *	Revision 1.8  2003/08/19 15:09:18  mlindner
- *	Fix: Ignore ConType parameter if empty value
- *	
- *	Revision 1.7  2003/08/13 12:00:35  mlindner
- *	Fix: Removed useless defines
- *	
- *	Revision 1.6  2003/08/12 16:49:41  mlindner
- *	Fix: UDP and TCP HW-CSum calculation (Kernel 2.5/2.6)
- *	Fix: UDP and TCP Proto checks
- *	Fix: Build without ProcFS
- *	Fix: Kernel 2.6 editorial changes
- *	
- *	Revision 1.5  2003/08/07 12:25:07  mlindner
- *	Fix: ConType parameter check and error detection
- *	Fix: Insert various fixes applied to the kernel tree
- *	
- *	Revision 1.4  2003/08/07 10:50:21  mlindner
- *	Add: Speed and HW-Csum support for Yukon Lite chipset
- *	
- *	Revision 1.3  2003/08/06 11:24:08  mlindner
- *	Add: Kernel updates
- *	
- *	Revision 1.2  2003/07/21 08:28:47  rroesler
- *	Fix: Handle padded bytes using skb_put()
- *	
- *	Revision 1.63  2003/07/15 09:26:23  rroesler
- *	Fix: Removed memory leak when sending short padded frames
- *	
- *	Revision 1.62  2003/07/09 11:11:16  rroesler
- *	Fix: Call of ReceiveIrq() performed with parameter SK_FALSE in
- *	     order not to hang the system with multiple spinlocks
- *	
- *	Revision 1.61  2003/07/08 07:32:41  rroesler
- *	Fix: Correct Kernel-version
- *	
- *	Revision 1.60  2003/07/07 15:42:30  rroesler
- *	Fix: Removed function pci_present() for 2.5/2.6 kernels (deprecated)
- *	Fix: Corrected warning in GetConfiguration()
- *	
- *	Revision 1.59  2003/07/07 09:44:32  rroesler
- *	Add: HW checksumming on kernel 2.5/2.6
- *	Add: padding of short frames (<60 bytes) with 0x00 instead of 0xaa
- *	Add: ConType parameter combining multiple other parameters into one
- *	Fix: Corrected bugreport #10721 (warning when changing MTU size)
- *	Fix: Removed obsolete function SetQueueSize()
- *	Fix: Function ChangeMtuSize() returns new MTU size in kernel 2.5/2.6
- *	
- *	Revision 1.58  2003/06/17 07:14:29  mlindner
- *	Add: Disable checksum functionality
- *	Fix: Unload module (Kernel 2.5)
- *	
- *	Revision 1.57  2003/06/05 14:55:27  mlindner
- *	Fix: ProcFS creation (Kernel 2.2.x)
- *	Fix: ProcFS OWNER (Kernel 2.2.x)
- *	
- *	Revision 1.56  2003/06/03 14:34:29  mlindner
- *	Add: Additions for SK_SLIM
- *	Fix: SkGeIoctl SK_IOCTL_GEN
- *	
- *	Revision 1.55  2003/05/26 13:00:52  mlindner
- *	Add: Support for Kernel 2.5/2.6
- *	Add: Support for new IO-control MIB data structure
- *	Add: New SkOsGetTime function
- *	Fix: Race condition with broken LM80 chip
- *	Fix: Race condition with padded frames
- *	
- *	Revision 1.54  2003/04/28 13:07:27  mlindner
- *	Fix: Delay race condition with some server machines
- *	
- *	Revision 1.53  2003/04/28 12:49:49  mlindner
- *	Fix: Code optimization
- *	
- *	Revision 1.52  2003/04/28 12:24:32  mlindner
- *	Fix: Disabled HW Error IRQ on 32-bit Yukon if sensor IRQ occurs
- *	
- *	Revision 1.51  2003/04/16 08:31:14  mlindner
- *	Fix: Kernel 2.2 compilation
- *	
- *	Revision 1.49  2003/04/10 09:08:51  mlindner
- *	Add: Blink mode verification
- *	Fix: Checksum calculation
- *	
- *	Revision 1.48  2003/03/21 14:48:38  rroesler
- *	Added code for interrupt moderation
- *	
- *	Revision 1.47  2003/03/12 13:56:15  mlindner
- *	Fix: Mac update during SK_DRV_NET_UP
- *	
- *	Revision 1.46  2003/02/25 14:16:36  mlindner
- *	Fix: Copyright statement
- *	
- *	Revision 1.45  2003/02/25 13:25:55  mlindner
- *	Add: Performance improvements
- *	Add: Support for various vendors
- *	Fix: Init function
- *	
- *	Revision 1.44  2003/01/09 09:25:26  mlindner
- *	Fix: Remove useless init_module/cleanup_module forward declarations
- *	
- *	Revision 1.43  2002/11/29 08:42:41  mlindner
- *	Fix: Boot message
- *	
- *	Revision 1.42  2002/11/28 13:30:23  mlindner
- *	Add: New frame check
- *	
- *	Revision 1.41  2002/11/27 13:55:18  mlindner
- *	Fix: Drop wrong csum packets
- *	Fix: Initialize proc_entry after hw check
- *	
- *	Revision 1.40  2002/10/31 07:50:37  tschilli
- *	Function SkGeInitAssignRamToQueues() from common module inserted.
- *	Autonegotiation is set to ON for all adapters.
- *	LinkSpeedUsed is used in link up status report.
- *	Role parameter will show up for 1000 Mbps links only.
- *	GetConfiguration() inserted after init level 1 in SkGeChangeMtu().
- *	All return values of SkGeInit() and SkGeInitPort() are checked.
- *	
- *	Revision 1.39  2002/10/02 12:56:05  mlindner
- *	Add: Support for Yukon
- *	Add: Support for ZEROCOPY, scatter-gather and hw checksum
- *	Add: New transmit ring function (use SG and TCP/UDP hardware checksumming)
- *	Add: New init function
- *	Add: Speed check and setup
- *	Add: Merge source for kernel 2.2.x and 2.4.x
- *	Add: Opcode check for tcp
- *	Add: Frame length check
- *	Fix: Transmit complete interrupt
- *	Fix: Interrupt moderation
- *	
- *	Revision 1.29.2.13  2002/01/14 12:44:52  mlindner
- *	Fix: Rlmt modes
- *	
- *	Revision 1.29.2.12  2001/12/07 12:06:18  mlindner
- *	Fix: malloc -> slab changes
- *	
- *	Revision 1.29.2.11  2001/12/06 15:19:20  mlindner
- *	Add: DMA attributes
- *	Fix: Module initialisation
- *	Fix: pci_map_single and pci_unmap_single replaced
- *	
- *	Revision 1.29.2.10  2001/12/06 09:56:50  mlindner
- *	Corrected some printk's
- *	
- *	Revision 1.29.2.9  2001/09/05 12:15:34  mlindner
- *	Add: LBFO Changes
- *	Fix: Counter Errors (Jumbo == to long errors)
- *	Fix: Changed pAC->PciDev declaration
- *	Fix: too short counters
- *	
- *	Revision 1.29.2.8  2001/06/25 12:10:44  mlindner
- *	fix: ReceiveIrq() changed.
- *	
- *	Revision 1.29.2.7  2001/06/25 08:07:05  mlindner
- *	fix: RLMT locking in ReceiveIrq() changed.
- *	
- *	Revision 1.29.2.6  2001/05/21 07:59:29  mlindner
- *	fix: MTU init problems
- *	
- *	Revision 1.29.2.5  2001/05/08 11:25:08  mlindner
- *	fix: removed VLAN error message
- *	
- *	Revision 1.29.2.4  2001/05/04 13:31:43  gklug
- *	fix: do not handle eth_copy on bad fragments received.
- *	
- *	Revision 1.29.2.3  2001/04/23 08:06:43  mlindner
- *	Fix: error handling
- *	
- *	Revision 1.29.2.2  2001/03/15 12:04:54  mlindner
- *	Fixed memory problem
- *	
- *	Revision 1.29.2.1  2001/03/12 16:41:44  mlindner
- *	add: procfs function
- *	add: dual-net function
- *	add: RLMT networks
- *	add: extended PNMI features
- *	
- *	Kernel 2.4.x specific:
- *	Revision 1.xx  2000/09/12 13:31:56  cgoos
- *	Fixed missign "dev=NULL in skge_probe.
- *	Added counting for jumbo frames (corrects error statistic).
- *	Removed VLAN tag check (enables VLAN support).
- *	
- *	Kernel 2.2.x specific:
- *	Revision 1.29  2000/02/21 13:31:56  cgoos
- *	Fixed "unused" warning for UltraSPARC change.
- *	
- *	Partially kernel 2.2.x specific:
- *	Revision 1.28  2000/02/21 10:32:36  cgoos
- *	Added fixes for UltraSPARC.
- *	Now printing RlmtMode and PrefPort setting at startup.
- *	Changed XmitFrame return value.
- *	Fixed rx checksum calculation for BIG ENDIAN systems.
- *	Fixed rx jumbo frames counted as ierrors.
- *	
- *	
- *	Revision 1.27  1999/11/25 09:06:28  cgoos
- *	Changed base_addr to unsigned long.
- *	
- *	Revision 1.26  1999/11/22 13:29:16  cgoos
- *	Changed license header to GPL.
- *	Changes for inclusion in linux kernel (2.2.13).
- *	Removed 2.0.x defines.
- *	Changed SkGeProbe to skge_probe.
- *	Added checks in SkGeIoctl.
- *	
- *	Revision 1.25  1999/10/07 14:47:52  cgoos
- *	Changed 984x to 98xx.
- *	
- *	Revision 1.24  1999/09/30 07:21:01  cgoos
- *	Removed SK_RLMT_SLOW_LOOKAHEAD option.
- *	Giving spanning tree packets also to OS now.
- *	
- *	Revision 1.23  1999/09/29 07:36:50  cgoos
- *	Changed assignment for IsBc/IsMc.
- *	
- *	Revision 1.22  1999/09/28 12:57:09  cgoos
- *	Added CheckQueue also to Single-Port-ISR.
- *	
- *	Revision 1.21  1999/09/28 12:42:41  cgoos
- *	Changed parameter strings for RlmtMode.
- *	
- *	Revision 1.20  1999/09/28 12:37:57  cgoos
- *	Added CheckQueue for fast delivery of RLMT frames.
- *	
- *	Revision 1.19  1999/09/16 07:57:25  cgoos
- *	Copperfield changes.
- *	
- *	Revision 1.18  1999/09/03 13:06:30  cgoos
- *	Fixed RlmtMode=CheckSeg bug: wrong DEV_KFREE_SKB in RLMT_SEND caused
- *	double allocated skb's.
- *	FrameStat in ReceiveIrq was accessed via wrong Rxd.
- *	Queue size for async. standby Tx queue was zero.
- *	FillRxLimit of 0 could cause problems with ReQueue, changed to 1.
- *	Removed debug output of checksum statistic.
- *	
- *	Revision 1.17  1999/08/11 13:55:27  cgoos
- *	Transmit descriptor polling was not reenabled after SkGePortInit.
- *	
- *	Revision 1.16  1999/07/27 15:17:29  cgoos
- *	Added some "\n" in output strings (removed while debuging...).
- *	
- *	Revision 1.15  1999/07/23 12:09:30  cgoos
- *	Performance optimization, rx checksumming, large frame support.
- *	
- *	Revision 1.14  1999/07/14 11:26:27  cgoos
- *	Removed Link LED settings (now in RLMT).
- *	Added status output at NET UP.
- *	Fixed SMP problems with Tx and SWITCH running in parallel.
- *	Fixed return code problem at RLMT_SEND event.
- *	
- *	Revision 1.13  1999/04/07 10:11:42  cgoos
- *	Fixed Single Port problems.
- *	Fixed Multi-Adapter problems.
- *	Always display startup string.
- *	
- *	Revision 1.12  1999/03/29 12:26:37  cgoos
- *	Reversed locking to fine granularity.
- *	Fixed skb double alloc problem (caused by incorrect xmit return code).
- *	Enhanced function descriptions.
- *	
- *	Revision 1.11  1999/03/15 13:10:51  cgoos
- *	Changed device identifier in output string to ethX.
- *	
- *	Revision 1.10  1999/03/15 12:12:34  cgoos
- *	Changed copyright notice.
- *	
- *	Revision 1.9  1999/03/15 12:10:17  cgoos
- *	Changed locking to one driver lock.
- *	Added check of SK_AC-size (for consistency with library).
- *	
- *	Revision 1.8  1999/03/08 11:44:02  cgoos
- *	Fixed missing dev->tbusy in SkGeXmit.
- *	Changed large frame (jumbo) buffer number.
- *	Added copying of short frames.
- *	
- *	Revision 1.7  1999/03/04 13:26:57  cgoos
- *	Fixed spinlock calls for SMP.
- *	
- *	Revision 1.6  1999/03/02 09:53:51  cgoos
- *	Added descriptor revertion for big endian machines.
- *	
- *	Revision 1.5  1999/03/01 08:50:59  cgoos
- *	Fixed SkGeChangeMtu.
- *	Fixed pci config space accesses.
- *	
- *	Revision 1.4  1999/02/18 15:48:44  cgoos
- *	Corrected some printk's.
- *	
- *	Revision 1.3  1999/02/18 12:45:55  cgoos
- *	Changed SK_MAX_CARD_PARAM to default 16
- *	
- *	Revision 1.2  1999/02/18 10:55:32  cgoos
- *	Removed SkGeDrvTimeStamp function.
- *	Printing "ethX:" before adapter type at adapter init.
- *	
- *
- *	10-Feb-1999 cg	Created, based on Linux' acenic.c, 3c59x.c and
- *			SysKonnects GEnesis Solaris driver
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Possible compiler options (#define xxx / -Dxxx):
  *
  *	debugging can be enable by changing SK_DEBUG_CHKMOD and
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skgehwt.c linux-2.4.26-pre6/drivers/net/sk98lin/skgehwt.c
--- linux-2.4.25/drivers/net/sk98lin/skgehwt.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skgehwt.c	2004-03-25 00:21:53.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgehwt.c
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/09/16 13:41:23 $
  * Purpose:	Hardware Timer
  *
  ******************************************************************************/
@@ -22,60 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgehwt.c,v $
- *	Revision 1.15  2003/09/16 13:41:23  rschmidt
- *	Added (C) Marvell to SysKonnectFileId
- *	Editorial changes
- *	
- *	Revision 1.14  2003/05/13 18:01:58  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.13  1999/11/22 13:31:12  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.12  1998/10/15 15:11:34  gklug
- *	fix: ID_sccs to SysKonnectFileId
- *	
- *	Revision 1.11  1998/10/08 15:27:51  gklug
- *	chg: correction factor is host clock dependent
- *	
- *	Revision 1.10  1998/09/15 14:18:31  cgoos
- *	Changed more BOOLEANs to SK_xxx
- *
- *	Revision 1.9  1998/09/15 14:16:06  cgoos
- *	Changed line 107: FALSE to SK_FALSE
- *	
- *	Revision 1.8  1998/08/24 13:04:44  gklug
- *	fix: typo
- *	
- *	Revision 1.7  1998/08/19 09:50:49  gklug
- *	fix: remove struct keyword from c-code (see CCC) add typedefs
- *	
- *	Revision 1.6  1998/08/17 09:59:02  gklug
- *	fix: typos
- *	
- *	Revision 1.5  1998/08/14 07:09:10  gklug
- *	fix: chg pAc -> pAC
- *	
- *	Revision 1.4  1998/08/10 14:14:52  gklug
- *	rmv: unneccessary SK_ADDR macro
- *	
- *	Revision 1.3  1998/08/07 12:53:44  gklug
- *	fix: first compiled version
- *	
- *	Revision 1.2  1998/08/07 09:19:29  gklug
- *	adapt functions to the C coding conventions
- *	rmv unneccessary functions.
- *	
- *	Revision 1.1  1998/08/05 11:28:36  gklug
- *	first version: adapted from SMT/FDDI
- *
- ******************************************************************************/
-
 /*
  *	Event queue and dispatcher
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skgeinit.c linux-2.4.26-pre6/drivers/net/sk98lin/skgeinit.c
--- linux-2.4.25/drivers/net/sk98lin/skgeinit.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skgeinit.c	2004-03-25 00:20:09.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgeinit.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.97 $
- * Date:	$Date: 2003/10/02 16:45:31 $
  * Purpose:	Contains functions to initialize the adapter
  *
  ******************************************************************************/
@@ -22,446 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgeinit.c,v $
- *	Revision 1.97  2003/10/02 16:45:31  rschmidt
- *	Replaced default values of GMAC parameters with defines.
- *	Removed hard reset of MACs in SkGeDeInit().
- *	Added define SK_PHY_LP_MODE around power saving mode in SkGeDeInit().
- *	Added check for VAUX available before switch power to VAUX.
- *	
- *	Revision 1.96  2003/09/18 14:02:41  rroesler
- *	Add: Perform a hardreset of MACs in GeDeInit()
- *	
- *	Revision 1.95  2003/09/16 14:26:59  rschmidt
- *	Added switch power to VCC (WA for VAUX problem) in SkGeInit1().
- *	Fixed setting PHY to coma mode and D3 power state in SkGeDeInit().
- *	Editorial changes.
- *	
- *	Revision 1.94  2003/09/16 07:17:10  mschmid
- *	Added init for new members in port structure for MAC control
- *	- PMacColThres
- *	- PMacJamLen
- *	- PMacJamIpgVal
- *	- PMacJamIpgData
- *	- PMacIpgData
- *	- PMacLimit4
- *	Added init for PHY power state in port structure
- *	- PPhyPowerState
- *	Added shutdown handling for Yukon Plus in SkGeDeInit()
- *	
- *	Revision 1.93  2003/05/28 15:44:43  rschmidt
- *	Added check for chip Id on WOL WA for chip Rev. A.
- *	Added setting of GILevel in SkGeDeInit().
- *	Minor changes to avoid LINT warnings.
- *	Editorial changes.
- *	
- *	Revision 1.92  2003/05/13 17:42:26  mkarl
- *	Added SK_FAR for PXE.
- *	Separated code pathes not used for SLIM driver to reduce code size.
- *	Removed calls to I2C for SLIM driver.
- *	Removed currently unused function SkGeLoadLnkSyncCnt.
- *	Editorial changes.
- *	
- *	Revision 1.91  2003/05/06 12:21:48  rschmidt
- *	Added use of pAC->GIni.GIYukon for selection of YUKON branches.
- *	Added defines around GENESIS resp. YUKON branches to reduce
- *	code size for PXE.
- *	Editorial changes.
- *	
- *	Revision 1.90  2003/04/28 09:12:20  rschmidt
- *	Added init for GIValIrqMask (common IRQ mask).
- *	Disabled HW Error IRQ on Yukon if sensor IRQ is set in SkGeInit1()
- *	by changing the common mask stored in GIValIrqMask.
- *	Editorial changes.
- *	
- *	Revision 1.89  2003/04/10 14:33:10  rschmidt
- *	Fixed alignement error of patchable configuration parameter
- *	in struct OemConfig caused by length of recognition string.
- *	
- *	Revision 1.88  2003/04/09 12:59:45  rschmidt
- *	Added define around initialization of patchable OEM specific
- *	configuration parameter.
- *	
- *	Revision 1.87  2003/04/08 16:46:13  rschmidt
- *	Added configuration variable for OEMs and initialization for
- *	GILedBlinkCtrl (LED Blink Control).
- *	Improved detection for YUKON-Lite Rev. A1.
- *	Editorial changes.
- *	
- *	Revision 1.86  2003/03/31 06:53:13  mkarl
- *	Corrected Copyright.
- *	Editorial changes.
- *	
- *	Revision 1.85  2003/02/05 15:30:33  rschmidt
- *	Corrected setting of GIHstClkFact (Host Clock Factor) and
- *	GIPollTimerVal (Descr. Poll Timer Init Value) for YUKON.
- *	Editorial changes.
- *	
- *	Revision 1.84  2003/01/28 09:57:25  rschmidt
- *	Added detection of YUKON-Lite Rev. A0 (stored in GIYukonLite).
- *	Disabled Rx GMAC FIFO Flush for YUKON-Lite Rev. A0.
- *	Added support for CLK_RUN (YUKON-Lite).
- *	Added additional check of PME from D3cold for setting GIVauxAvail.
- *	Editorial changes.
- *	
- *	Revision 1.83  2002/12/17 16:15:41  rschmidt
- *	Added default setting of PhyType (Copper) for YUKON.
- *	Added define around check for HW self test results.
- *	Editorial changes.
- *	
- *	Revision 1.82  2002/12/05 13:40:21  rschmidt
- *	Added setting of Rx GMAC FIFO Flush Mask register.
- *	Corrected PhyType with new define SK_PHY_MARV_FIBER when
- *	YUKON Fiber board was found.
- *	Editorial changes.
- *	
- *	Revision 1.81  2002/11/15 12:48:35  rschmidt
- *	Replaced message SKERR_HWI_E018 with SKERR_HWI_E024 for Rx queue error
- *	in SkGeStopPort().
- *	Added init for pAC->GIni.GIGenesis with SK_FALSE in YUKON-branch.
- *	Editorial changes.
- *	
- *	Revision 1.80  2002/11/12 17:28:30  rschmidt
- *	Initialized GIPciSlot64 and GIPciClock66 in SkGeInit1().
- *	Reduced PCI FIFO watermarks for 32bit/33MHz bus in SkGeInitBmu().
- *	Editorial changes.
- *	
- *	Revision 1.79  2002/10/21 09:31:02  mkarl
- *	Changed SkGeInitAssignRamToQueues(), removed call to
- *	SkGeInitAssignRamToQueues in SkGeInit1 and fixed compiler warning in
- *	SkGeInit1.
- *	
- *	Revision 1.78  2002/10/16 15:55:07  mkarl
- *	Fixed a bug in SkGeInitAssignRamToQueues.
- *	
- *	Revision 1.77  2002/10/14 15:07:22  rschmidt
- *	Corrected timeout handling for Rx queue in SkGeStopPort() (#10748)
- *	Editorial changes.
- *	
- *	Revision 1.76  2002/10/11 09:24:38  mkarl
- *	Added check for HW self test results.
- *	
- *	Revision 1.75  2002/10/09 16:56:44  mkarl
- *	Now call SkGeInitAssignRamToQueues() in Init Level 1 in order to assign
- *	the adapter memory to the queues. This default assignment is not suitable
- *	for dual net mode.
- *	
- *	Revision 1.74  2002/09/12 08:45:06  rwahl
- *	Set defaults for PMSCap, PLinkSpeed & PLinkSpeedCap dependent on PHY.
- *	
- *	Revision 1.73  2002/08/16 15:19:45  rschmidt
- *	Corrected check for Tx queues in SkGeCheckQSize().
- *	Added init for new entry GIGenesis and GICopperType
- *	Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
- *	Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros.
- *	
- *	Revision 1.72  2002/08/12 13:38:55  rschmidt
- *	Added check if VAUX is available (stored in GIVauxAvail)
- *	Initialized PLinkSpeedCap in Port struct with SK_LSPEED_CAP_1000MBPS
- *	Editorial changes.
- *	
- *	Revision 1.71  2002/08/08 16:32:58  rschmidt
- *	Added check for Tx queues in SkGeCheckQSize().
- *	Added start of Time Stamp Timer (YUKON) in SkGeInit2().
- *	Editorial changes.
- *	
- *	Revision 1.70  2002/07/23 16:04:26  rschmidt
- *	Added init for GIWolOffs (HW-Bug in YUKON 1st rev.)
- *	Minor changes
- *	
- *	Revision 1.69  2002/07/17 17:07:08  rwahl
- *	- SkGeInit1(): fixed PHY type debug output; corrected init of GIFunc
- *	  table & GIMacType.
- *	- Editorial changes.
- *	
- *	Revision 1.68  2002/07/15 18:38:31  rwahl
- *	Added initialization for MAC type dependent function table.
- *	
- *	Revision 1.67  2002/07/15 15:45:39  rschmidt
- *	Added Tx Store & Forward for YUKON (GMAC Tx FIFO is only 1 kB)
- *	Replaced SK_PHY_MARV by SK_PHY_MARV_COPPER
- *	Editorial changes
- *	
- *	Revision 1.66  2002/06/10 09:35:08  rschmidt
- *	Replaced C++ comments (//)
- *	Editorial changes
- *	
- *	Revision 1.65  2002/06/05 08:33:37  rschmidt
- *	Changed GIRamSize and Reset sequence for YUKON.
- *	SkMacInit() replaced by SkXmInitMac() resp. SkGmInitMac()
- *	
- *	Revision 1.64  2002/04/25 13:03:20  rschmidt
- *	Changes for handling YUKON.
- *	Removed reference to xmac_ii.h (not necessary).
- *	Moved all defines into header file.
- *	Replaced all SkXm...() functions with SkMac...() to handle also
- *	YUKON's GMAC.
- *	Added handling for GMAC FIFO in SkGeInitMacFifo(), SkGeStopPort().
- *	Removed 'goto'-directive from SkGeCfgSync(), SkGeCheckQSize().
- *	Replaced all XMAC-access macros by functions: SkMacRxTxDisable(),
- *	SkMacFlushTxFifo().
- *	Optimized timeout handling in SkGeStopPort().
- *	Initialized PLinkSpeed in Port struct with SK_LSPEED_AUTO.
- *	Release of GMAC Link Control reset in SkGeInit1().
- *	Initialized GIChipId and GIChipRev in GE Init structure.
- *	Added GIRamSize and PhyType values for YUKON.
- *	Removed use of PRxCmd to setup XMAC.
- *	Moved setting of XM_RX_DIS_CEXT to SkXmInitMac().
- *	Use of SkGeXmitLED() only for GENESIS.
- *	Changes for V-CPU support.
- *	Editorial changes.
- *	
- *	Revision 1.63  2001/04/05 11:02:09  rassmann
- *	Stop Port check of the STOP bit did not take 2/18 sec as wanted.
- *	
- *	Revision 1.62  2001/02/07 07:54:21  rassmann
- *	Corrected copyright.
- *	
- *	Revision 1.61  2001/01/31 15:31:40  gklug
- *	fix: problem with autosensing an SR8800 switch
- *	
- *	Revision 1.60  2000/10/18 12:22:21  cgoos
- *	Added workaround for half duplex hangup.
- *	
- *	Revision 1.59  2000/10/10 11:22:06  gklug
- *	add: in manual half duplex mode ignore carrier extension errors
- *	
- *	Revision 1.58  2000/10/02 14:10:27  rassmann
- *	Reading BCOM PHY after releasing reset until it returns a valid value.
- *	
- *	Revision 1.57  2000/08/03 14:55:28  rassmann
- *	Waiting for I2C to be ready before de-initializing adapter
- *	(prevents sensors from hanging up).
- *	
- *	Revision 1.56  2000/07/27 12:16:48  gklug
- *	fix: Stop Port check of the STOP bit does now take 2/18 sec as wanted
- *	
- *	Revision 1.55  1999/11/22 13:32:26  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.54  1999/10/26 07:32:54  malthoff
- *	Initialize PHWLinkUp with SK_FALSE. Required for Diagnostics.
- *	
- *	Revision 1.53  1999/08/12 19:13:50  malthoff
- *	Fix for 1000BT. Do not owerwrite XM_MMU_CMD when
- *	disabling receiver and transmitter. Other bits
- *	may be lost.
- *	
- *	Revision 1.52  1999/07/01 09:29:54  gklug
- *	fix: DoInitRamQueue needs pAC
- *	
- *	Revision 1.51  1999/07/01 08:42:21  gklug
- *	chg: use Store & forward for RAM buffer when Jumbos are used
- *	
- *	Revision 1.50  1999/05/27 13:19:38  cgoos
- *	Added Tx PCI watermark initialization.
- *	Removed Tx RAM queue Store & Forward setting.
- *	
- *	Revision 1.49  1999/05/20 14:32:45  malthoff
- *	SkGeLinkLED() is completly removed now.
- *	
- *	Revision 1.48  1999/05/19 07:28:24  cgoos
- *	SkGeLinkLED no more available for drivers.
- *	Changes for 1000Base-T.
- *	
- *	Revision 1.47  1999/04/08 13:57:45  gklug
- *	add: Init of new port struct fiels PLinkResCt
- *	chg: StopPort Timer check
- *	
- *	Revision 1.46  1999/03/25 07:42:15  malthoff
- *	SkGeStopPort(): Add workaround for cache incoherency.
- *			Create error log entry, disable port, and
- *			exit loop if it does not terminate.
- *	Add XM_RX_LENERR_OK to the default value for the
- *	XMAC receive command register.
- *	
- *	Revision 1.45  1999/03/12 16:24:47  malthoff
- *	Remove PPollRxD and PPollTxD.
- *	Add check for GIPollTimerVal.
- *
- *	Revision 1.44  1999/03/12 13:40:23  malthoff
- *	Fix: SkGeXmitLED(), SK_LED_TST mode does not work.
- *	Add: Jumbo frame support.
- *	Chg: Resolution of parameter IntTime in SkGeCfgSync().
- *
- *	Revision 1.43  1999/02/09 10:29:46  malthoff
- *	Bugfix: The previous modification again also for the second location.
- *
- *	Revision 1.42  1999/02/09 09:35:16  malthoff
- *	Bugfix: The bits '66 MHz Capable' and 'NEWCAP are reset while
- *		clearing the error bits in the PCI status register.
- *
- *	Revision 1.41  1999/01/18 13:07:02  malthoff
- *	Bugfix: Do not use CFG cycles after during Init- or Runtime, because
- *		they may not be available after Boottime.
- *
- *	Revision 1.40  1999/01/11 12:40:49  malthoff
- *	Bug fix: PCI_STATUS: clearing error bits sets the UDF bit.
- *
- *	Revision 1.39  1998/12/11 15:17:33  gklug
- *	chg: Init LipaAutoNeg with Unknown
- *
- *	Revision 1.38  1998/12/10 11:02:57  malthoff
- *	Disable Error Log Message when calling SkGeInit(level 2)
- *	more than once.
- *
- *	Revision 1.37  1998/12/07 12:18:25  gklug
- *	add: refinement of autosense mode: take into account the autoneg cap of LiPa
- *
- *	Revision 1.36  1998/12/07 07:10:39  gklug
- *	fix: init values of LinkBroken/ Capabilities for management
- *
- *	Revision 1.35  1998/12/02 10:56:20  gklug
- *	fix: do NOT init LoinkSync Counter.
- *
- *	Revision 1.34  1998/12/01 10:53:21  gklug
- *	add: init of additional Counters for workaround
- *
- *	Revision 1.33  1998/12/01 10:00:49  gklug
- *	add: init PIsave var in Port struct
- *
- *	Revision 1.32  1998/11/26 14:50:40  gklug
- *	chg: Default is autosensing with AUTOFULL mode
- *
- *	Revision 1.31  1998/11/25 15:36:16  gklug
- *	fix: do NOT stop LED Timer when port should be stopped
- *
- *	Revision 1.30  1998/11/24 13:15:28  gklug
- *	add: Init PCkeckPar struct member
- *
- *	Revision 1.29  1998/11/18 13:19:27  malthoff
- *	Disable packet arbiter timeouts on receive side.
- *	Use maximum timeout value for packet arbiter
- *	transmit timeouts.
- *	Add TestStopBit() function to handle stop RX/TX
- *	problem with active descriptor poll timers.
- *	Bug Fix: Descriptor Poll Timer not started, because
- *	GIPollTimerVal was initialized with 0.
- *
- *	Revision 1.28  1998/11/13 14:24:26  malthoff
- *	Bug Fix: SkGeStopPort() may hang if a Packet Arbiter Timout
- *	is pending or occurs while waiting for TX_STOP and RX_STOP.
- *	The PA timeout is cleared now while waiting for TX- or RX_STOP.
- *
- *	Revision 1.27  1998/11/02 11:04:36  malthoff
- *	fix the last fix
- *
- *	Revision 1.26  1998/11/02 10:37:03  malthoff
- *	Fix: SkGePollTxD() enables always the synchronounous poll timer.
- *
- *	Revision 1.25  1998/10/28 07:12:43  cgoos
- *	Fixed "LED_STOP" in SkGeLnkSyncCnt, "== SK_INIT_IO" in SkGeInit.
- *	Removed: Reset of RAM Interface in SkGeStopPort.
- *
- *	Revision 1.24  1998/10/27 08:13:12  malthoff
- *	Remove temporary code.
- *
- *	Revision 1.23  1998/10/26 07:45:03  malthoff
- *	Add Address Calculation Workaround: If the EPROM byte
- *	Id is 3, the address offset is 512 kB.
- *	Initialize default values for PLinkMode and PFlowCtrlMode.
- *
- *	Revision 1.22  1998/10/22 09:46:47  gklug
- *	fix SysKonnectFileId typo
- *
- *	Revision 1.21  1998/10/20 12:11:56  malthoff
- *	Don't dendy the Queue config if the size of the unused
- *	Rx qeueu is zero.
- *
- *	Revision 1.20  1998/10/19 07:27:58  malthoff
- *	SkGeInitRamIface() is public to be called by diagnostics.
- *
- *	Revision 1.19  1998/10/16 13:33:45  malthoff
- *	Fix: enabling descriptor polling is not allowed until
- *	the descriptor addresses are set. Descriptor polling
- *	must be handled by the driver.
- *
- *	Revision 1.18  1998/10/16 10:58:27  malthoff
- *	Remove temp. code for Diag prototype.
- *	Remove lint warning for dummy reads.
- *	Call SkGeLoadLnkSyncCnt() during SkGeInitPort().
- *
- *	Revision 1.17  1998/10/14 09:16:06  malthoff
- *	Change parameter LimCount and programming of
- *	the limit counter in SkGeCfgSync().
- *
- *	Revision 1.16  1998/10/13 09:21:16  malthoff
- *	Don't set XM_RX_SELF_RX in RxCmd Reg, because it's
- *	like a Loopback Mode in half duplex.
- *
- *	Revision 1.15  1998/10/09 06:47:40  malthoff
- *	SkGeInitMacArb(): set recovery counters init value
- *	to zero although this counters are not uesd.
- *	Bug fix in Rx Upper/Lower Pause Threshold calculation.
- *	Add XM_RX_SELF_RX to RxCmd.
- *
- *	Revision 1.14  1998/10/06 15:15:53  malthoff
- *	Make sure no pending IRQ is cleared in SkGeLoadLnkSyncCnt().
- *
- *	Revision 1.13  1998/10/06 14:09:36  malthoff
- *	Add SkGeLoadLnkSyncCnt(). Modify
- *	the 'port stopped' condition according
- *	to the current problem report.
- *
- *	Revision 1.12  1998/10/05 08:17:21  malthoff
- *	Add functions: SkGePollRxD(), SkGePollTxD(),
- *	DoCalcAddr(), SkGeCheckQSize(),
- *	DoInitRamQueue(), and SkGeCfgSync().
- *	Add coding for SkGeInitMacArb(), SkGeInitPktArb(),
- *	SkGeInitMacFifo(), SkGeInitRamBufs(),
- *	SkGeInitRamIface(), and SkGeInitBmu().
- *
- *	Revision 1.11  1998/09/29 08:26:29  malthoff
- *	bug fix: SkGeInit0() 'i' should be increment.
- *
- *	Revision 1.10  1998/09/28 13:19:01  malthoff
- *	Coding time: Save the done work.
- *	Modify SkGeLinkLED(), add SkGeXmitLED(),
- *	define SkGeCheckQSize(), SkGeInitMacArb(),
- *	SkGeInitPktArb(), SkGeInitMacFifo(),
- *	SkGeInitRamBufs(), SkGeInitRamIface(),
- *	and SkGeInitBmu(). Do coding for SkGeStopPort(),
- *	SkGeInit1(), SkGeInit2(), and SkGeInit3().
- *	Do coding for SkGeDinit() and SkGeInitPort().
- *
- *	Revision 1.9  1998/09/16 14:29:05  malthoff
- *	Some minor changes.
- *
- *	Revision 1.8  1998/09/11 05:29:14  gklug
- *	add: init state of a port
- *
- *	Revision 1.7  1998/09/04 09:26:25  malthoff
- *	Short temporary modification.
- *
- *	Revision 1.6  1998/09/04 08:27:59  malthoff
- *	Remark the do-while in StopPort() because it never ends
- *	without a GE adapter.
- *
- *	Revision 1.5  1998/09/03 14:05:45  malthoff
- *	Change comment for SkGeInitPort(). Do not
- *	repair the queue sizes if invalid.
- *
- *	Revision 1.4  1998/09/03 10:03:19  malthoff
- *	Implement the new interface according to the
- *	reviewed interface specification.
- *
- *	Revision 1.3  1998/08/19 09:11:25  gklug
- *	fix: struct are removed from c-source (see CCC)
- *
- *	Revision 1.2  1998/07/28 12:33:58  malthoff
- *	Add 'IoC' parameter in function declaration and SK IO macros.
- *
- *	Revision 1.1  1998/07/23 09:48:57  malthoff
- *	Creation. First dummy 'C' file.
- *	SkGeInit(Level 0) is card_start for GE.
- *	SkGeDeInit() is card_stop for GE.
- *
- *
- ******************************************************************************/
 
 #include "h/skdrv1st.h"
 #include "h/skdrv2nd.h"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skgemib.c linux-2.4.26-pre6/drivers/net/sk98lin/skgemib.c
--- linux-2.4.25/drivers/net/sk98lin/skgemib.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skgemib.c	2004-03-25 00:18:59.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgemib.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/15 13:38:12 $
  * Purpose:	Private Network Management Interface Management Database
  *
  ****************************************************************************/
@@ -22,54 +20,6 @@
  *
  ******************************************************************************/
 
-/*****************************************************************************
- *
- * History:
- *
- *	$Log: skgemib.c,v $
- *	Revision 1.11  2003/09/15 13:38:12  tschilli
- *	OID_SKGE_PHY_LP_MODE included only after using #define SK_PHY_LP_MODE.
- *	
- *	Revision 1.10  2003/08/15 12:28:59  tschilli
- *	Added new OIDs:
- *	OID_SKGE_DRIVER_RELDATE
- *	OID_SKGE_DRIVER_FILENAME
- *	OID_SKGE_CHIPID
- *	OID_SKGE_RAMSIZE
- *	OID_SKGE_VAUXAVAIL
- *	OID_SKGE_PHY_TYPE
- *	OID_SKGE_PHY_LP_MODE
- *	
- *	Revision 1.9  2003/05/23 12:55:20  tschilli
- *	OID_SKGE_BOARDLEVEL added.
- *	
- *	Revision 1.8  2003/03/27 11:19:15  tschilli
- *	Copyright messages changed.
- *	
- *	Revision 1.7  2002/12/16 09:04:34  tschilli
- *	Code for VCT handling added.
- *	
- *	Revision 1.6  2002/08/09 15:40:21  rwahl
- *	Editorial change (renamed ConfSpeedCap).
- *	
- *	Revision 1.5  2002/08/09 11:05:34  rwahl
- *	Added oid handling for link speed cap.
- *	
- *	Revision 1.4  2002/08/09 09:40:27  rwahl
- *	Added support for NDIS OID_PNP_xxx.
- *	
- *	Revision 1.3  2002/07/17 19:39:54  rwahl
- *	Added handler for OID_SKGE_SPEED_MODE & OID_SKGE_SPEED_STATUS.
- *	
- *	Revision 1.2  2002/05/22 08:59:00  rwahl
- *	- static functions only for release build.
- *	- Source file must be included.
- *	
- *	Revision 1.1  2002/05/22 08:12:42  rwahl
- *	Initial version.
- *	
- ****************************************************************************/
-
 /*
  * PRIVATE OID handler function prototypes
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skgepnmi.c linux-2.4.26-pre6/drivers/net/sk98lin/skgepnmi.c
--- linux-2.4.25/drivers/net/sk98lin/skgepnmi.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skgepnmi.c	2004-03-25 00:21:01.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgepnmi.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.111 $
- * Date:	$Date: 2003/09/15 13:35:35 $
  * Purpose:	Private Network Management Interface
  *
  ****************************************************************************/
@@ -22,469 +20,6 @@
  *
  ******************************************************************************/
 
-/*****************************************************************************
- *
- * History:
- *
- *	$Log: skgepnmi.c,v $
- *	Revision 1.111  2003/09/15 13:35:35  tschilli
- *	Code for OID_SKGE_PHY_LP_MODE completed (using #define SK_PHY_LP_MODE).
- *	SK_DIAG_ATTACHED handling for OID_SKGE_DIAG_MODE in DiagActions() changed.
- *	
- *	Revision 1.110  2003/08/15 12:28:04  tschilli
- *	Added new OIDs:
- *	OID_SKGE_DRIVER_RELDATE
- *	OID_SKGE_DRIVER_FILENAME
- *	OID_SKGE_CHIPID
- *	OID_SKGE_RAMSIZE
- *	OID_SKGE_VAUXAVAIL
- *	OID_SKGE_PHY_TYPE
- *	OID_SKGE_PHY_LP_MODE
- *	
- *	Added SK_DIAG_ATTACHED handling for OID_SKGE_DIAG_MODE in DiagActions().
- *	
- *	Revision 1.109  2003/07/17 14:15:24  tschilli
- *	Bug in SkPnmiGenIoctl() fixed.
- *	
- *	Revision 1.108  2003/05/27 07:10:11  tschilli
- *	Bug in SkPnmiGenIoctl() fixed.
- *	
- *	Revision 1.107  2003/05/23 13:01:10  tschilli
- *	Code for DIAG support added (#define SK_DIAG_SUPPORT).
- *	Code for generic PNMI IOCTL support added. The new function
- *	SkPnmiGenIoctl() is used for this purpose.
- *	Handling of OID_SKGE_BOARDLEVEL added.
- *	Incorrect buffer size handling of OID_SKGE_MTU during GET action fixed.
- *	Return code handling in PowerManagement() fixed.
- *	Editorial changes.
- *  
- *	Revision 1.106  2003/04/10 14:47:31  rschmidt
- *	Fixed handling for OID_GEN_RCV_OK and OID_GEN_XMIT_OK for YUKON's GMAC
- *	in GetPhysStatVal().
- *	Replaced macro PHY_READ() with function call SkXmPhyRead().
- *	Made optimisations for readability and code size.
- *	Editorial changes.
- *	
- *	Revision 1.105  2003/04/09 12:51:32  rschmidt
- *	Fixed XMAC only handling for some events in SkPnmiEvent().
- *	Fixed return value for OID_GEN_RCV_OK (SK_PNMI_HRX) in GetPhysStatVal().
- *	Editorial changes.
- *	
- *	Revision 1.104  2003/03/27 11:18:21  tschilli
- *	BRK statements from DEBUG code removed.
- *	OID_GEN_XMIT_OK and OID_GEN_RCV_OK work with Yukon now.
- *	Copyright messages changed.
- *	
- *	Revision 1.103  2002/12/20 09:57:13  tschilli
- *	SK_PNMI_EVT_VCT_RESET event code changed.
- *	Unused variable from Vct() removed.
- *	
- *	Revision 1.102  2002/12/16 14:03:24  tschilli
- *	VCT code in Vct() changed.
- *	
- *	Revision 1.101  2002/12/16 09:04:10  tschilli
- *	Code for VCT handling added.
- *	
- *	Revision 1.100  2002/09/26 14:28:13  tschilli
- *	For XMAC the values in the SK_PNMI_PORT Port struct are copied to
- *	the new SK_PNMI_PORT BufPort struct during a MacUpdate() call.
- *	These values are used when GetPhysStatVal() is called. With this
- *	mechanism you get the best results when software corrections for
- *	counters are needed. Example: RX_LONGFRAMES.
- *	
- *	Revision 1.99  2002/09/17 12:31:19  tschilli
- *	OID_SKGE_TX_HW_ERROR_CTS, OID_SKGE_OUT_ERROR_CTS, OID_GEN_XMIT_ERROR:
- *	Double count of SK_PNMI_HTX_EXCESS_COL in function General() removed.
- *	OID_PNP_CAPABILITIES: sizeof(SK_PM_WAKE_UP_CAPABILITIES) changed to
- *	sizeof(SK_PNP_CAPABILITIES) in function PowerManagement().
- *	
- *	Revision 1.98  2002/09/10 09:00:03  rwahl
- *	Adapted boolean definitions according sktypes.
- *	
- *	Revision 1.97  2002/09/05 15:07:03  rwahl
- *	Editorial changes.
- *	
- *	Revision 1.96  2002/09/05 11:04:14  rwahl
- *	- Rx/Tx packets statistics of virtual port were zero on link down (#10750)
- *	- For GMAC the overflow IRQ for Rx longframe counter was not counted.
- *	- Incorrect calculation for oids OID_SKGE_RX_HW_ERROR_CTS,
- *	  OID_SKGE_IN_ERRORS_CTS,  OID_GEN_RCV_ERROR.
- *	- Moved correction for OID_SKGE_STAT_RX_TOO_LONG to GetPhysStatVal().
- *	- Editorial changes.
- *	
- *	Revision 1.95  2002/09/04 08:53:37  rwahl
- *	- Incorrect statistics for Rx_too_long counter with jumbo frame (#10751)
- *	- StatRxFrameTooLong & StatRxPMaccErr counters were not reset.
- *	- Fixed compiler warning for debug msg arg types.
- *	
- *	Revision 1.94  2002/08/09 15:42:14  rwahl
- *	- Fixed StatAddr table for GMAC.
- *	- VirtualConf(): returned indeterminated status for speed oids if no
- *	  active port.
- *	
- *	Revision 1.93  2002/08/09 11:04:59  rwahl
- *	Added handler for link speed caps.
- *	
- *	Revision 1.92  2002/08/09 09:43:03  rwahl
- *	- Added handler for NDIS OID_PNP_xxx ids.
- *	
- *	Revision 1.91  2002/07/17 19:53:03  rwahl
- *	- Added StatOvrflwBit table for XMAC & GMAC.
- *	- Extended StatAddr table for GMAC. Added check of number of counters
- *	  in enumeration and size of StatAddr table on init level.
- *	- Added use of GIFunc table.
- *	- ChipSet is not static anymore,
- *	- Extended SIRQ event handler for both mac types.
- *	- Fixed rx short counter bug (#10620)
- *	- Added handler for oids SKGE_SPEED_MODE & SKGE_SPEED_STATUS.
- *	- Extended GetPhysStatVal() for GMAC.
- *	- Editorial changes.
- *	
- *	Revision 1.90  2002/05/22 08:56:25  rwahl
- *	- Moved OID table to separate source file.
- *	- Fix: TX_DEFFERAL counter incremented in full-duplex mode.
- *	- Use string definitions for error msgs.
- *	
- *	Revision 1.89  2001/09/18 10:01:30  mkunz
- *	some OID's fixed for dualnetmode
- *	
- *	Revision 1.88  2001/08/02 07:58:08  rwahl
- *	- Fixed NetIndex to csum module at ResetCounter().
- *	
- *	Revision 1.87  2001/04/06 13:35:09  mkunz
- *	-Bugs fixed in handling of OID_SKGE_MTU and the VPD OID's
- *	
- *	Revision 1.86  2001/03/09 09:18:03  mkunz
- *	Changes in SK_DBG_MSG
- *	
- *	Revision 1.85  2001/03/08 09:37:31  mkunz
- *	Bugfix in ResetCounter for Pnmi.Port structure
- *	
- *	Revision 1.84  2001/03/06 09:04:55  mkunz
- *	Made some changes in instance calculation
- *	
- *	Revision 1.83  2001/02/15 09:15:32  mkunz
- *	Necessary changes for dual net mode added
- *	
- *	Revision 1.82  2001/02/07 08:24:19  mkunz
- *	-Made changes in handling of OID_SKGE_MTU
- *	
- *	Revision 1.81  2001/02/06 09:58:00  mkunz
- *	-Vpd bug fixed
- *	-OID_SKGE_MTU added
- *	-pnmi support for dual net mode. Interface function and macros extended
- *	
- *	Revision 1.80  2001/01/22 13:41:35  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.79  2000/12/05 14:57:40  cgoos
- *	SetStruct failed before first Link Up (link mode of virtual
- *	port "INDETERMINATED").
- *	
- *	Revision 1.78  2000/09/12 10:44:58  cgoos
- *	Fixed SK_PNMI_STORE_U32 calls with typecasted argument.
- *	
- *	Revision 1.77  2000/09/07 08:10:19  rwahl
- *	- Modified algorithm for 64bit NDIS statistic counters;
- *	  returns 64bit or 32bit value depending on passed buffer
- *	  size. Indicate capability for 64bit NDIS counter, if passed
- *	  buffer size is zero. OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR,
- *	  and OID_GEN_RCV_NO_BUFFER handled as 64bit counter, too.
- *	- corrected OID_SKGE_RLMT_PORT_PREFERRED.
- *	
- *	Revision 1.76  2000/08/03 15:23:39  rwahl
- *	- Correction for FrameTooLong counter has to be moved to OID handling
- *	  routines (instead of statistic counter routine).
- *	- Fix in XMAC Reset Event handling: Only offset counter for hardware
- *	  statistic registers are updated.
- *	
- *	Revision 1.75  2000/08/01 16:46:05  rwahl
- *	- Added StatRxLongFrames counter and correction of FrameTooLong counter.
- *	- Added directive to control width (default = 32bit) of NDIS statistic
- *	  counters (SK_NDIS_64BIT_CTR).
- *	
- *	Revision 1.74  2000/07/04 11:41:53  rwahl
- *	- Added volition connector type.
- *	
- *	Revision 1.73  2000/03/15 16:33:10  rwahl
- *	Fixed bug 10510; wrong reset of virtual port statistic counters.
- *	
- *	Revision 1.72  1999/12/06 16:15:53  rwahl
- *	Fixed problem of instance range for current and factory MAC address.
- *	
- *	Revision 1.71  1999/12/06 10:14:20  rwahl
- *	Fixed bug 10476; set operation for PHY_OPERATION_MODE.
- *	
- *	Revision 1.70  1999/11/22 13:33:34  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.69  1999/10/18 11:42:15  rwahl
- *	Added typecasts for checking event dependent param (debug only).
- *	
- *	Revision 1.68  1999/10/06 09:35:59  cgoos
- *	Added state check to PHY_READ call (hanged if called during startup).
- *	
- *	Revision 1.67  1999/09/22 09:53:20  rwahl
- *	- Read Broadcom register for updating FCS error counter (1000Base-T).
- *
- *	Revision 1.66  1999/08/26 13:47:56  rwahl
- *	Added SK_DRIVER_SENDEVENT when queueing RLMT_CHANGE_THRES trap.
- *	
- *	Revision 1.65  1999/07/26 07:49:35  cgoos
- *	Added two typecasts to avoid compiler warnings.
- *	
- *	Revision 1.64  1999/05/20 09:24:12  cgoos
- *	Changes for 1000Base-T (sensors, Master/Slave).
- *
- *	Revision 1.63  1999/04/13 15:11:58  mhaveman
- *	Moved include of rlmt.h to header skgepnmi.h because some macros
- *	are needed there.
- *	
- *	Revision 1.62  1999/04/13 15:08:07  mhaveman
- *	Replaced again SK_RLMT_CHECK_LINK with SK_PNMI_RLMT_MODE_CHK_LINK
- *	to grant unified interface by only using the PNMI header file.
- *	SK_PNMI_RLMT_MODE_CHK_LINK is defined the same as SK_RLMT_CHECK_LINK.
- *	
- *	Revision 1.61  1999/04/13 15:02:48  mhaveman
- *	Changes caused by review:
- *	-Changed some comments
- *	-Removed redundant check for OID_SKGE_PHYS_FAC_ADDR
- *	-Optimized PRESET check.
- *	-Meaning of error SK_ADDR_DUPLICATE_ADDRESS changed. Set of same
- *	 address will now not cause this error. Removed corresponding check.
- *	
- *	Revision 1.60  1999/03/23 10:41:23  mhaveman
- *	Added comments.
- *	
- *	Revision 1.59  1999/02/19 08:01:28  mhaveman
- *	Fixed bug 10372 that after counter reset all ports were displayed
- *	as inactive.
- *	
- *	Revision 1.58  1999/02/16 18:04:47  mhaveman
- *	Fixed problem of twisted OIDs SENSOR_WAR_TIME and SENSOR_ERR_TIME.
- *	
- *	Revision 1.56  1999/01/27 12:29:11  mhaveman
- *	SkTimerStart was called with time value in milli seconds but needs
- *	micro seconds.
- *	
- *	Revision 1.55  1999/01/25 15:00:38  mhaveman
- *	Added support to allow multiple ports to be active. If this feature in
- *	future will be used, the Management Data Base variables PORT_ACTIVE
- *	and PORT_PREFERED should be moved to the port specific part of RLMT.
- *	Currently they return the values of the first active physical port
- *	found. A set to the virtual port will actually change all active
- *	physical ports. A get returns the melted values of all active physical
- *	ports. If the port values differ a return value INDETERMINATED will
- *	be returned. This effects especially the CONF group.
- *	
- *	Revision 1.54  1999/01/19 10:10:22  mhaveman
- *	-Fixed bug 10354: Counter values of virtual port were wrong after port
- *	 switches
- *	-Added check if a switch to the same port is notified.
- *	
- *	Revision 1.53  1999/01/07 09:25:21  mhaveman
- *	Forgot to initialize a variable.
- *	
- *	Revision 1.52  1999/01/05 10:34:33  mhaveman
- *	Fixed little error in RlmtChangeEstimate calculation.
- *	
- *	Revision 1.51  1999/01/05 09:59:07  mhaveman
- *	-Moved timer start to init level 2
- *	-Redesigned port switch average calculation to avoid 64bit
- *	 arithmetic.
- *	
- *	Revision 1.50  1998/12/10 15:13:59  mhaveman
- *	-Fixed: PHYS_CUR_ADDR returned wrong addresses
- *	-Fixed: RLMT_PORT_PREFERED and RLMT_CHANGE_THRES preset returned
- *	        always BAD_VALUE.
- *	-Fixed: TRAP buffer seemed to sometimes suddenly empty
- *	
- *	Revision 1.49  1998/12/09 16:17:07  mhaveman
- *	Fixed: Couldnot delete VPD keys on UNIX.
- *	
- *	Revision 1.48  1998/12/09 14:11:10  mhaveman
- *	-Add: Debugmessage for XMAC_RESET supressed to minimize output.
- *	-Fixed: RlmtChangeThreshold will now be initialized.
- *	-Fixed: VPD_ENTRIES_LIST extended value with unnecessary space char.
- *	-Fixed: On VPD key creation an invalid key name could be created
- *	        (e.g. A5)
- *	-Some minor changes in comments and code.
- *	
- *	Revision 1.47  1998/12/08 16:00:31  mhaveman
- *	-Fixed: For RLMT_PORT_ACTIVE will now be returned a 0 if no port
- *		is active.
- *	-Fixed: For the RLMT statistics group only the last value was
- *		returned and the rest of the buffer was filled with 0xff
- *	-Fixed: Mysteriously the preset on RLMT_MODE still returned
- *		BAD_VALUE.
- *	Revision 1.46  1998/12/08 10:04:56  mhaveman
- *	-Fixed: Preset on RLMT_MODE returned always BAD_VALUE error.
- *	-Fixed: Alignment error in GetStruct
- *	-Fixed: If for Get/Preset/SetStruct the buffer size is equal or
- *	        larger than SK_PNMI_MIN_STRUCT_SIZE the return value is stored
- *		to the buffer. In this case the caller should always return
- *	        ok to its upper routines. Only if the buffer size is less
- *	        than SK_PNMI_MIN_STRUCT_SIZE and the return value is unequal
- *	        to 0, an error should be returned by the caller.
- *	-Fixed: Wrong number of instances with RLMT statistic.
- *	-Fixed: Return now SK_LMODE_STAT_UNKNOWN if the LinkModeStatus is 0.
- *	
- *	Revision 1.45  1998/12/03 17:17:24  mhaveman
- *	-Removed for VPD create action the buffer size limitation to 4 bytes.
- *	-Pass now physical/active physical port to ADDR for CUR_ADDR set
- *	
- *	Revision 1.44  1998/12/03 15:14:35  mhaveman
- *	Another change to Vpd instance evaluation.
- *
- *	Revision 1.43  1998/12/03 14:18:10  mhaveman
- *	-Fixed problem in PnmiSetStruct. It was impossible to set any value.
- *	-Removed VPD key evaluation for VPD_FREE_BYTES and VPD_ACTION.
- *
- *	Revision 1.42  1998/12/03 11:31:47  mhaveman
- *	Inserted cast to satisfy lint.
- *	
- *	Revision 1.41  1998/12/03 11:28:16  mhaveman
- *	Removed SK_PNMI_CHECKPTR
- *	
- *	Revision 1.40  1998/12/03 11:19:07  mhaveman
- *	Fixed problems
- *	-A set to virtual port will now be ignored. A set with broadcast
- *	 address to any port will be ignored.
- *	-GetStruct function made VPD instance calculation wrong.
- *	-Prefered port returned -1 instead of 0.
- *	
- *	Revision 1.39  1998/11/26 15:30:29  mhaveman
- *	Added sense mode to link mode.
- *	
- *	Revision 1.38  1998/11/23 15:34:00  mhaveman
- *	-Fixed bug for RX counters. On an RX overflow interrupt the high
- *	 words of all RX counters were incremented.
- *	-SET operations on FLOWCTRL_MODE and LINK_MODE accept now the
- *	 value 0, which has no effect. It is usefull for multiple instance
- *	 SETs.
- *	
- *	Revision 1.37  1998/11/20 08:02:04  mhaveman
- *	-Fixed: Ports were compared with MAX_SENSORS
- *	-Fixed: Crash in GetTrapEntry with MEMSET macro
- *	-Fixed: Conversions between physical, logical port index and instance
- *	
- *	Revision 1.36  1998/11/16 07:48:53  mhaveman
- *	Casted SK_DRIVER_SENDEVENT with (void) to eleminate compiler warnings
- *	on Solaris.
- *	
- *	Revision 1.35  1998/11/16 07:45:34  mhaveman
- *	SkAddrOverride now returns value and will be checked.
- *
- *	Revision 1.34  1998/11/10 13:40:37  mhaveman
- *	Needed to change interface, because NT driver needs a return value
- *	of needed buffer space on TOO_SHORT errors. Therefore all
- *	SkPnmiGet/Preset/Set functions now have a pointer to the length
- *	parameter, where the needed space on error is returned.
- *	
- *	Revision 1.33  1998/11/03 13:52:46  mhaveman
- *	Made file lint conform.
- *	
- *	Revision 1.32  1998/11/03 13:19:07  mhaveman
- *	The events SK_HWEV_SET_LMODE and SK_HWEV_SET_FLOWMODE pass now in
- *	Para32[0] the physical MAC index and in Para32[1] the new mode.
- *	
- *	Revision 1.31  1998/11/03 12:30:40  gklug
- *	fix: compiler warning memset
- *
- *	Revision 1.30  1998/11/03 12:04:46  mhaveman
- *	Fixed problem in SENSOR_VALUE, which wrote beyond the buffer end
- *	Fixed alignment problem with CHIPSET.
- *
- *	Revision 1.29  1998/11/02 11:23:54  mhaveman
- *	Corrected SK_ERROR_LOG to SK_ERR_LOG. Sorry.
- *	
- *	Revision 1.28  1998/11/02 10:47:16  mhaveman
- *	Added syslog messages for internal errors.
- *	
- *	Revision 1.27  1998/10/30 15:48:06  mhaveman
- *	Fixed problems after simulation of SK_PNMI_EVT_CHG_EST_TIMER and
- *	RlmtChangeThreshold calculation.
- *	
- *	Revision 1.26  1998/10/29 15:36:55  mhaveman
- *	-Fixed bug in trap buffer handling.
- *	-OID_SKGE_DRIVER_DESCR, OID_SKGE_DRIVER_VERSION, OID_SKGE_HW_DESCR,
- *	 OID_SKGE_HW_VERSION, OID_SKGE_VPD_ENTRIES_LIST, OID_SKGE_VPD_KEY,
- *	 OID_SKGE_VPD_VALUE, and OID_SKGE_SENSOR_DESCR return values with
- *	 a leading octet before each string storing the string length.
- *	-Perform a RlmtUpdate during SK_PNMI_EVT_XMAC_RESET to minimize
- *	 RlmtUpdate calls in GetStatVal.
- *	-Inserted SK_PNMI_CHECKFLAGS macro increase readability.
- *	
- *	Revision 1.25  1998/10/29 08:50:36  mhaveman
- *	Fixed problems after second event simulation.
- *	
- *	Revision 1.24  1998/10/28 08:44:37  mhaveman
- *	-Fixed alignment problem
- *	-Fixed problems during event simulation
- *	-Fixed sequence of error return code (INSTANCE -> ACCESS -> SHORT)
- *	-Changed type of parameter Instance back to SK_U32 because of VPD
- *	-Updated new VPD function calls
- *
- *	Revision 1.23  1998/10/23 10:16:37  mhaveman
- *	Fixed bugs after buffer test simulation.
- *	
- *	Revision 1.22  1998/10/21 13:23:52  mhaveman
- *	-Call syntax of SkOsGetTime() changed to SkOsGetTime(pAc).
- *	-Changed calculation of hundrets of seconds.
- *
- *	Revision 1.20  1998/10/20 07:30:45  mhaveman
- *	Made type changes to unsigned integer where possible.
- *	
- *	Revision 1.19  1998/10/19 10:51:30  mhaveman
- *	-Made Bug fixes after simulation run
- *	-Renamed RlmtMAC... to RlmtPort...
- *	-Marked workarounds with Errata comments
- *	
- *	Revision 1.18  1998/10/14 07:50:08  mhaveman
- *	-For OID_SKGE_LINK_STATUS the link down detection has moved from RLMT
- *	 to HWACCESS.
- *	-Provided all MEMCPY/MEMSET macros with (char *) pointers, because
- *	 Solaris throwed warnings when mapping to bcopy/bset.
- *
- *	Revision 1.17  1998/10/13 07:42:01  mhaveman
- *	-Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA
- *	-Removed old cvs history entries
- *	-Renamed MacNumber to PortNumber
- *
- *	Revision 1.16  1998/10/07 10:52:49  mhaveman
- *	-Inserted handling of some OID_GEN_ Ids for windows
- *	-Fixed problem with 803.2 statistic.
- *	
- *	Revision 1.15  1998/10/01 09:16:29  mhaveman
- *	Added Debug messages for function call and UpdateFlag tracing.
- *	
- *	Revision 1.14  1998/09/30 13:39:09  mhaveman
- *	-Reduced namings of 'MAC' by replacing them with 'PORT'.
- *	-Completed counting of OID_SKGE_RX_HW_ERROR_CTS,
- *       OID_SKGE_TX_HW_ERROR_CTS,
- *	 OID_SKGE_IN_ERRORS_CTS, and OID_SKGE_OUT_ERROR_CTS.
- *	-SET check for RlmtMode
- *	
- *	Revision 1.13  1998/09/28 13:13:08  mhaveman
- *	Hide strcmp, strlen, and strncpy behind macros SK_STRCMP, SK_STRLEN,
- *	and SK_STRNCPY. (Same reasons as for mem.. and MEM..)
- *	
- *	Revision 1.12  1998/09/16 08:18:36  cgoos
- *	Fix: XM_INxx and XM_OUTxx called with different parameter order:
- *      sometimes IoC,Mac,...  sometimes Mac,IoC,... Now always first variant.
- *	Fix: inserted "Pnmi." into some pAC->pDriverDescription / Version.
- *	Change: memset, memcpy to makros SK_MEMSET, SK_MEMCPY
- *
- *	Revision 1.11  1998/09/04 17:01:45  mhaveman
- *	Added SyncCounter as macro and OID_SKGE_.._NO_DESCR_CTS to
- *	OID_SKGE_RX_NO_BUF_CTS.
- *	
- *	Revision 1.10  1998/09/04 14:35:35  mhaveman
- *	Added macro counters, that are counted by driver.
- *	
- ****************************************************************************/
-
-
 #ifndef _lint
 static const char SysKonnectFileId[] =
 	"@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skgesirq.c linux-2.4.26-pre6/drivers/net/sk98lin/skgesirq.c
--- linux-2.4.25/drivers/net/sk98lin/skgesirq.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skgesirq.c	2004-03-25 00:16:53.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skgesirq.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.92 $
- * Date:	$Date: 2003/09/16 14:37:07 $
  * Purpose:	Special IRQ module
  *
  ******************************************************************************/
@@ -22,374 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skgesirq.c,v $
- *	Revision 1.92  2003/09/16 14:37:07  rschmidt
- *	Added debug messages in some SkGePortCheckUp...() routines.
- *	Fixed compiler warnings for different types.
- *	Avoided port check up in reset state (eg. coma mode).
- *	Editorial changes.
- *	
- *	Revision 1.91  2003/07/04 12:46:22  rschmidt
- *	Added debug messages in SkGePortCheckUpGmac().
- *	Added error log message and new driver event SK_DRV_DOWNSHIFT_DET
- *	for Downshift detection (Yukon-Copper).
- *	Editorial changes.
- *	
- *	Revision 1.90  2003/05/28 15:35:45  rschmidt
- *	Added parameter AutoNeg in all SkGePortCheckUp...() to save code.
- *	Added setting for AutoNeg only once in SkGePortCheckUp().
- *	Moved defines for return codes of SkGePortCheckUp() to header file.
- *	Editorial changes.
- *	
- *	Revision 1.89  2003/05/13 17:32:20  mkarl
- *	Removed links to RLMT and PNMI for SLIM driver (SK_SLIM).
- *	Separated GENESIS and YUKON only code to reduce code size.
- *	
- *	Revision 1.88  2003/05/06 13:20:34  rschmidt
- *	Changed workaround for Tx hang in half duplex only for Genesis.
- *	Replaced SkPnmiGetVar() calls for Tx Octets Counter
- *	with SkXmMacStatistic() in SkGeSirqIsr().
- *	Added defines around GENESIS resp. YUKON branches to reduce
- *	code size for PXE.
- *	Editorial changes.
- *	
- *	Revision 1.87  2003/04/28 09:18:31  rschmidt
- *	Added increment for GITimeStampCnt (high dword for
- *	Time Stamp Timer counter), when overflow IRQ occurs.
- *	Disabled HW Error IRQ on 32-bit Yukon if sensor IRQ occurs
- *	by changing the common mask stored in GIValIrqMask.
- *	Changed handling for HW Error IRQ in SkGeSirqIsr().
- *	Added clearing of the software forced IRQ in SkGeSirqIsr().
- *	Editorial changes.
- *	
- *	Revision 1.86  2003/04/09 13:03:24  rschmidt
- *	Added workaround for configuration of GPHY's Auto-negotiation
- *	advertisement register after link down event in SkPhyIsrGmac().
- *	
- *	Revision 1.85  2003/04/08 16:39:02  rschmidt
- *	Changed handling for different PhyTypes for source code
- *	portability to PXE, UNDI.
- *	Editorial changes.
- *	
- *	Revision 1.84  2003/03/31 07:01:43  mkarl
- *	Corrected Copyright.
- *	Editorial changes.
- *	
- *	Revision 1.83  2003/02/05 15:10:59  rschmidt
- *	Fixed setting of PLinkSpeedUsed in SkHWLinkUp() when
- *	auto-negotiation is disabled.
- *	Editorial changes.
- *	
- *	Revision 1.82  2003/01/29 13:34:33  rschmidt
- *	Added some typecasts to avoid compiler warnings.
- *	
- *	Revision 1.81  2002/12/05 10:49:51  rschmidt
- *	Fixed missing Link Down Event for fiber (Bug Id #10768)
- *	Added reading of cable length when link is up
- *	Removed testing of unused error bits in PHY ISR
- *	Editorial changes.
- *	
- *	Revision 1.80  2002/11/12 17:15:21  rschmidt
- *	Replaced SkPnmiGetVar() by ...MacStatistic() in SkMacParity().
- *	Editorial changes.
- *	
- *	Revision 1.79  2002/10/14 15:14:51  rschmidt
- *	Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in
- *	SkMacParity() depending on GIChipRev (HW-Bug #8).
- *	Added error messages for GPHY Auto-Negotiation Error and
- *	FIFO Overflow/Underrun in SkPhyIsrGmac().
- *	Editorial changes.
- *	
- *	Revision 1.78  2002/10/10 15:54:29  mkarl
- *	changes for PLinkSpeedUsed
- *	
- *	Revision 1.77  2002/09/12 08:58:51  rwahl
- *	Retrieve counters needed for XMAC errata workarounds directly because
- *	PNMI returns corrected counter values (e.g. #10620).
- *	
- *	Revision 1.76  2002/08/16 15:21:54  rschmidt
- *	Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
- *	Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros.
- *	Editorial changes.
- *	
- *	Revision 1.75  2002/08/12 13:50:47  rschmidt
- *	Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in
- *	SkMacParity() by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE (HW-Bug #8).
- *	Added clearing of IS_IRQ_TIST_OV and IS_IRQ_SENSOR in SkGeHwErr().
- *	Corrected handling of Link Up and Auto-Negotiation Over for GPHY.
- *	in SkGePortCheckUpGmac().
- *	Editorial changes.
- *	
- *	Revision 1.74  2002/08/08 16:17:04  rschmidt
- *	Added PhyType check for SK_HWEV_SET_ROLE event (copper only)
- *	Changed Link Up check reading PHY Specific Status (YUKON)
- *	Editorial changes
- *	
- *	Revision 1.73  2002/07/15 18:36:53  rwahl
- *	Editorial changes.
- *	
- *	Revision 1.72  2002/07/15 15:46:26  rschmidt
- *	Added new event: SK_HWEV_SET_SPEED
- *	Editorial changes
- *	
- *	Revision 1.71  2002/06/10 09:34:19  rschmidt
- *	Editorial changes
- *	
- *	Revision 1.70  2002/06/05 08:29:18  rschmidt
- *	SkXmRxTxEnable() replaced by SkMacRxTxEnable().
- *	Editorial changes.
- *	
- *	Revision 1.69  2002/04/25 13:03:49  rschmidt
- *	Changes for handling YUKON.
- *	Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
- *	Replaced all XMAC-access macros by functions: SkMacRxTxDisable(),
- *	SkMacIrqDisable().
- *	Added handling for GMAC FIFO in SkMacParity().
- *	Replaced all SkXm...() functions with SkMac...() to handle also
- *	YUKON's GMAC.
- *	Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
- *	by functions SkXmPhyRead(), SkXmPhyWrite().
- *	Disabling all PHY interrupts moved to SkMacIrqDisable().
- *	Added handling for GPHY IRQ in SkGeSirqIsr().
- *	Removed status parameter from MAC IRQ handler SkMacIrq().
- *	Added SkGePortCheckUpGmac(), SkPhyIsrGmac() for GMAC.
- *	Editorial changes
- *	
- *	Revision 1.68  2002/02/26 15:24:53  rwahl
- *	Fix: no link with manual configuration (#10673). The previous fix for
- *	#10639 was removed. So for RLMT mode = CLS the RLMT may switch to
- *	misconfigured port. It should not occur for the other RLMT modes.
- *	
- *	Revision 1.67  2001/11/20 09:19:58  rwahl
- *	Reworked bugfix #10639 (no dependency to RLMT mode).
- *	
- *	Revision 1.66  2001/10/26 07:52:53  afischer
- *	Port switching bug in `check local link` mode
- *	
- *	Revision 1.65  2001/02/23 13:41:51  gklug
- *	fix: PHYS2INST should be used correctly for Dual Net operation
- *	chg: do no longer work with older PNMI
- *	
- *	Revision 1.64  2001/02/15 11:27:04  rassmann
- *	Working with RLMT v1 if SK_MAX_NETS undefined.
- *	
- *	Revision 1.63  2001/02/06 10:44:23  mkunz
- *	- NetIndex added to interface functions of pnmi V4 with dual net support
- *	
- *	Revision 1.62  2001/01/31 15:31:41  gklug
- *	fix: problem with autosensing an SR8800 switch
- *	
- *	Revision 1.61  2000/11/09 11:30:09  rassmann
- *	WA: Waiting after releasing reset until BCom chip is accessible.
- *
- *	Revision 1.60  2000/10/18 12:37:48  cgoos
- *	Reinserted the comment for version 1.56.
- *	
- *	Revision 1.59  2000/10/18 12:22:20  cgoos
- *	Added workaround for half duplex hangup.
- *	
- *	Revision 1.58  2000/09/28 13:06:04  gklug
- *	fix: BCom may NOT be touched if XMAC is in RESET state
- *	
- *	Revision 1.57  2000/09/08 12:38:39  cgoos
- *	Added forgotten variable declaration.
- *	
- *	Revision 1.56  2000/09/08 08:12:13  cgoos
- *	Changed handling of parity errors in SkGeHwErr (correct reset of error).
- *
- *	Revision 1.55  2000/06/19 08:36:25  cgoos
- *	Changed comment.
- *	
- *	Revision 1.54  2000/05/22 08:45:57  malthoff
- *	Fix: #10523 is valid for all BCom PHYs.
- *	
- *	Revision 1.53  2000/05/19 10:20:30  cgoos
- *	Removed Solaris debug output code.
- *	
- *	Revision 1.52  2000/05/19 10:19:37  cgoos
- *	Added PHY state check in HWLinkDown.
- *	Move PHY interrupt code to IS_EXT_REG case in SkGeSirqIsr.
- *	
- *	Revision 1.51  2000/05/18 05:56:20  cgoos
- *	Fixed typo.
- *	
- *	Revision 1.50  2000/05/17 12:49:49  malthoff
- *	Fixes BCom link bugs (#10523).
- *	
- *	Revision 1.49  1999/12/17 11:02:50  gklug
- *	fix: read PHY_STAT of Broadcom chip more often to assure good status
- *	
- *	Revision 1.48  1999/12/06 10:01:17  cgoos
- *	Added SET function for Role.
- *	
- *	Revision 1.47  1999/11/22 13:34:24  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.46  1999/09/16 10:30:07  cgoos
- *	Removed debugging output statement from Linux.
- *	
- *	Revision 1.45  1999/09/16 07:32:55  cgoos
- *	Fixed dual-port copperfield bug (PHY_READ from resetted port).
- *	Removed some unused variables.
- *	
- *	Revision 1.44  1999/08/03 15:25:04  cgoos
- *	Removed workaround for disabled interrupts in half duplex mode.
- *	
- *	Revision 1.43  1999/08/03 14:27:58  cgoos
- *	Removed SENSE mode code from SkGePortCheckUpBcom.
- *	
- *	Revision 1.42  1999/07/26 09:16:54  cgoos
- *	Added some typecasts to avoid compiler warnings.
- *	
- *	Revision 1.41  1999/05/19 07:28:59  cgoos
- *	Changes for 1000Base-T.
- *	
- *	Revision 1.40  1999/04/08 13:59:39  gklug
- *	fix: problem with 3Com switches endless RESTARTs
- *	
- *	Revision 1.39  1999/03/08 10:10:52  gklug
- *	fix: AutoSensing did switch to next mode even if LiPa indicated offline
- *	
- *	Revision 1.38  1999/03/08 09:49:03  gklug
- *	fix: Bug using pAC instead of IoC, causing AIX problems
- *	fix: change compare for Linux compiler bug workaround
- *	
- *	Revision 1.37  1999/01/28 14:51:33  gklug
- *	fix: monitor for autosensing and extra RESETS the RX on wire counters
- *	
- *	Revision 1.36  1999/01/22 09:19:55  gklug
- *	fix: Init DupMode and InitPauseMd are now called in RxTxEnable
- *	
- *	Revision 1.35  1998/12/11 15:22:59  gklug
- *	chg: autosensing: check for receive if manual mode was guessed
- *	chg: simplified workaround for XMAC errata
- *	chg: wait additional 100 ms before link goes up.
- *	chg: autoneg timeout to 600 ms
- *	chg: restart autoneg even if configured to autonegotiation
- *	
- *	Revision 1.34  1998/12/10 10:33:14  gklug
- *	add: more debug messages
- *	fix: do a new InitPhy if link went down (AutoSensing problem)
- *	chg: Check for zero shorts if link is NOT up
- *	chg: reset Port if link goes down
- *	chg: wait additional 100 ms when link comes up to check shorts
- *	fix: dummy read extended autoneg status to prevent link going down immediately
- *	
- *	Revision 1.33  1998/12/07 12:18:29  gklug
- *	add: refinement of autosense mode: take into account the autoneg cap of LiPa
- *	
- *	Revision 1.32  1998/12/07 07:11:21  gklug
- *	fix: compiler warning
- *	
- *	Revision 1.31  1998/12/02 09:29:05  gklug
- *	fix: WA XMAC Errata: FCSCt check was not correct.
- *	fix: WA XMAC Errata: Prec Counter were NOT updated in case of short checks.
- *	fix: Clear Stat : now clears the Prev counters of all known Ports
- *	
- *	Revision 1.30  1998/12/01 10:54:15  gklug
- *	dd: workaround for XMAC errata changed. Check RX count and CRC err Count, too.
- *	
- *	Revision 1.29  1998/12/01 10:01:53  gklug
- *	fix: if MAC IRQ occurs during port down, this will be handled correctly
- *	
- *	Revision 1.28  1998/11/26 16:22:11  gklug
- *	fix: bug in autosense if manual modes are used
- *	
- *	Revision 1.27  1998/11/26 15:50:06  gklug
- *	fix: PNMI needs to set PLinkModeConf
- *	
- *	Revision 1.26  1998/11/26 14:51:58  gklug
- *	add: AutoSensing functionalty
- *	
- *	Revision 1.25  1998/11/26 07:34:37  gklug
- *	fix: Init PrevShorts when restarting port due to Link connection
- *	
- *	Revision 1.24  1998/11/25 10:57:32  gklug
- *	fix: remove unreferenced local vars
- *	
- *	Revision 1.23  1998/11/25 08:26:40  gklug
- *	fix: don't do a RESET on a starting or stopping port
- *	
- *	Revision 1.22  1998/11/24 13:29:44  gklug
- *	add: Workaround for MAC parity errata
- *	
- *	Revision 1.21  1998/11/18 15:31:06  gklug
- *	fix: lint bugs
- *	
- *	Revision 1.20  1998/11/18 12:58:54  gklug
- *	fix: use PNMI query instead of hardware access
- *	
- *	Revision 1.19  1998/11/18 12:54:55  gklug
- *	chg: add new workaround for XMAC Errata
- *	add: short event counter monitoring on active link too
- *	
- *	Revision 1.18  1998/11/13 14:27:41  malthoff
- *	Bug Fix: Packet Arbiter Timeout was not cleared correctly
- *	for timeout on TX1 and TX2.
- *	
- *	Revision 1.17  1998/11/04 07:01:59  cgoos
- *	Moved HW link poll sequence.
- *	Added call to SkXmRxTxEnable.
- *	
- *	Revision 1.16  1998/11/03 13:46:03  gklug
- *	add: functionality of SET_LMODE and SET_FLOW_MODE
- *	fix: send RLMT LinkDown event when Port stop is given with LinkUp
- *	
- *	Revision 1.15  1998/11/03 12:56:47  gklug
- *	fix: Needs more events
- *	
- *	Revision 1.14  1998/10/30 07:36:35  gklug
- *	rmv: unnecessary code
- *	
- *	Revision 1.13  1998/10/29 15:21:57  gklug
- *	add: Poll link feature for activating HW link
- *	fix: Deactivate HWLink when Port STOP is given
- *	
- *	Revision 1.12  1998/10/28 07:38:57  cgoos
- *	Checking link status at begin of SkHWLinkUp.
- *	
- *	Revision 1.11  1998/10/22 09:46:50  gklug
- *	fix SysKonnectFileId typo
- *	
- *	Revision 1.10  1998/10/14 13:57:47  gklug
- *	add: Port start/stop event
- *	
- *	Revision 1.9  1998/10/14 05:48:29  cgoos
- *	Added definition for Para.
- *	
- *	Revision 1.8  1998/10/14 05:40:09  gklug
- *	add: Hardware Linkup signal used
- *	
- *	Revision 1.7  1998/10/09 06:50:20  malthoff
- *	Remove ID_sccs by SysKonnectFileId.
- *
- *	Revision 1.6  1998/10/08 09:11:49  gklug
- *	add: clear IRQ commands
- *	
- *	Revision 1.5  1998/10/02 14:27:35  cgoos
- *	Fixed some typos and wrong event names.
- *	
- *	Revision 1.4  1998/10/02 06:24:17  gklug
- *	add: HW error function
- *	fix: OUT macros
- *	
- *	Revision 1.3  1998/10/01 07:03:00  gklug
- *	add: ISR for the usual interrupt source register
- *	
- *	Revision 1.2  1998/09/03 13:50:33  gklug
- *	add: function prototypes
- *	
- *	Revision 1.1  1998/08/27 11:50:21  gklug
- *	initial revision
- *	
- *
- *
- ******************************************************************************/
-
 /*
  *	Special Interrupt handler
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/ski2c.c linux-2.4.26-pre6/drivers/net/sk98lin/ski2c.c
--- linux-2.4.25/drivers/net/sk98lin/ski2c.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/ski2c.c	2004-03-25 00:16:50.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	ski2c.c
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.59 $
- * Date:	$Date: 2003/10/20 09:07:25 $
  * Purpose:	Functions to access Voltage and Temperature Sensor
  *
  ******************************************************************************/
@@ -22,219 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: ski2c.c,v $
- *	Revision 1.59  2003/10/20 09:07:25  rschmidt
- *	Added cast SK_U32 in SkI2cWrite() to avoid compiler warning.
- *	Editorial changes.
- *	
- *	Revision 1.58  2003/09/23 09:22:53  malthoff
- *	Parameter I2cDevSize added in SkI2cRead and SkI2cWrite to
- *	support larger devices on the TWSI bus.
- *	
- *	Revision 1.57  2003/01/28 09:17:38  rschmidt
- *	Fixed handling for sensors on YUKON Fiber.
- *	Editorial changes.
- *	
- *	Revision 1.56  2002/12/19 14:20:41  rschmidt
- *	Added debugging code in SkI2cWait().
- *	Replaced all I2C-write operations with function SkI2cWrite().
- *	Fixed compiler warning because of uninitialized 'Time' in SkI2cEvent().
- *	Editorial changes.
- *	
- *	Revision 1.55  2002/10/15 07:23:55  rschmidt
- *	Added setting of the GIYukon32Bit bool variable to distinguish
- *	32-bit adapters.
- *	Editorial changes (TWSI).
- *	
- *	Revision 1.54  2002/08/13 09:05:06  rschmidt
- *	Added new thresholds if VAUX is not available (GIVauxAvail).
- *	Merged defines for PHY PLL 3V3 voltage (A and B).
- *	Editorial changes.
- *	
- *	Revision 1.53  2002/08/08 11:04:53  rwahl
- *	Added missing comment for revision 1.51
- *	
- *	Revision 1.52  2002/08/08 10:09:02  jschmalz
- *	Sensor init state caused wrong error log entry
- *	
- *	Revision 1.51  2002/08/06 09:43:03  jschmalz
- *	Extensions and changes for Yukon
- *	
- *	Revision 1.50  2002/08/02 12:09:22  rschmidt
- *	Added support for YUKON sensors.
- *	Editorial changes.
- *	
- *	Revision 1.49  2002/07/30 11:07:52  rschmidt
- *	Replaced MaxSens init by update for Copper in SkI2cInit1(),
- *	because it was already initialized in SkI2cInit0().
- *	Editorial changes.
- *	
- *	Revision 1.48  2001/08/16 12:44:33  afischer
- *	LM80 sensor init values corrected
- *	
- *	Revision 1.47  2001/04/05 11:38:09  rassmann
- *	Set SenState to idle in SkI2cWaitIrq().
- *	Changed error message in SkI2cWaitIrq().
- *	
- *	Revision 1.46  2001/04/02 14:03:35  rassmann
- *	Changed pAC to IoC in SK_IN32().
- *	
- *	Revision 1.45  2001/03/21 12:12:49  rassmann
- *	Resetting I2C_READY interrupt in SkI2cInit1().
- *	
- *	Revision 1.44  2000/08/07 15:49:03  gklug
- *	Fix: SK_INFAST only in NetWare driver.
- *	
- *	Revision 1.43  2000/08/03 14:28:17  rassmann
- *	Added function to wait for I2C being ready before resetting the board.
- *	Replaced one duplicate "out of range" message with correct one.
- *	
- *	Revision 1.42  1999/11/22 13:35:12  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.41  1999/09/14 14:11:30  malthoff
- *	The 1000BT Dual Link adapter has got only one Fan.
- *	The second Fan has been removed.
- *	
- *	Revision 1.40  1999/05/27 13:37:27  malthoff
- *	Set divisor of 1 for fan count calculation.
- *	
- *	Revision 1.39  1999/05/20 14:54:43  malthoff
- *	I2c.DummyReads is not used in Diagnostics.
- *	
- *	Revision 1.38  1999/05/20 09:20:56  cgoos
- *	Changes for 1000Base-T (up to 9 sensors and fans).
- *	
- *	Revision 1.37  1999/03/25 15:11:36  gklug
- *	fix: reset error flag if sensor reads correct value
- *	
- *	Revision 1.36  1999/01/07 14:11:16  gklug
- *	fix: break added
- *	
- *	Revision 1.35  1999/01/05 15:31:49  gklug
- *	fix: CLEAR STAT command is now added correctly
- *	
- *	Revision 1.34  1998/12/01 13:45:16  gklug
- *	fix: introduced Init level, because we don't need reinits
- *	
- *	Revision 1.33  1998/11/09 14:54:25  malthoff
- *	Modify I2C Transfer Timeout handling for Diagnostics.
- *	
- *	Revision 1.32  1998/11/03 06:54:35  gklug
- *	fix: Need dummy reads at the beginning to init sensors
- *
- *	Revision 1.31  1998/11/03 06:42:42  gklug
- *	fix: select correctVIO range only if between warning levels
- *	
- *	Revision 1.30  1998/11/02 07:36:53  gklug
- *	fix: Error should not include WARNING message
- *	
- *	Revision 1.29  1998/10/30 15:07:43  malthoff
- *	Disable 'I2C does not compelete' error log for diagnostics.
- *	
- *	Revision 1.28  1998/10/22 09:48:11  gklug
- *	fix: SysKonnectFileId typo
- *	
- *	Revision 1.27  1998/10/20 09:59:46  gklug
- *	add: parameter to SkOsGetTime
- *	
- *	Revision 1.26  1998/10/09 06:10:59  malthoff
- *	Remove ID_sccs by SysKonnectFileId.
- *	
- *	Revision 1.25  1998/09/08 12:40:26  gklug
- *	fix: syntax error in if clause
- *	
- *	Revision 1.24  1998/09/08 12:19:42  gklug
- *	chg: INIT Level checking
- *	
- *	Revision 1.23  1998/09/08 07:37:20  gklug
- *	fix: log error if PCI_IO voltage sensor could not be initialized
- *	
- *	Revision 1.22  1998/09/04 08:30:03  malthoff
- *	Bugfixes during SK_DIAG testing:
- *	- correct NS2BCLK() macro
- *	- correct SkI2cSndDev()
- *	- correct SkI2cWait() loop waiting for an event
- *	
- *	Revision 1.21  1998/08/27 14:46:01  gklug
- *	chg: if-then-else replaced by switch
- *
- *	Revision 1.20  1998/08/27 14:40:07  gklug
- *	test: integral types
- *	
- *	Revision 1.19  1998/08/25 07:51:54  gklug
- *	fix: typos for compiling
- *	
- *	Revision 1.18  1998/08/25 06:12:24  gklug
- *	add: count errors and warnings
- *	fix: check not the sensor state but the ErrFlag!
- *	
- *	Revision 1.17  1998/08/25 05:56:48  gklug
- *	add: CheckSensor function
- *	
- *	Revision 1.16  1998/08/20 11:41:10  gklug
- *	chg: omit STRCPY macro by using char * as Sensor Description
- *	
- *	Revision 1.15  1998/08/20 11:37:35  gklug
- *	chg: change Ioc to IoC
- *	
- *	Revision 1.14  1998/08/20 11:32:52  gklug
- *	fix: Para compile error
- *	
- *	Revision 1.13  1998/08/20 11:27:41  gklug
- *	fix: Compile bugs with new awrning constants
- *	
- *	Revision 1.12  1998/08/20 08:53:05  gklug
- *	fix: compiler errors
- *	add: Threshold values
- *	
- *	Revision 1.11  1998/08/19 12:39:22  malthoff
- *	Compiler Fix: Some names have changed.
- *	
- *	Revision 1.10  1998/08/19 12:20:56  gklug
- *	fix: remove struct from C files (see CCC)
- *	
- *	Revision 1.9  1998/08/19 06:28:46  malthoff
- *	SkOsGetTime returns SK_U64 now.
- *	
- *	Revision 1.8  1998/08/17 13:53:33  gklug
- *	fix: Parameter of event function and its result
- *	
- *	Revision 1.7  1998/08/17 07:02:15  malthoff
- *	Modify the functions for accessing the I2C SW Registers.
- *	Modify SkI2cWait().
- *	Put Lm80RcvReg into sklm80.c
- *	Remove Compiler Errors.
- *	
- *	Revision 1.6  1998/08/14 07:13:20  malthoff
- *	remove pAc with pAC
- *	remove smc with pAC
- *	change names to new convention
- *
- *	Revision 1.5  1998/08/14 06:24:49  gklug
- *	add: init level 1 and 2
- *
- *	Revision 1.4  1998/08/12 14:31:12  gklug
- *	add: error log for unknown event
- *
- *	Revision 1.3  1998/08/12 13:37:04  gklug
- *	add: Init 0 function
- *
- *	Revision 1.2  1998/08/11 07:27:15  gklug
- *	add: functions of the interface
- *	adapt rest of source to C coding Conventions
- *	rmv: unnecessary code taken from Mona Lisa
- *
- *	Revision 1.1  1998/06/19 14:28:43  malthoff
- *	Created. Sources taken from ML Projekt.
- *	Sources have to be reworked for GE.
- *
- ******************************************************************************/
-
 /*
  *	I2C Protocol
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/sklm80.c linux-2.4.26-pre6/drivers/net/sk98lin/sklm80.c
--- linux-2.4.25/drivers/net/sk98lin/sklm80.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/sklm80.c	2004-03-25 00:21:45.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	sklm80.c
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.22 $
- * Date:	$Date: 2003/10/20 09:08:21 $
  * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
  *
  ******************************************************************************/
@@ -22,86 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: sklm80.c,v $
- *	Revision 1.22  2003/10/20 09:08:21  rschmidt
- *	Editorial changes.
- *	
- *	Revision 1.21  2003/09/23 09:29:04  malthoff
- *	Parameter Dev_Size added to macro SK_I2C_CTL.
- *	
- *	Revision 1.20  2002/08/13 09:16:27  rschmidt
- *	Changed return value for SkLm80ReadSensor() back to 'int'
- *	Editorial changes.
- *	
- *	Revision 1.19  2002/08/06 09:43:31  jschmalz
- *	Extensions and changes for Yukon.
- *	
- *	Revision 1.18  2002/08/02 12:26:57  rschmidt
- *	Editorial changes.
- *	
- *	Revision 1.17  1999/11/22 13:35:51  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.16  1999/05/27 14:05:47  malthoff
- *	Fans: Set SenVal to 0 if the fan value is 0 or 0xff. Both values
- *	are outside the limits (0: div zero error, 0xff: value not in
- *	range, assume 0).
- *	
- *	Revision 1.15  1999/05/27 13:38:51  malthoff
- *	Pervent from Division by zero errors.
- *	
- *	Revision 1.14  1999/05/20 09:20:01  cgoos
- *	Changes for 1000Base-T (Fan sensors).
- *	
- *	Revision 1.13  1998/10/22 09:48:14  gklug
- *	fix: SysKonnectFileId typo
- *	
- *	Revision 1.12  1998/10/09 06:12:06  malthoff
- *	Remove ID_sccs by SysKonnectFileId.
- *	
- *	Revision 1.11  1998/09/04 08:33:48  malthoff
- *	bug fix: SenState = SK_SEN_IDLE when
- *	leaving SK_SEN_VALEXT state
- *	
- *	Revision 1.10  1998/08/20 12:02:10  gklug
- *	fix: compiler warnings type mismatch
- *
- *	Revision 1.9  1998/08/20 11:37:38  gklug
- *	chg: change Ioc to IoC
- *	
- *	Revision 1.8  1998/08/19 12:20:58  gklug
- *	fix: remove struct from C files (see CCC)
- *	
- *	Revision 1.7  1998/08/17 07:04:57  malthoff
- *	Take SkLm80RcvReg() function from ski2c.c.
- *	Add IoC parameter to BREAK_OR_WAIT() macro.
- *	
- *	Revision 1.6  1998/08/14 07:11:28  malthoff
- *	remove pAc with pAC.
- *
- *	Revision 1.5  1998/08/14 06:46:55  gklug
- *	fix: temperature can get negative
- *
- *	Revision 1.4  1998/08/13 08:27:04  gklug
- *	add: temperature reading now o.k.
- *	fix: pSen declaration, SK_ERR_LOG call, ADDR macro
- *
- *	Revision 1.3  1998/08/13 07:28:21  gklug
- *	fix: pSen was wrong initialized
- *	add: correct conversion for voltage readings
- *
- *	Revision 1.2  1998/08/11 07:52:14  gklug
- *	add: Lm80 read sensor function
- *
- *	Revision 1.1  1998/07/17 09:57:12  gklug
- *	initial version
- *
- ******************************************************************************/
-
 /*
 	LM80 functions
 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skproc.c linux-2.4.26-pre6/drivers/net/sk98lin/skproc.c
--- linux-2.4.25/drivers/net/sk98lin/skproc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skproc.c	2004-03-25 00:17:22.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skproc.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/12/11 16:03:57 $
  * Purpose:	Funktions to display statictic data
  *
  ******************************************************************************/
@@ -24,98 +22,6 @@
  *	The information in this file is provided "AS IS" without warranty.
  *
  ******************************************************************************/
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skproc.c,v $
- *	Revision 1.11  2003/12/11 16:03:57  mlindner
- *	Fix: Create backup from pnmi data structure
- *	
- *	Revision 1.10  2003/11/19 16:25:36  mlindner
- *	Fix: Print output as 64-bit digit
- *	
- *	Revision 1.9  2003/11/17 13:29:05  mlindner
- *	Fix: Editorial changes
- *	
- *	Revision 1.8  2003/11/13 14:18:48  rroesler
- *	Fix: added latest changes regarding the use of the proc system
- *	
- *	Revision 1.7  2003/11/10 09:35:07  rroesler
- *	Fix: diag backup restore of PNMI structure
- *	
- *	Revision 1.6  2003/11/07 17:31:39  rroesler
- *	Add: security counter for the proc file system
- *	
- *	Revision 1.5  2003/10/07 08:17:08  mlindner
- *	Fix: Copyright changes
- *	
- *	Revision 1.4  2003/09/01 15:29:24  mlindner
- *	Fix: Editorial changes
- *	
- *	Revision 1.3  2003/08/29 12:30:58  mlindner
- *	Add: Version entry in the proc file system
- *	
- *	Revision 1.2  2003/08/12 16:45:29  mlindner
- *	Add: Removed SkNumber and SkDoDiv
- *	Add: Counter output as (unsigned long long)
- *	
- *	Revision 1.1  2003/07/18 13:39:57  rroesler
- *	Fix: Re-enter after CVS crash
- *	
- *	Revision 1.8  2003/06/27 14:41:42  rroesler
- *	Corrected compiler-warning kernel 2.2
- *	
- *	Revision 1.7  2003/06/27 12:09:51  rroesler
- *	corrected minor edits
- *	
- *	Revision 1.6  2003/05/26 12:58:53  mlindner
- *	Add: Support for Kernel 2.5/2.6
- *	
- *	Revision 1.5  2003/03/19 14:40:47  mlindner
- *	Fix: Editorial changes
- *	
- *	Revision 1.4  2003/02/25 14:16:37  mlindner
- *	Fix: Copyright statement
- *	
- *	Revision 1.3  2002/10/02 12:59:51  mlindner
- *	Add: Support for Yukon
- *	Add: Speed check and setup
- *	Add: Merge source for kernel 2.2.x and 2.4.x
- *	Add: Read sensor names directly from VPD
- *	Fix: Volt values
- *	
- *	Revision 1.2.2.7  2002/01/14 12:45:15  mlindner
- *	Fix: Editorial changes
- *	
- *	Revision 1.2.2.6  2001/12/06 15:26:07  mlindner
- *	Fix: Return value of proc_read
- *	
- *	Revision 1.2.2.5  2001/12/06 09:57:39  mlindner
- *	New ProcFs entries
- *	
- *	Revision 1.2.2.4  2001/09/05 12:16:02  mlindner
- *	Add: New ProcFs entries
- *	Fix: Counter Errors (Jumbo == to long errors)
- *	Fix: Kernel error compilation
- *	Fix: too short counters
- *	
- *	Revision 1.2.2.3  2001/06/25 07:26:26  mlindner
- *	Add: More error messages
- *	
- *	Revision 1.2.2.2  2001/03/15 12:50:13  mlindner
- *	fix: ProcFS owner protection
- *	
- *	Revision 1.2.2.1  2001/03/12 16:43:48  mlindner
- *	chg: 2.4 requirements for procfs
- *	
- *	Revision 1.1  2001/01/22 14:15:31  mlindner
- *	added ProcFs functionality
- *	Dual Net functionality integrated
- *	Rlmt networks added
- *	
- *
- ******************************************************************************/
 
 #include <linux/proc_fs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skqueue.c linux-2.4.26-pre6/drivers/net/sk98lin/skqueue.c
--- linux-2.4.25/drivers/net/sk98lin/skqueue.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skqueue.c	2004-03-25 00:18:20.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skqueue.c
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.20 $
- * Date:	$Date: 2003/09/16 13:44:00 $
  * Purpose:	Management of an event queue.
  *
  ******************************************************************************/
@@ -22,77 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skqueue.c,v $
- *	Revision 1.20  2003/09/16 13:44:00  rschmidt
- *	Added (C) Marvell to SysKonnectFileId
- *	Editorial changes
- *	
- *	Revision 1.19  2003/05/13 18:00:07  mkarl
- *	Removed calls to RLMT, TWSI, and PNMI for SLIM driver (SK_SLIM).
- *	Editorial changes.
- *	
- *	Revision 1.18  2002/05/07 14:11:11  rwahl
- *	Fixed Watcom Precompiler error.
- *	
- *	Revision 1.17  2002/03/25 10:06:41  mkunz
- *	SkIgnoreEvent deleted
- *	
- *	Revision 1.16  2002/03/15 10:51:59  mkunz
- *	Added event classes for link aggregation
- *	
- *	Revision 1.15  1999/11/22 13:36:29  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.14  1998/10/15 15:11:35  gklug
- *	fix: ID_sccs to SysKonnectFileId
- *	
- *	Revision 1.13  1998/09/08 08:47:52  gklug
- *	add: init level handling
- *	
- *	Revision 1.12  1998/09/08 07:43:20  gklug
- *	fix: Sirq Event function name
- *	
- *	Revision 1.11  1998/09/08 05:54:34  gklug
- *	chg: define SK_CSUM is replaced by SK_USE_CSUM
- *	
- *	Revision 1.10  1998/09/03 14:14:49  gklug
- *	add: CSUM and HWAC Eventclass and function.
- *	
- *	Revision 1.9  1998/08/19 09:50:50  gklug
- *	fix: remove struct keyword from c-code (see CCC) add typedefs
- *	
- *	Revision 1.8  1998/08/17 13:43:11  gklug
- *	chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR
- *	
- *	Revision 1.7  1998/08/14 07:09:11  gklug
- *	fix: chg pAc -> pAC
- *	
- *	Revision 1.6  1998/08/11 12:13:14  gklug
- *	add: return code feature of Event service routines
- *	add: correct Error log calls
- *	
- *	Revision 1.5  1998/08/07 12:53:45  gklug
- *	fix: first compiled version
- *	
- *	Revision 1.4  1998/08/07 09:20:48  gklug
- *	adapt functions to C coding conventions.
- *	
- *	Revision 1.3  1998/08/05 11:29:32  gklug
- *	rmv: Timer event entry. Timer will queue event directly
- *	
- *	Revision 1.2  1998/07/31 11:22:40  gklug
- *	Initial version
- *	
- *	Revision 1.1  1998/07/30 15:14:01  gklug
- *	Initial version. Adapted from SMT
- *
- ******************************************************************************/
-
-
 /*
  *	Event queue and dispatcher
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skrlmt.c linux-2.4.26-pre6/drivers/net/sk98lin/skrlmt.c
--- linux-2.4.25/drivers/net/sk98lin/skrlmt.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skrlmt.c	2004-03-25 00:20:37.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skrlmt.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.69 $
- * Date:	$Date: 2003/04/15 09:39:22 $
  * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
  *
  ******************************************************************************/
@@ -24,254 +22,6 @@
 
 /******************************************************************************
  *
- * History:
- *
- *	$Log: skrlmt.c,v $
- *	Revision 1.69  2003/04/15 09:39:22  tschilli
- *	Copyright messages changed.
- *	"#error C++ is not yet supported." removed.
- *	
- *	Revision 1.68  2003/01/31 15:26:56  rschmidt
- *	Added init for local variables in RlmtInit().
- *	
- *	Revision 1.67  2003/01/31 14:12:41  mkunz
- *	single port adapter runs now with two identical MAC addresses
- *	
- *	Revision 1.66  2002/09/23 15:14:19  rwahl
- *	- Reset broadcast timestamp on link down.
- *	- Editorial corrections.
- *	
- *	Revision 1.65  2002/07/22 14:29:48  rwahl
- *	- Removed BRK statement from debug check.
- *	
- *	Revision 1.64  2001/11/28 19:36:14  rwahl
- *	- RLMT Packets sent to an invalid MAC address in CLP/CLPSS mode
- *	  (#10650).
- *	- Reworked fix for port switching in CLS mode (#10639)
- *	 (no dependency to RLMT module).
- *	- Enabled dbg output for entry/exit of event functions.
- *	- Editorial changes.
- *	
- *	Revision 1.63  2001/10/26 07:53:18  afischer
- *	Port switching bug in `check local link` mode
- *	
- *	Revision 1.62  2001/07/03 12:16:30  mkunz
- *	New Flag ChgBcPrio (Change priority of last broadcast received)
- *	
- *	Revision 1.61  2001/03/14 12:52:08  rassmann
- *	Fixed reporting of active port up/down to PNMI.
- *	
- *	Revision 1.60  2001/02/21 16:02:25  gklug
- *	fix: when RLMT starts set Active Port for PNMI
- *	
- *	Revision 1.59  2001/02/16 14:38:19  rassmann
- *	Initializing some pointers earlier in the init phase.
- *	Rx Mbufs are freed if the net which they belong to is stopped.
- *	
- *	Revision 1.58  2001/02/14 14:06:31  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.57  2001/02/05 14:25:26  rassmann
- *	Prepared RLMT for transparent operation.
- *	
- *	Revision 1.56  2001/01/30 10:29:09  rassmann
- *	Not checking switching befor RlmtStart.
- *	Editorial changes.
- *	
- *	Revision 1.55  2001/01/22 13:41:38  rassmann
- *	Supporting two nets on dual-port adapters.
- *	
- *	Revision 1.54  2000/11/30 13:25:07  rassmann
- *	Setting SK_TICK_INCR to 1 by default.
- *	
- *	Revision 1.53  2000/11/30 10:48:07  cgoos
- *	Changed definition of SK_RLMT_BC_DELTA.
- *	
- *	Revision 1.52  2000/11/27 12:50:03  rassmann
- *	Checking ports after receiving broadcasts.
- *	
- *	Revision 1.51  2000/11/17 08:58:00  rassmann
- *	Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event.
- *	
- *	Revision 1.50  2000/11/09 12:24:34  rassmann
- *	Indicating that segmentation check is not running anymore after
- *	  SkRlmtCheckSeg().
- *	Restarting segmentation timer after segmentation log.
- *	Editorial changes.
- *	
- *	Revision 1.49  1999/11/22 13:38:02  cgoos
- *	Changed license header to GPL.
- *	Added initialization to some variables to avoid compiler warnings.
- *	
- *	Revision 1.48  1999/10/04 14:01:17  rassmann
- *	Corrected reaction to reception of BPDU frames (#10441).
- *	
- *	Revision 1.47  1999/07/20 12:53:36  rassmann
- *	Fixed documentation errors for lookahead macros.
- *	
- *	Revision 1.46  1999/05/28 13:29:16  rassmann
- *	Replaced C++-style comment.
- *	
- *	Revision 1.45  1999/05/28 13:28:08  rassmann
- *	Corrected syntax error (xxx).
- *	
- *	Revision 1.44  1999/05/28 11:15:54  rassmann
- *	Changed behaviour to reflect Design Spec v1.2.
- *	Controlling Link LED(s).
- *	Introduced RLMT Packet Version field in RLMT Packet.
- *	Newstyle lookahead macros (checking meta-information before looking at
- *	  the packet).
- *	
- *	Revision 1.43  1999/01/28 13:12:43  rassmann
- *	Corrected Lookahead (bug introduced in previous Rev.).
- *	
- *	Revision 1.42  1999/01/28 12:50:41  rassmann
- *	Not using broadcast time stamps in CheckLinkState mode.
- *	
- *	Revision 1.41  1999/01/27 14:13:02  rassmann
- *	Monitoring broadcast traffic.
- *	Switching more reliably and not too early if switch is
- *	 configured for spanning tree.
- *	
- *	Revision 1.40  1999/01/22 13:17:30  rassmann
- *	Informing PNMI of NET_UP.
- *	Clearing RLMT multicast addresses before setting them for the first time.
- *	Reporting segmentation earlier, setting a "quiet time"
- *	 after a report.
- *	
- *	Revision 1.39  1998/12/10 15:29:53  rassmann
- *	Corrected SuspectStatus in SkRlmtBuildCheckChain().
- *	Corrected CHECK_SEG mode.
- *	
- *	Revision 1.38  1998/12/08 13:11:23  rassmann
- *	Stopping SegTimer at RlmtStop.
- *	
- *	Revision 1.37  1998/12/07 16:51:42  rassmann
- *	Corrected comments.
- *	
- *	Revision 1.36  1998/12/04 10:58:56  rassmann
- *	Setting next pointer to NULL when receiving.
- *	
- *	Revision 1.35  1998/12/03 16:12:42  rassmann
- *	Ignoring/correcting illegal PrefPort values.
- *	
- *	Revision 1.34  1998/12/01 11:45:35  rassmann
- *	Code cleanup.
- *	
- *	Revision 1.33  1998/12/01 10:29:32  rassmann
- *	Starting standby ports before getting the net up.
- *	Checking if a port is started when the link comes up.
- *	
- *	Revision 1.32  1998/11/30 16:19:50  rassmann
- *	New default for PortNoRx.
- *	
- *	Revision 1.31  1998/11/27 19:17:13  rassmann
- *	Corrected handling of LINK_DOWN coming shortly after LINK_UP.
- *	
- *	Revision 1.30  1998/11/24 12:37:31  rassmann
- *	Implemented segmentation check.
- *	
- *	Revision 1.29  1998/11/18 13:04:32  rassmann
- *	Secured PortUpTimer event.
- *	Waiting longer before starting standby port(s).
- *	
- *	Revision 1.28  1998/11/17 13:43:04  rassmann
- *	Handling (logical) tx failure.
- *	Sending packet on logical address after PORT_SWITCH.
- *	
- *	Revision 1.27  1998/11/13 17:09:50  rassmann
- *	Secured some events against being called in wrong state.
- *	
- *	Revision 1.26  1998/11/13 16:56:54  rassmann
- *	Added macro version of SkRlmtLookaheadPacket.
- *	
- *	Revision 1.25  1998/11/06 18:06:04  rassmann
- *	Corrected timing when RLMT checks fail.
- *	Clearing tx counter earlier in periodical checks.
- *	
- *	Revision 1.24  1998/11/05 10:37:27  rassmann
- *	Checking destination address in Lookahead.
- *	
- *	Revision 1.23  1998/11/03 13:53:49  rassmann
- *	RLMT should switch now (at least in mode 3).
- *	
- *	Revision 1.22  1998/10/29 14:34:49  rassmann
- *	Clearing SK_RLMT struct at startup.
- *	Initializing PortsUp during SK_RLMT_START.
- *	
- *	Revision 1.21  1998/10/28 11:30:17  rassmann
- *	Default mode is now SK_RLMT_CHECK_LOC_LINK.
- *	
- *	Revision 1.20  1998/10/26 16:02:03  rassmann
- *	Ignoring LINK_DOWN for links that are down.
- *	
- *	Revision 1.19  1998/10/22 15:54:01  rassmann
- *	Corrected EtherLen.
- *	Starting Link Check when second port comes up.
- *	
- *	Revision 1.18  1998/10/22 11:39:50  rassmann
- *	Corrected signed/unsigned mismatches.
- *	Corrected receive list handling and address recognition.
- *	
- *	Revision 1.17  1998/10/19 17:01:20  rassmann
- *	More detailed checking of received packets.
- *	
- *	Revision 1.16  1998/10/15 15:16:34  rassmann
- *	Finished Spanning Tree checking.
- *	Checked with lint.
- *	
- *	Revision 1.15  1998/09/24 19:16:07  rassmann
- *	Code cleanup.
- *	Introduced Timer for PORT_DOWN due to no RX.
- *	
- *	Revision 1.14  1998/09/18 20:27:14  rassmann
- *	Added address override.
- *	
- *	Revision 1.13  1998/09/16 11:31:48  rassmann
- *	Including skdrv1st.h again. :(
- *	
- *	Revision 1.12  1998/09/16 11:09:50  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.11  1998/09/15 12:32:03  rassmann
- *	Syntax correction.
- *	
- *	Revision 1.10  1998/09/15 11:28:49  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.9  1998/09/14 17:07:37  rassmann
- *	Added code for port checking via LAN.
- *	Changed Mbuf definition.
- *	
- *	Revision 1.8  1998/09/07 11:14:14  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.7  1998/09/07 09:06:07  rassmann
- *	Syntax corrections.
- *	
- *	Revision 1.6  1998/09/04 19:41:33  rassmann
- *	Syntax corrections.
- *	Started entering code for checking local links.
- *	
- *	Revision 1.5  1998/09/04 12:14:27  rassmann
- *	Interface cleanup.
- *	
- *	Revision 1.4  1998/09/02 16:55:28  rassmann
- *	Updated to reflect new DRV/HWAC/RLMT interface.
- *	
- *	Revision 1.3  1998/08/27 14:29:03  rassmann
- *	Code cleanup.
- *	
- *	Revision 1.2  1998/08/27 14:26:24  rassmann
- *	Updated interface.
- *	
- *	Revision 1.1  1998/08/21 08:26:49  rassmann
- *	First public version.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
  * Description:
  *
  * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/sktimer.c linux-2.4.26-pre6/drivers/net/sk98lin/sktimer.c
--- linux-2.4.25/drivers/net/sk98lin/sktimer.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/sktimer.c	2004-03-25 00:17:30.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	sktimer.c
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/09/16 13:46:51 $
  * Purpose:	High level timer functions.
  *
  ******************************************************************************/
@@ -22,60 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: sktimer.c,v $
- *	Revision 1.14  2003/09/16 13:46:51  rschmidt
- *	Added (C) Marvell to SysKonnectFileId
- *	Editorial changes
- *	
- *	Revision 1.13  2003/05/13 18:01:01  mkarl
- *	Editorial changes.
- *	
- *	Revision 1.12  1999/11/22 13:38:51  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.11  1998/12/17 13:24:13  gklug
- *	fix: restart problem: do NOT destroy timer queue if init 1 is done
- *	
- *	Revision 1.10  1998/10/15 15:11:36  gklug
- *	fix: ID_sccs to SysKonnectFileId
- *	
- *	Revision 1.9  1998/09/15 15:15:04  cgoos
- *	Changed TRUE/FALSE to SK_TRUE/SK_FALSE
- *	
- *	Revision 1.8  1998/09/08 08:47:55  gklug
- *	add: init level handling
- *	
- *	Revision 1.7  1998/08/19 09:50:53  gklug
- *	fix: remove struct keyword from c-code (see CCC) add typedefs
- *	
- *	Revision 1.6  1998/08/17 13:43:13  gklug
- *	chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR
- *	
- *	Revision 1.5  1998/08/14 07:09:14  gklug
- *	fix: chg pAc -> pAC
- *	
- *	Revision 1.4  1998/08/07 12:53:46  gklug
- *	fix: first compiled version
- *	
- *	Revision 1.3  1998/08/07 09:31:53  gklug
- *	fix: delta spelling
- *	
- *	Revision 1.2  1998/08/07 09:31:02  gklug
- *	adapt functions to new c coding conventions
- *	rmv: "fast" handling
- *	chg: inserting of new timer in queue.
- *	chg: event queue generation when timer runs out
- *	
- *	Revision 1.1  1998/08/05 11:27:55  gklug
- *	first version: adapted from SMT
- *
- ******************************************************************************/
-
-
 /*
  *	Event queue and dispatcher
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skvpd.c linux-2.4.26-pre6/drivers/net/sk98lin/skvpd.c
--- linux-2.4.25/drivers/net/sk98lin/skvpd.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skvpd.c	2004-03-25 00:20:27.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skvpd.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/01/13 10:42:45 $
  * Purpose:	Shared software to read and write VPD data
  *
  ******************************************************************************/
@@ -21,145 +19,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skvpd.c,v $
- *	Revision 1.37  2003/01/13 10:42:45  rschmidt
- *	Replaced check for PCI device Id from YUKON with GENESIS
- *	to set the VPD size in VpdInit()
- *	Editorial changes
- *	
- *	Revision 1.36  2002/11/14 15:16:56  gheinig
- *	Added const specifier to key and buf parameters for VpdPara, VpdRead
- *	and VpdWrite for Diag 7 GUI
- *	
- *	Revision 1.35  2002/10/21 14:31:59  gheinig
- *	Took out CVS web garbage at head of file
- *	
- *	Revision 1.34  2002/10/21 11:47:24  gheinig
- *	Reverted to version 1.32 due to unwanted commit
- *	
- *	Revision 1.32  2002/10/14 16:04:29  rschmidt
- *	Added saving of VPD ROM Size from PCI_OUR_REG_2
- *	Avoid reading of PCI_OUR_REG_2 in VpdTransferBlock()
- *	Editorial changes
- *	
- *	Revision 1.31  2002/09/10 09:21:32  mkarl
- *	Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis
- *	
- *	Revision 1.30  2002/09/09 14:43:03  mkarl
- *	changes for diagnostics in order to read VPD data before the adapter
- *	has been initialized
- *	editorial changes
- *	
- *	Revision 1.29  2002/07/26 13:20:43  mkarl
- *	added Yukon support
- *	save size of VPD in pAC->vpd.vpd_size
- *	
- *	Revision 1.28  2002/04/02 15:31:47  afischer
- *	Bug fix in VpdWait()
- *	
- *	Revision 1.27  2000/08/10 11:29:06  rassmann
- *	Editorial changes.
- *	Preserving 32-bit alignment in structs for the adapter context.
- *	Removed unused function VpdWriteDword() (#if 0).
- *	Made VpdReadKeyword() available for SKDIAG only.
- *	
- *	Revision 1.26  2000/06/13 08:00:01  mkarl
- *	additional cast to avoid compile problems in 64 bit environment
- *	
- *	Revision 1.25  1999/11/22 13:39:32  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.24  1999/03/11 14:25:49  malthoff
- *	Replace __STDC__ with SK_KR_PROTO.
- *	
- *	Revision 1.23  1999/01/11 15:13:11  gklug
- *	fix: syntax error
- *	
- *	Revision 1.22  1998/10/30 06:41:15  gklug
- *	rmv: WARNING
- *	
- *	Revision 1.21  1998/10/29 07:15:14  gklug
- *	fix: Write Stream function needs verify.
- *	
- *	Revision 1.20  1998/10/28 18:05:08  gklug
- *	chg: no DEBUG in VpdMayWrite
- *	
- *	Revision 1.19  1998/10/28 15:56:11  gklug
- *	fix: Return len at end of ReadStream
- *	fix: Write even less than 4 bytes correctly
- *	
- *	Revision 1.18  1998/10/28 09:00:47  gklug
- *	fix: unreferenced local vars
- *	
- *	Revision 1.17  1998/10/28 08:25:45  gklug
- *	fix: WARNING
- *	
- *	Revision 1.16  1998/10/28 08:17:30  gklug
- *	fix: typo
- *	
- *	Revision 1.15  1998/10/28 07:50:32  gklug
- *	fix: typo
- *	
- *	Revision 1.14  1998/10/28 07:20:38  gklug
- *	chg: Interface functions to use IoC as parameter as well
- *	fix: VpdRead/WriteDWord now returns SK_U32
- *	chg: VPD_IN/OUT names conform to SK_IN/OUT
- *	add: usage of VPD_IN/OUT8 macros
- *	add: VpdRead/Write Stream functions to r/w a stream of data
- *	fix: VpdTransferBlock swapped illegal
- *	add: VpdMayWrite
- *	
- *	Revision 1.13  1998/10/22 10:02:37  gklug
- *	fix: SysKonnectFileId typo
- *	
- *	Revision 1.12  1998/10/20 10:01:01  gklug
- *	fix: parameter to SkOsGetTime
- *	
- *	Revision 1.11  1998/10/15 12:51:48  malthoff
- *	Remove unrequired parameter p in vpd_setup_para().
- *	
- *	Revision 1.10  1998/10/08 14:52:43  malthoff
- *	Remove CvsId by SysKonnectFileId.
- *	
- *	Revision 1.9  1998/09/16 07:33:52  malthoff
- *	replace memcmp() by SK_MEMCMP and
- *	memcpy() by SK_MEMCPY() to be
- *	independent from the 'C' Standard Library.
- *	
- *	Revision 1.8  1998/08/19 12:52:35  malthoff
- *	compiler fix: use SK_VPD_KEY instead of S_VPD.
- *	
- *	Revision 1.7  1998/08/19 08:14:01  gklug
- *	fix: remove struct keyword as much as possible from the C-code (see CCC)
- *	
- *	Revision 1.6  1998/08/18 13:03:58  gklug
- *	SkOsGetTime now returns SK_U64
- *	
- *	Revision 1.5  1998/08/18 08:17:29  malthoff
- *	Ensure we issue a VPD read in vpd_read_dword().
- *	Discard all VPD keywords other than Vx or Yx, where
- *	x is '0..9' or 'A..Z'.
- *	
- *	Revision 1.4  1998/07/03 14:52:19  malthoff
- *	Add category SK_DBGCAT_FATAL to some debug macros.
- *	bug fix: correct the keyword name check in vpd_write().
- *	
- *	Revision 1.3  1998/06/26 11:16:53  malthoff
- *	Correct the modified File Identifier.
- *	
- *	Revision 1.2  1998/06/26 11:13:43  malthoff
- *	Modify the File Identifier.
- *	
- *	Revision 1.1  1998/06/19 14:11:08  malthoff
- *	Created, Tests with AIX were performed successfully
- *	
- *
- ******************************************************************************/
-
 /*
 	Please refer skvpd.txt for infomation how to include this module
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skxmac2.c linux-2.4.26-pre6/drivers/net/sk98lin/skxmac2.c
--- linux-2.4.25/drivers/net/sk98lin/skxmac2.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sk98lin/skxmac2.c	2004-03-25 00:19:28.000000000 +0000
@@ -2,8 +2,6 @@
  *
  * Name:	skxmac2.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.102 $
- * Date:	$Date: 2003/10/02 16:53:58 $
  * Purpose:	Contains functions to initialize the MACs and PHYs
  *
  ******************************************************************************/
@@ -22,461 +20,6 @@
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- * History:
- *
- *	$Log: skxmac2.c,v $
- *	Revision 1.102  2003/10/02 16:53:58  rschmidt
- *	Changed setting of GMAC parameters with new macros.
- *	Added define SLIM around SkGm...LowPowerMode().
- *	Editorial changes.
- *	
- *	Revision 1.101  2003/09/16 14:49:07  rschmidt
- *	Added routines SkGmClearRst(), SkXmClearRst, SkMacClearRst().
- *	Added WA code for Yukon-Lite's COMA mode in SkGmHardRst().
- *	Replaced PCI-Config R/W through internal access.
- *	Fixed return from coma mode in SkGmLeaveLowPowerMode().
- *	Fixed compiler warnings for different types.
- *	Editorial changes.
- *	
- *	Revision 1.100  2003/09/16 07:09:11  mschmid
- *	Added functions SkGmEnterLowPowerMode() and
- *	SkGmLeaveLowPowerMode()
- *	
- *	Revision 1.99  2003/07/11 12:19:33  rschmidt
- *	Reduced init values for Master & Slave downshift counters to
- *	minimum values.
- *	Editorial changes.
- *	
- *	Revision 1.98  2003/07/04 12:53:56  rschmidt
- *	Changed setting of downshift feature in SkGmInitPhyMarv().
- *	Enabled downshift feature only for para 'Speed' set to 'Auto'.
- *	Changed init values for Master & Slave downshift counters.
- *	Editorial changes.
- *	
- *	Revision 1.97  2003/05/28 15:53:47  rschmidt
- *	Removed setting of Yukon PHY's 'force link good' in loopback mode.
- *	Replaced call pFnMacOverflow() with SkXmOverflowStatus() resp.
- *	SkGmOverflowStatus().
- *	Editorial changes.
- *	
- *	Revision 1.96  2003/05/13 17:37:11  mkarl
- *	Removed calls to PNMI for SLIM driver.
- *	Added SK_FAR for PXE.
- *	Separated code pathes not used for SLIM driver.
- *	Some further separations for YUKON and GENESIS.
- *	Editorial changes.
- *	
- *	Revision 1.95  2003/05/06 13:09:53  rschmidt
- *	Changed init sequence for auto-negotiation disabled in SkGmInitMac().
- *	Added defines around GENESIS resp. YUKON branches to reduce
- *	code size for PXE.
- *	Editorial changes.
- *	
- *	Revision 1.94  2003/04/10 14:36:40  rschmidt
- *	Fixed define for debug code in SkGmInitPhyMarv().
- *	
- *	Revision 1.93  2003/04/08 16:58:16  rschmidt
- *	Changed initialisation of GMAC and GPHY for disabling
- *	Flow-Control with parameter 'none' (Bug Id #10769).
- *	Changed init for blinking active LED and normal duplex LED
- *	depending on value from GILedBlinkCtrl (LED Blink Control).
- *	Added control for Link100 LED.
- *	Changed handling for different PhyTypes for source code
- *	portability to PXE, UNDI.
- *	Editorial changes.
- *	
- *	Revision 1.92  2003/03/31 07:12:33  mkarl
- *	Restore PHY_MARV_AUNE_ADV after writing to GM_GP_CTRL in order to make
- *	auto-negotiation of limited flow-control possible.
- *	Corrected Copyright.
- *	Editorial changes.
- *	
- *	Revision 1.91  2003/02/05 15:09:34  rschmidt
- *	Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv().
- *	Disabled auto-update for speed, duplex and flow-control when
- *	auto-negotiation is not enabled (Bug Id #10766).
- *	Editorial changes.
- *	
- *	Revision 1.90  2003/01/29 13:35:19  rschmidt
- *	Increment Rx FIFO Overflow counter only in DEBUG-mode.
- *	Corrected define for blinking active LED.
- *	
- *	Revision 1.89  2003/01/28 16:37:45  rschmidt
- *	Changed init for blinking active LED
- *	
- *	Revision 1.88  2003/01/28 10:09:38  rschmidt
- *	Added debug outputs in SkGmInitMac().
- *	Added customized init of LED registers in SkGmInitPhyMarv(),
- *	for blinking active LED (#ifdef ACT_LED_BLINK) and
- *	for normal duplex LED (#ifdef DUP_LED_NORMAL).
- *	Editorial changes.
- *	
- *	Revision 1.87  2002/12/10 14:39:05  rschmidt
- *	Improved initialization of GPHY in SkGmInitPhyMarv().
- *	Editorial changes.
- *	
- *	Revision 1.86  2002/12/09 15:01:12  rschmidt
- *	Added setup of Ext. PHY Specific Ctrl Reg (downshift feature).
- *	
- *	Revision 1.85  2002/12/05 14:09:16  rschmidt
- *	Improved avoiding endless loop in SkGmPhyRead(), SkGmPhyWrite().
- *	Added additional advertising for 10Base-T when 100Base-T is selected.
- *	Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter.
- *	Editorial changes.
- *	
- *	Revision 1.84  2002/11/15 12:50:09  rschmidt
- *	Changed SkGmCableDiagStatus() when getting results.
- *	
- *	Revision 1.83  2002/11/13 10:28:29  rschmidt
- *	Added some typecasts to avoid compiler warnings.
- *	
- *	Revision 1.82  2002/11/13 09:20:46  rschmidt
- *	Replaced for(..) with do {} while (...) in SkXmUpdateStats().
- *	Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic().
- *	Added SkGmCableDiagStatus() for Virtual Cable Test (VCT).
- *	Editorial changes.
- *	
- *	Revision 1.81  2002/10/28 14:28:08  rschmidt
- *	Changed MAC address setup for GMAC in SkGmInitMac().
- *	Optimized handling of counter overflow IRQ in SkGmOverflowStatus().
- *	Editorial changes.
- *	
- *	Revision 1.80  2002/10/14 15:29:44  rschmidt
- *	Corrected disabling of all PHY IRQs.
- *	Added WA for deviation #16 (address used for pause packets).
- *	Set Pause Mode in SkMacRxTxEnable() only for Genesis.
- *	Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode.
- *	SkXmTimeStamp() replaced by SkMacTimeStamp().
- *	Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq().
- *	Editorial changes.
- *	
- *	Revision 1.79  2002/10/10 15:55:36  mkarl
- *	changes for PLinkSpeedUsed
- *	
- *	Revision 1.78  2002/09/12 09:39:51  rwahl
- *	Removed deactivate code for SIRQ overflow event separate for TX/RX.
- *	
- *	Revision 1.77  2002/09/09 12:26:37  mkarl
- *	added handling for Yukon to SkXmTimeStamp
- *	
- *	Revision 1.76  2002/08/21 16:41:16  rschmidt
- *	Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE.
- *	Added forced speed settings in SkGmInitPhyMarv().
- *	Added settings of full/half duplex capabilities for YUKON Fiber.
- *	Editorial changes.
- *	
- *	Revision 1.75  2002/08/16 15:12:01  rschmidt
- *	Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
- *	Added function SkMacHashing() for ADDR-Module.
- *	Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced
- *	with macros).
- *	Removed functions SkGmGetMuxConfig().
- *	Added HWCFG_MODE init for YUKON Fiber.
- *	Changed initialization of GPHY in SkGmInitPhyMarv().
- *	Changed check of parameter in SkXmMacStatistic().
- *	Editorial changes.
- *	
- *	Revision 1.74  2002/08/12 14:00:17  rschmidt
- *	Replaced usage of Broadcom PHY Ids with defines.
- *	Corrected error messages in SkGmMacStatistic().
- *	Made SkMacPromiscMode() public for ADDR-Module.
- *	Editorial changes.
- *	
- *	Revision 1.73  2002/08/08 16:26:24  rschmidt
- *	Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac().
- *	Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM.
- *	Editorial changes.
- *	
- *	Revision 1.72  2002/07/24 15:11:19  rschmidt
- *	Fixed wrong placement of parenthesis.
- *	Editorial changes.
- *	
- *	Revision 1.71  2002/07/23 16:05:18  rschmidt
- *	Added global functions for PHY: SkGePhyRead(), SkGePhyWrite().
- *	Fixed Tx Counter Overflow IRQ (Bug ID #10730).
- *	Editorial changes.
- *	
- *	Revision 1.70  2002/07/18 14:27:27  rwahl
- *	Fixed syntax error.
- *	
- *	Revision 1.69  2002/07/17 17:08:47  rwahl
- *	Fixed check in SkXmMacStatistic().
- *	
- *	Revision 1.68  2002/07/16 07:35:24  rwahl
- *	Removed check for cleared mib counter in SkGmResetCounter().
- *	
- *	Revision 1.67  2002/07/15 18:35:56  rwahl
- *	Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(),
- *	  SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(),
- *	  SkXmOverflowStatus(), SkGmOverflowStatus().
- *	Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both
- *	  RX & TX.
- *	Changes to SkGmInitMac(): call to SkGmResetCounter().
- *	Editorial changes.
- *	
- *	Revision 1.66  2002/07/15 15:59:30  rschmidt
- *	Added PHY Address in SkXmPhyRead(), SkXmPhyWrite().
- *	Added MIB Clear Counter in SkGmInitMac().
- *	Added Duplex and Flow-Control settings.
- *	Reset all Multicast filtering Hash reg. in SkGmInitMac().
- *	Added new function: SkGmGetMuxConfig().
- *	Editorial changes.
- *	
- *	Revision 1.65  2002/06/10 09:35:39  rschmidt
- *	Replaced C++ comments (//).
- *	Added #define VCPU around VCPUwaitTime.
- *	Editorial changes.
- *	
- *	Revision 1.64  2002/06/05 08:41:10  rschmidt
- *	Added function for XMAC2: SkXmTimeStamp().
- *	Added function for YUKON: SkGmSetRxCmd().
- *	Changed SkGmInitMac() resp. SkGmHardRst().
- *	Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode).
- *	SkXmRxTxEnable() replaced by SkMacRxTxEnable().
- *	Editorial changes.
- *	
- *	Revision 1.63  2002/04/25 13:04:44  rschmidt
- *	Changes for handling YUKON.
- *	Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
- *	Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
- *	by functions SkXmPhyRead(), SkXmPhyWrite();
- *	Removed use of PRxCmd to setup XMAC.
- *	Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res.
- *	Added setting of XM_RX_DIS_CEXT in SkXmInitMac().
- *	Removed status parameter from MAC IRQ handler SkMacIrq(),
- *	SkXmIrq() and SkGmIrq().
- *	SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy().
- *	Added SkMac...() functions to handle both XMAC and GMAC.
- *	Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(),
- *	SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(),
- *	SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite().
- *	Changes for V-CPU support.
- *	Editorial changes.
- *	
- *	Revision 1.62  2001/08/06 09:50:14  rschmidt
- *	Workaround BCOM Errata #1 for the C5 type.
- *	Editorial changes.
- *	
- *	Revision 1.61  2001/02/09 15:40:59  rassmann
- *	Editorial changes.
- *	
- *	Revision 1.60  2001/02/07 15:02:01  cgoos
- *	Added workaround for Fujitsu switch link down.
- *	
- *	Revision 1.59  2001/01/10 09:38:06  cgoos
- *	Fixed Broadcom C0/A1 Id check for workaround.
- *	
- *	Revision 1.58  2000/11/29 11:30:38  cgoos
- *	Changed DEBUG sections with NW output to xDEBUG
- *	
- *	Revision 1.57  2000/11/27 12:40:40  rassmann
- *	Suppressing preamble after first access to BCom, not before (#10556).
- *	
- *	Revision 1.56  2000/11/09 12:32:48  rassmann
- *	Renamed variables.
- *	
- *	Revision 1.55  2000/11/09 11:30:10  rassmann
- *	WA: Waiting after releasing reset until BCom chip is accessible.
- *	
- *	Revision 1.54  2000/10/02 14:10:27  rassmann
- *	Reading BCOM PHY after releasing reset until it returns a valid value.
- *	
- *	Revision 1.53  2000/07/27 12:22:11  gklug
- *	fix: possible endless loop in XmHardRst.
- *	
- *	Revision 1.52  2000/05/22 08:48:31  malthoff
- *	Fix: #10523 errata valid for all BCOM PHYs.
- *	
- *	Revision 1.51  2000/05/17 12:52:18  malthoff
- *	Fixes BCom link errata (#10523).
- *	
- *	Revision 1.50  1999/11/22 13:40:14  cgoos
- *	Changed license header to GPL.
- *	
- *	Revision 1.49  1999/11/22 08:12:13  malthoff
- *	Add workaround for power consumption feature of BCom C0 chip.
- *	
- *	Revision 1.48  1999/11/16 08:39:01  malthoff
- *	Fix: MDIO preamble suppression is port dependent.
- *	
- *	Revision 1.47  1999/08/27 08:55:35  malthoff
- *	1000BT: Optimizing MDIO transfer by oppressing MDIO preamble.
- *	
- *	Revision 1.46  1999/08/13 11:01:12  malthoff
- *	Fix for 1000BT: pFlowCtrlMode was not set correctly.
- *	
- *	Revision 1.45  1999/08/12 19:18:28  malthoff
- *	1000BT Fixes: Do not owerwrite XM_MMU_CMD.
- *	Do not execute BCOM A1 workaround for B1 chips.
- *	Fix pause frame setting.
- *	Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL.
- *	
- *	Revision 1.44  1999/08/03 15:23:48  cgoos
- *	Fixed setting of PHY interrupt mask in half duplex mode.
- *	
- *	Revision 1.43  1999/08/03 15:22:17  cgoos
- *	Added some debug output.
- *	Disabled XMac GP0 interrupt for external PHYs.
- *	
- *	Revision 1.42  1999/08/02 08:39:23  malthoff
- *	BCOM PHY: TX LED: To get the mono flop behaviour it is required
- *	to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL.
- *	
- *	Revision 1.41  1999/07/30 06:54:31  malthoff
- *	Add temp. workarounds for the BCOM Phy revision A1.
- *	
- *	Revision 1.40  1999/06/01 07:43:26  cgoos
- *	Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to
- *	AUTOFULL/AUTOHALF.
- *	
- *	Revision 1.39  1999/05/19 07:29:51  cgoos
- *	Changes for 1000Base-T.
- *	
- *	Revision 1.38  1999/04/08 14:35:10  malthoff
- *	Add code for enabling signal detect. Enabling signal detect is disabled.
- *	
- *	Revision 1.37  1999/03/12 13:42:54  malthoff
- *	Add: Jumbo Frame Support.
- *	Add: Receive modes SK_LENERR_OK_ON/OFF and
- *	SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd().
- *	
- *	Revision 1.36  1999/03/08 10:10:55  gklug
- *	fix: AutoSensing did switch to next mode even if LiPa indicated offline
- *
- *	Revision 1.35  1999/02/22 15:16:41  malthoff
- *	Remove some compiler warnings.
- *
- *	Revision 1.34  1999/01/22 09:19:59  gklug
- *	fix: Init DupMode and InitPauseMd are now called in RxTxEnable
- *
- *	Revision 1.33  1998/12/11 15:19:11  gklug
- *	chg: lipa autoneg stati
- *	chg: debug messages
- *	chg: do NOT use spurious XmIrq
- *
- *	Revision 1.32  1998/12/10 11:08:44  malthoff
- *	bug fix: pAC has been used for IOs in SkXmHardRst().
- *	SkXmInitPhy() is also called for the Diag in SkXmInitMac().
- *
- *	Revision 1.31  1998/12/10 10:39:11  gklug
- *	fix: do 4 RESETS of the XMAC at the beginning
- *	fix: dummy read interrupt source register BEFORE initializing the Phy
- *	add: debug messages
- *	fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt
- *
- *	Revision 1.30  1998/12/07 12:18:32  gklug
- *	add: refinement of autosense mode: take into account the autoneg cap of LiPa
- *
- *	Revision 1.29  1998/12/07 07:12:29  gklug
- *	fix: if page is received the link is  down.
- *
- *	Revision 1.28  1998/12/01 10:12:47  gklug
- *	chg: if spurious IRQ from XMAC encountered, save it
- *
- *	Revision 1.27  1998/11/26 07:33:38  gklug
- *	add: InitPhy call is now in XmInit function
- *
- *	Revision 1.26  1998/11/18 13:38:24  malthoff
- *	'Imsk' is also unused in SkXmAutoNegDone.
- *
- *	Revision 1.25  1998/11/18 13:28:01  malthoff
- *	Remove unused variable 'Reg' in SkXmAutoNegDone().
- *
- *	Revision 1.24  1998/11/18 13:18:45  gklug
- *	add: workaround for xmac errata #1
- *	add: detect Link Down also when Link partner requested config
- *	chg: XMIrq is only used when link is up
- *
- *	Revision 1.23  1998/11/04 07:07:04  cgoos
- *	Added function SkXmRxTxEnable.
- *
- *	Revision 1.22  1998/10/30 07:35:54  gklug
- *	fix: serve LinkDown interrupt when link is already down
- *
- *	Revision 1.21  1998/10/29 15:32:03  gklug
- *	fix: Link Down signaling
- *
- *	Revision 1.20  1998/10/29 11:17:27  gklug
- *	fix: AutoNegDone bug
- *
- *	Revision 1.19  1998/10/29 10:14:43  malthoff
- *	Add endainesss comment for reading/writing MAC addresses.
- *
- *	Revision 1.18  1998/10/28 07:48:55  cgoos
- *	Fix: ASS somtimes signaled although link is up.
- *
- *	Revision 1.17  1998/10/26 07:55:39  malthoff
- *	Fix in SkXmInitPauseMd(): Pause Mode
- *	was disabled and not enabled.
- *	Fix in SkXmAutoNegDone(): Checking Mode bits
- *	always failed, becaues of some missing braces.
- *
- *	Revision 1.16  1998/10/22 09:46:52  gklug
- *	fix SysKonnectFileId typo
- *
- *	Revision 1.15  1998/10/21 05:51:37  gklug
- *	add: para DoLoop to InitPhy function for loopback set-up
- *
- *	Revision 1.14  1998/10/16 10:59:23  malthoff
- *	Remove Lint warning for dummy reads.
- *
- *	Revision 1.13  1998/10/15 14:01:20  malthoff
- *	Fix: SkXmAutoNegDone() is (int) but does not return a value.
- *
- *	Revision 1.12  1998/10/14 14:45:04  malthoff
- *	Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by
- *	SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent
- *	from the Sirq module.
- *
- *	Revision 1.11  1998/10/14 13:59:01  gklug
- *	add: InitPhy function
- *
- *	Revision 1.10  1998/10/14 11:20:57  malthoff
- *	Make SkXmAutoNegDone() public, because it's
- *	used in diagnostics, too.
- *	The Link Up event to the RLMT is issued in SkXmIrq().
- *  SkXmIrq() is not available in diagnostics.
- *  Use PHY_READ when reading PHY registers.
- *
- *	Revision 1.9  1998/10/14 05:50:10  cgoos
- *	Added definition for Para.
- *
- *	Revision 1.8  1998/10/14 05:41:28  gklug
- *	add: Xmac IRQ
- *	add: auto-negotiation done function
- *
- *	Revision 1.7  1998/10/09 06:55:20  malthoff
- *	The configuration of the XMACs Tx Request Threshold
- *	depends from the drivers port usage now. The port
- *	usage is configured in GIPortUsage.
- *
- *	Revision 1.6  1998/10/05 07:48:00  malthoff
- *	minor changes
- *
- *	Revision 1.5  1998/10/01 07:03:54  gklug
- *	add: dummy function for XMAC ISR
- *
- *	Revision 1.4  1998/09/30 12:37:44  malthoff
- *	Add SkXmSetRxCmd() and related code.
- *
- *	Revision 1.3  1998/09/28 13:26:40  malthoff
- *	Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd()
- *
- *	Revision 1.2  1998/09/16 14:34:21  malthoff
- *	Add SkXmClrExactAddr(), SkXmClrSrcCheck(),
- *	SkXmClrHashAddr(), SkXmFlushTxFifo(),
- *	SkXmFlushRxFifo(), and SkXmHardRst().
- *	Finish Coding of SkXmSoftRst().
- *	The sources may be compiled now.
- *
- *	Revision 1.1  1998/09/04 10:05:56  malthoff
- *	Created.
- *
- *
- ******************************************************************************/
-
 #include "h/skdrv1st.h"
 #include "h/skdrv2nd.h"
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sungem.c linux-2.4.26-pre6/drivers/net/sungem.c
--- linux-2.4.25/drivers/net/sungem.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/sungem.c	2004-03-25 00:22:12.000000000 +0000
@@ -651,6 +651,7 @@ static __inline__ void gem_post_rxds(str
 	cluster_start = curr = (gp->rx_new & ~(4 - 1));
 	count = 0;
 	kick = -1;
+	wmb();
 	while (curr != limit) {
 		curr = NEXT_RX(curr);
 		if (++count == 4) {
@@ -667,13 +668,16 @@ static __inline__ void gem_post_rxds(str
 			count = 0;
 		}
 	}
-	if (kick >= 0)
+	if (kick >= 0) {
+		mb();
 		writel(kick, gp->regs + RXDMA_KICK);
+	}
 }
 
 static void gem_rx(struct gem *gp)
 {
 	int entry, drops;
+	u32 done;
 
 	if (netif_msg_intr(gp))
 		printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
@@ -681,6 +685,7 @@ static void gem_rx(struct gem *gp)
 
 	entry = gp->rx_new;
 	drops = 0;
+	done = readl(gp->regs + RXDMA_DONE);
 	for (;;) {
 		struct gem_rxd *rxd = &gp->init_block->rxd[entry];
 		struct sk_buff *skb;
@@ -691,6 +696,19 @@ static void gem_rx(struct gem *gp)
 		if ((status & RXDCTRL_OWN) != 0)
 			break;
 
+		/* When writing back RX descriptor, GEM writes status
+		 * then buffer address, possibly in seperate transactions.
+		 * If we don't wait for the chip to write both, we could
+		 * post a new buffer to this descriptor then have GEM spam
+		 * on the buffer address.  We sync on the RX completion
+		 * register to prevent this from happening.
+		 */
+		if (entry == done) {
+			done = readl(gp->regs + RXDMA_DONE);
+			if (entry == done)
+				break;
+		}
+
 		skb = gp->rx_skbs[entry];
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
@@ -877,6 +895,7 @@ static int gem_start_xmit(struct sk_buff
 		if (gem_intme(entry))
 			ctrl |= TXDCTRL_INTME;
 		txd->buffer = cpu_to_le64(mapping);
+		wmb();
 		txd->control_word = cpu_to_le64(ctrl);
 		entry = NEXT_TX(entry);
 	} else {
@@ -916,6 +935,7 @@ static int gem_start_xmit(struct sk_buff
 			
 			txd = &gp->init_block->txd[entry];
 			txd->buffer = cpu_to_le64(mapping);
+			wmb();
 			txd->control_word = cpu_to_le64(this_ctrl | len);
 
 			if (gem_intme(entry))
@@ -925,6 +945,7 @@ static int gem_start_xmit(struct sk_buff
 		}
 		txd = &gp->init_block->txd[first_entry];
 		txd->buffer = cpu_to_le64(first_mapping);
+		wmb();
 		txd->control_word =
 			cpu_to_le64(ctrl | TXDCTRL_SOF | intme | first_len);
 	}
@@ -936,6 +957,7 @@ static int gem_start_xmit(struct sk_buff
 	if (netif_msg_tx_queued(gp))
 		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
 		       dev->name, entry, skb->len);
+	mb();
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
 	spin_unlock_irq(&gp->lock);
 
@@ -1430,6 +1452,7 @@ static void gem_clean_rings(struct gem *
 			gp->rx_skbs[i] = NULL;
 		}
 		rxd->status_word = 0;
+		wmb();
 		rxd->buffer = 0;
 	}
 
@@ -1491,6 +1514,7 @@ static void gem_init_rings(struct gem *g
 					RX_BUF_ALLOC_SIZE(gp),
 					PCI_DMA_FROMDEVICE);
 		rxd->buffer = cpu_to_le64(dma_addr);
+		wmb();
 		rxd->status_word = cpu_to_le64(RXDCTRL_FRESH(gp));
 		skb_reserve(skb, RX_OFFSET);
 	}
@@ -1499,8 +1523,10 @@ static void gem_init_rings(struct gem *g
 		struct gem_txd *txd = &gb->txd[i];
 
 		txd->control_word = 0;
+		wmb();
 		txd->buffer = 0;
 	}
+	wmb();
 }
 
 /* Must be invoked under gp->lock. */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/tg3.c linux-2.4.26-pre6/drivers/net/tg3.c
--- linux-2.4.25/drivers/net/tg3.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/tg3.c	2004-03-25 00:19:26.000000000 +0000
@@ -55,8 +55,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"2.6"
-#define DRV_MODULE_RELDATE	"February 3, 2004"
+#define DRV_MODULE_VERSION	"2.9"
+#define DRV_MODULE_RELDATE	"March 8, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -191,6 +191,8 @@ static struct pci_device_id tg3_pci_tbl[
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ 0, }
 };
 
@@ -212,8 +214,46 @@ static void tg3_write_indirect_reg32(str
 	}
 }
 
+static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
+{
+	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&tp->indirect_lock, flags);
+		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+		spin_unlock_irqrestore(&tp->indirect_lock, flags);
+	} else {
+		unsigned long dest = tp->regs + off;
+		writel(val, dest);
+		readl(dest);    /* always flush PCI write */
+	}
+}
+
+static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+	unsigned long mbox = tp->regs + off;
+	writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+		readl(mbox);
+}
+
+static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+	unsigned long mbox = tp->regs + off;
+	writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
+		writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+		readl(mbox);
+}
+
+#define tw32_mailbox(reg, val)  writel(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_rx_mbox(reg, val)  _tw32_rx_mbox(tp, reg, val)
+#define tw32_tx_mbox(reg, val)  _tw32_tx_mbox(tp, reg, val)
+
 #define tw32(reg,val)		tg3_write_indirect_reg32(tp,(reg),(val))
-#define tw32_mailbox(reg, val)	writel(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_f(reg,val)		_tw32_flush(tp,(reg),(val))
 #define tw16(reg,val)		writew(((val) & 0xffff), tp->regs + (reg))
 #define tw8(reg,val)		writeb(((val) & 0xff), tp->regs + (reg))
 #define tr32(reg)		readl(tp->regs + (reg))
@@ -300,18 +340,15 @@ static void tg3_switch_clocks(struct tg3
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
 	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
-		tw32(TG3PCI_CLOCK_CTRL,
+		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
-		tw32(TG3PCI_CLOCK_CTRL,
+		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl | (CLOCK_CTRL_ALTCLK));
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
 	}
-	tw32(TG3PCI_CLOCK_CTRL, clock_ctrl);
-	tr32(TG3PCI_CLOCK_CTRL);
+	tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl);
 	udelay(40);
 }
 
@@ -323,9 +360,8 @@ static int tg3_readphy(struct tg3 *tp, i
 	int loops, ret;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE,
+		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		tr32(MAC_MI_MODE);
 		udelay(40);
 	}
 
@@ -337,8 +373,7 @@ static int tg3_readphy(struct tg3 *tp, i
 		      MI_COM_REG_ADDR_MASK);
 	frame_val |= (MI_COM_CMD_READ | MI_COM_START);
 	
-	tw32(MAC_MI_COM, frame_val);
-	tr32(MAC_MI_COM);
+	tw32_f(MAC_MI_COM, frame_val);
 
 	loops = PHY_BUSY_LOOPS;
 	while (loops-- > 0) {
@@ -359,8 +394,7 @@ static int tg3_readphy(struct tg3 *tp, i
 	}
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
@@ -373,9 +407,8 @@ static int tg3_writephy(struct tg3 *tp, 
 	int loops, ret;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE,
+		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		tr32(MAC_MI_MODE);
 		udelay(40);
 	}
 
@@ -386,8 +419,7 @@ static int tg3_writephy(struct tg3 *tp, 
 	frame_val |= (val & MI_COM_DATA_MASK);
 	frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
 	
-	tw32(MAC_MI_COM, frame_val);
-	tr32(MAC_MI_COM);
+	tw32_f(MAC_MI_COM, frame_val);
 
 	loops = PHY_BUSY_LOOPS;
 	while (loops-- > 0) {
@@ -405,8 +437,7 @@ static int tg3_writephy(struct tg3 *tp, 
 		ret = 0;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
@@ -655,6 +686,18 @@ static int tg3_phy_reset(struct tg3 *tp,
 		return err;
 
 out:
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323);
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+	}
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) {
+		tg3_writephy(tp, 0x1c, 0x8d68);
+		tg3_writephy(tp, 0x1c, 0x8d68);
+	}
 	tg3_phy_set_wirespeed(tp);
 	return 0;
 }
@@ -677,45 +720,41 @@ static void tg3_frob_aux_power(struct tg
 	    (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		} else {
 			if (tp_peer != tp &&
 			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
 				return;
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT2));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT2));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		}
 	} else {
@@ -725,27 +764,24 @@ static void tg3_frob_aux_power(struct tg
 			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
 				return;
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		}
 	}
 }
 
-static int tg3_setup_phy(struct tg3 *);
+static int tg3_setup_phy(struct tg3 *, int);
 
 static int tg3_set_power_state(struct tg3 *tp, int state)
 {
@@ -771,8 +807,7 @@ static int tg3_set_power_state(struct tg
 		pci_write_config_word(tp->pdev,
 				      pm + PCI_PM_CTRL,
 				      power_control);
-		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-		tr32(GRC_LOCAL_CTRL);
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 		udelay(100);
 
 		return 0;
@@ -813,7 +848,7 @@ static int tg3_set_power_state(struct tg
 		tp->link_config.speed = SPEED_10;
 		tp->link_config.duplex = DUPLEX_HALF;
 		tp->link_config.autoneg = AUTONEG_ENABLE;
-		tg3_setup_phy(tp);
+		tg3_setup_phy(tp, 0);
 	}
 
 	pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
@@ -839,12 +874,10 @@ static int tg3_set_power_state(struct tg
 		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
 			mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
 
-		tw32(MAC_MODE, mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, mac_mode);
 		udelay(100);
 
-		tw32(MAC_RX_MODE, RX_MODE_ENABLE);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
 		udelay(10);
 	}
 
@@ -857,10 +890,9 @@ static int tg3_set_power_state(struct tg
 		base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
 			     CLOCK_CTRL_TXCLK_DISABLE);
 
-		tw32(TG3PCI_CLOCK_CTRL, base_val |
+		tw32_f(TG3PCI_CLOCK_CTRL, base_val |
 		     CLOCK_CTRL_ALTCLK |
 		     CLOCK_CTRL_PWRDOWN_PLL133);
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
 	} else {
 		u32 newbits1, newbits2;
@@ -879,12 +911,10 @@ static int tg3_set_power_state(struct tg
 			newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
 		}
 
-		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
-		tr32(TG3PCI_CLOCK_CTRL);
+		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
 		udelay(40);
 
-		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
-		tr32(TG3PCI_CLOCK_CTRL);
+		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
 		udelay(40);
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
@@ -899,8 +929,8 @@ static int tg3_set_power_state(struct tg
 				newbits3 = CLOCK_CTRL_44MHZ_CORE;
 			}
 
-			tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3);
-			tr32(TG3PCI_CLOCK_CTRL);
+			tw32_f(TG3PCI_CLOCK_CTRL,
+					 tp->pci_clock_ctrl | newbits3);
 			udelay(40);
 		}
 	}
@@ -1014,7 +1044,7 @@ static void tg3_aux_stat_to_speed_duplex
 	};
 }
 
-static int tg3_phy_copper_begin(struct tg3 *tp, int wait_for_link)
+static int tg3_phy_copper_begin(struct tg3 *tp)
 {
 	u32 new_adv;
 	int i;
@@ -1132,7 +1162,7 @@ static int tg3_phy_copper_begin(struct t
 		tg3_readphy(tp, MII_BMCR, &orig_bmcr);
 		if (bmcr != orig_bmcr) {
 			tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
-			for (i = 0; i < 15000; i++) {
+			for (i = 0; i < 1500; i++) {
 				u32 tmp;
 
 				udelay(10);
@@ -1151,27 +1181,6 @@ static int tg3_phy_copper_begin(struct t
 			     BMCR_ANENABLE | BMCR_ANRESTART);
 	}
 
-	if (wait_for_link) {
-		tp->link_config.active_speed = SPEED_INVALID;
-		tp->link_config.active_duplex = DUPLEX_INVALID;
-		for (i = 0; i < 300000; i++) {
-			u32 tmp;
-
-			udelay(10);
-			tg3_readphy(tp, MII_BMSR, &tmp);
-			tg3_readphy(tp, MII_BMSR, &tmp);
-			if (!(tmp & BMSR_LSTATUS))
-				continue;
-
-			tg3_readphy(tp, MII_TG3_AUX_STAT, &tmp);
-			tg3_aux_stat_to_speed_duplex(tp, tmp,
-						     &tp->link_config.active_speed,
-						     &tp->link_config.active_duplex);
-		}
-		if (tp->link_config.active_speed == SPEED_INVALID)
-			return -EINVAL;
-	}
-
 	return 0;
 }
 
@@ -1202,7 +1211,7 @@ static int tg3_init_5401phy_dsp(struct t
 	return err;
 }
 
-static int tg3_setup_copper_phy(struct tg3 *tp)
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
 	int current_link_up;
 	u32 bmsr, dummy;
@@ -1210,15 +1219,17 @@ static int tg3_setup_copper_phy(struct t
 	u8 current_duplex;
 	int i, err;
 
-	tw32(MAC_STATUS,
+	tw32(MAC_EVENT, 0);
+
+	tw32_f(MAC_STATUS,
 	     (MAC_STATUS_SYNC_CHANGED |
-	      MAC_STATUS_CFG_CHANGED));
-	tr32(MAC_STATUS);
+	      MAC_STATUS_CFG_CHANGED |
+	      MAC_STATUS_MI_COMPLETION |
+	      MAC_STATUS_LNKSTATE_CHANGED));
 	udelay(40);
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
@@ -1233,8 +1244,10 @@ static int tg3_setup_copper_phy(struct t
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		if (!(bmsr & BMSR_LSTATUS))
-			tg3_phy_reset(tp, 1);
+			force_reset = 1;
 	}
+	if (force_reset)
+		tg3_phy_reset(tp, 1);
 
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1370,7 +1383,7 @@ static int tg3_setup_copper_phy(struct t
 	if (current_link_up == 0) {
 		u32 tmp;
 
-		tg3_phy_copper_begin(tp, 0);
+		tg3_phy_copper_begin(tp);
 
 		tg3_readphy(tp, MII_BMSR, &tmp);
 		tg3_readphy(tp, MII_BMSR, &tmp);
@@ -1410,24 +1423,19 @@ static int tg3_setup_copper_phy(struct t
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
 	    tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
 		tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
-	if (tp->tg3_flags &
-	    (TG3_FLAG_USE_LINKCHG_REG |
-	     TG3_FLAG_POLL_SERDES)) {
+	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
 		/* Polled via timer. */
-		tw32(MAC_EVENT, 0);
+		tw32_f(MAC_EVENT, 0);
 	} else {
-		tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	}
-	tr32(MAC_EVENT);
 	udelay(40);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
@@ -1436,10 +1444,9 @@ static int tg3_setup_copper_phy(struct t
 	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
 	     (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
 		udelay(120);
-		tw32(MAC_STATUS,
+		tw32_f(MAC_STATUS,
 		     (MAC_STATUS_SYNC_CHANGED |
 		      MAC_STATUS_CFG_CHANGED));
-		tr32(MAC_STATUS);
 		udelay(40);
 		tg3_write_mem(tp,
 			      NIC_SRAM_FIRMWARE_MBOX,
@@ -1601,8 +1608,7 @@ static int tg3_fiber_aneg_smachine(struc
 		ap->txconfig = 0;
 		tw32(MAC_TX_AUTO_NEG, 0);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ret = ANEG_TIMER_ENAB;
@@ -1627,8 +1633,7 @@ static int tg3_fiber_aneg_smachine(struc
 		ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
 		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_ABILITY_DETECT;
@@ -1644,8 +1649,7 @@ static int tg3_fiber_aneg_smachine(struc
 		ap->txconfig |= ANEG_CFG_ACK;
 		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_ACK_DETECT;
@@ -1731,8 +1735,7 @@ static int tg3_fiber_aneg_smachine(struc
 	case ANEG_STATE_IDLE_DETECT_INIT:
 		ap->link_time = ap->cur_time;
 		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_IDLE_DETECT;
@@ -1773,7 +1776,7 @@ static int tg3_fiber_aneg_smachine(struc
 	return ret;
 }
 
-static int tg3_setup_fiber_phy(struct tg3 *tp)
+static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 {
 	u32 orig_pause_cfg;
 	u16 orig_active_speed;
@@ -1789,8 +1792,7 @@ static int tg3_setup_fiber_phy(struct tg
 
 	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
 	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	/* Reset when initting first time or we have a link. */
@@ -1838,10 +1840,9 @@ static int tg3_setup_fiber_phy(struct tg
 
 	/* Enable link change interrupt unless serdes polling.  */
 	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
-		tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	else
-		tw32(MAC_EVENT, 0);
-	tr32(MAC_EVENT);
+		tw32_f(MAC_EVENT, 0);
 	udelay(40);
 
 	current_link_up = 0;
@@ -1859,12 +1860,10 @@ static int tg3_setup_fiber_phy(struct tg
 			tw32(MAC_TX_AUTO_NEG, 0);
 
 			tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-			tw32(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
 			udelay(40);
 
-			tw32(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
 			udelay(40);
 
 			aninfo.state = ANEG_STATE_UNKNOWN;
@@ -1880,8 +1879,7 @@ static int tg3_setup_fiber_phy(struct tg
 			}
 
 			tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-			tw32(MAC_MODE, tp->mac_mode);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode);
 			udelay(40);
 
 			if (status == ANEG_DONE &&
@@ -1905,10 +1903,9 @@ static int tg3_setup_fiber_phy(struct tg
 			}
 			for (i = 0; i < 60; i++) {
 				udelay(20);
-				tw32(MAC_STATUS,
+				tw32_f(MAC_STATUS,
 				     (MAC_STATUS_SYNC_CHANGED |
 				      MAC_STATUS_CFG_CHANGED));
-				tr32(MAC_STATUS);
 				udelay(40);
 				if ((tr32(MAC_STATUS) &
 				     (MAC_STATUS_SYNC_CHANGED |
@@ -1926,8 +1923,7 @@ static int tg3_setup_fiber_phy(struct tg
 	}
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	tp->hw_status->status =
@@ -1936,10 +1932,9 @@ static int tg3_setup_fiber_phy(struct tg
 
 	for (i = 0; i < 100; i++) {
 		udelay(20);
-		tw32(MAC_STATUS,
+		tw32_f(MAC_STATUS,
 		     (MAC_STATUS_SYNC_CHANGED |
 		      MAC_STATUS_CFG_CHANGED));
-		tr32(MAC_STATUS);
 		udelay(40);
 		if ((tr32(MAC_STATUS) &
 		     (MAC_STATUS_SYNC_CHANGED |
@@ -1975,12 +1970,10 @@ static int tg3_setup_fiber_phy(struct tg
 	}
 
 	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-		tw32(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
 		udelay(40);
 		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-			tw32(MAC_MODE, tp->mac_mode);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode);
 			udelay(40);
 		}
 	}
@@ -1988,14 +1981,14 @@ static int tg3_setup_fiber_phy(struct tg
 	return 0;
 }
 
-static int tg3_setup_phy(struct tg3 *tp)
+static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 {
 	int err;
 
 	if (tp->phy_id == PHY_ID_SERDES) {
-		err = tg3_setup_fiber_phy(tp);
+		err = tg3_setup_fiber_phy(tp, force_reset);
 	} else {
-		err = tg3_setup_copper_phy(tp);
+		err = tg3_setup_copper_phy(tp, force_reset);
 	}
 
 	if (tp->link_config.active_speed == SPEED_1000 &&
@@ -2324,25 +2317,19 @@ next_pkt_nopost:
 
 	/* ACK the status ring. */
 	tp->rx_rcb_ptr = rx_rcb_ptr;
-	tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
 		     (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp)));
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
 
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
 		sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE;
-		tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
+		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
 	}
 	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
 		sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE;
-		tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
+		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
 	}
 
 	return received;
@@ -2364,7 +2351,7 @@ static int tg3_poll(struct net_device *n
 		if (sblk->status & SD_STATUS_LINK_CHG) {
 			sblk->status = SD_STATUS_UPDATED |
 				(sblk->status & ~SD_STATUS_LINK_CHG);
-			tg3_setup_phy(tp);
+			tg3_setup_phy(tp, 0);
 		}
 	}
 
@@ -2794,32 +2781,17 @@ static int tg3_start_xmit_4gbug(struct s
 
 	/* Packets are ready, update Tx producer idx local and on card. */
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
-			tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-				      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	} else {
 		/* First, make sure tg3 sees last descriptor fully
 		 * in SRAM.
 		 */
 		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
+			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
 
-		tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
-			tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-				      TG3_64BIT_REG_LOW), entry);
-
-		/* Now post the mailbox write itself.  */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	}
 
 	tp->tx_prod = entry;
@@ -2964,11 +2936,8 @@ static int tg3_start_xmit(struct sk_buff
 	 * the double-write bug tests.
 	 */
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	} else {
 		/* First, make sure tg3 sees last descriptor fully
 		 * in SRAM.
@@ -2977,13 +2946,8 @@ static int tg3_start_xmit(struct sk_buff
 			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
 			     TG3_64BIT_REG_LOW);
 
-		tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-
-		/* Now post the mailbox write itself.  */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	}
 
 	tp->tx_prod = entry;
@@ -3337,8 +3301,7 @@ static int tg3_stop_block(struct tg3 *tp
 
 	val = tr32(ofs);
 	val &= ~enable_bit;
-	tw32(ofs, val);
-	tr32(ofs);
+	tw32_f(ofs, val);
 
 	for (i = 0; i < MAX_WAIT_CNT; i++) {
 		udelay(100);
@@ -3365,8 +3328,7 @@ static int tg3_abort_hw(struct tg3 *tp)
 	tg3_disable_ints(tp);
 
 	tp->rx_mode &= ~RX_MODE_ENABLE;
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
@@ -3387,13 +3349,11 @@ static int tg3_abort_hw(struct tg3 *tp)
 		goto out;
 
 	tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	tp->tx_mode &= ~TX_MODE_ENABLE;
-	tw32(MAC_TX_MODE, tp->tx_mode);
-	tr32(MAC_TX_MODE);
+	tw32_f(MAC_TX_MODE, tp->tx_mode);
 
 	for (i = 0; i < MAX_WAIT_CNT; i++) {
 		udelay(100);
@@ -3419,7 +3379,10 @@ static int tg3_abort_hw(struct tg3 *tp)
 	if (err)
 		goto out;
 
-	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+	if (tp->hw_status)
+		memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+	if (tp->hw_stats)
+		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
 out:
 	return err;
@@ -3716,8 +3679,7 @@ static int tg3_halt_cpu(struct tg3 *tp, 
 		}
 
 		tw32(offset + CPU_STATE, 0xffffffff);
-		tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-		tr32(offset + CPU_MODE);
+		tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
 		udelay(10);
 	} else {
 		for (i = 0; i < 10000; i++) {
@@ -3840,20 +3802,14 @@ static int tg3_load_5701_a0_firmware_fix
 
 	/* Now startup only the RX cpu. */
 	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+	tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
 
-	/* Flush posted writes. */
-	tr32(RX_CPU_BASE + CPU_PC);
 	for (i = 0; i < 5; i++) {
 		if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR)
 			break;
 		tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
 		tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-		tw32(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
-
-		/* Flush posted writes. */
-		tr32(RX_CPU_BASE + CPU_PC);
-
+		tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
 		udelay(1000);
 	}
 	if (i >= 5) {
@@ -3864,10 +3820,7 @@ static int tg3_load_5701_a0_firmware_fix
 		return -ENODEV;
 	}
 	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32(RX_CPU_BASE + CPU_MODE,  0x00000000);
-
-	/* Flush posted writes. */
-	tr32(RX_CPU_BASE + CPU_MODE);
+	tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 
 	return 0;
 }
@@ -4425,20 +4378,14 @@ static int tg3_load_tso_firmware(struct 
 
 	/* Now startup the cpu. */
 	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_PC,    info.text_base);
+	tw32_f(cpu_base + CPU_PC,    info.text_base);
 
-	/* Flush posted writes. */
-	tr32(cpu_base + CPU_PC);
 	for (i = 0; i < 5; i++) {
 		if (tr32(cpu_base + CPU_PC) == info.text_base)
 			break;
 		tw32(cpu_base + CPU_STATE, 0xffffffff);
 		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-		tw32(cpu_base + CPU_PC,    info.text_base);
-
-		/* Flush posted writes. */
-		tr32(cpu_base + CPU_PC);
-
+		tw32_f(cpu_base + CPU_PC,    info.text_base);
 		udelay(1000);
 	}
 	if (i >= 5) {
@@ -4449,11 +4396,7 @@ static int tg3_load_tso_firmware(struct 
 		return -ENODEV;
 	}
 	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_MODE,  0x00000000);
-
-	/* Flush posted writes. */
-	tr32(cpu_base + CPU_MODE);
-
+	tw32_f(cpu_base + CPU_MODE,  0x00000000);
 	return 0;
 }
 
@@ -4500,9 +4443,6 @@ static int tg3_set_mac_addr(struct net_d
 	struct tg3 *tp = dev->priv;
 	struct sockaddr *addr = p;
 
-	if (netif_running(dev))
-		return -EBUSY;
-
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
 	spin_lock_irq(&tp->lock);
@@ -4562,10 +4502,9 @@ static int tg3_reset_hw(struct tg3 *tp)
 		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 	if (tp->phy_id == PHY_ID_SERDES) {
 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
-		tw32(MAC_MODE, tp->mac_mode);
+		tw32_f(MAC_MODE, tp->mac_mode);
 	} else
-		tw32(MAC_MODE, 0);
-	tr32(MAC_MODE);
+		tw32_f(MAC_MODE, 0);
 	udelay(40);
 
 	/* Wait for firmware initialization to complete. */
@@ -4595,8 +4534,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	 * other revision.
 	 */
 	tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
-	tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
-	tr32(TG3PCI_CLOCK_CTRL);
+	tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
 	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
@@ -4793,9 +4731,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tp->tx_prod = 0;
 	tp->tx_cons = 0;
 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	tw32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
 		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
@@ -4822,9 +4758,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	}
 
 	tp->rx_rcb_ptr = 0;
-	tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
 	tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
 		       tp->rx_rcb_mapping,
@@ -4833,19 +4767,13 @@ static int tg3_reset_hw(struct tg3 *tp)
 		       0);
 
 	tp->rx_std_ptr = tp->rx_pending;
-	tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
+	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tp->rx_std_ptr);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
 
-	if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)
-		tp->rx_jumbo_ptr = tp->rx_jumbo_pending;
-	else
-		tp->rx_jumbo_ptr = 0;
-	tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
+	tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) ?
+						tp->rx_jumbo_pending : 0;
+	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tp->rx_jumbo_ptr);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
 
 	/* Initialize MAC address and backoff seed. */
 	__tg3_set_mac_addr(tp);
@@ -4950,24 +4878,21 @@ static int tg3_reset_hw(struct tg3 *tp)
 
 	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
 		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
-	tw32(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
 	udelay(40);
 
 	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
 		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
 				       GRC_LCLCTRL_GPIO_OUTPUT1);
-	tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-	tr32(GRC_LOCAL_CTRL);
+	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
 	tr32(MAILBOX_INTERRUPT_0);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-		tw32(DMAC_MODE, DMAC_MODE_ENABLE);
-		tr32(DMAC_MODE);
+		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
 		udelay(40);
 	}
 
@@ -4980,8 +4905,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	    (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 &&
 	    !(tp->tg3_flags2 & TG3_FLG2_IS_5788))
 		val |= WDMAC_MODE_RX_ACCEL;
-	tw32(WDMAC_MODE, val);
-	tr32(WDMAC_MODE);
+	tw32_f(WDMAC_MODE, val);
 	udelay(40);
 
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
@@ -4999,8 +4923,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 		tw32(TG3PCI_X_CAPS, val);
 	}
 
-	tw32(RDMAC_MODE, rdmac_mode);
-	tr32(RDMAC_MODE);
+	tw32_f(RDMAC_MODE, rdmac_mode);
 	udelay(40);
 
 	tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
@@ -5029,13 +4952,11 @@ static int tg3_reset_hw(struct tg3 *tp)
 #endif
 
 	tp->tx_mode = TX_MODE_ENABLE;
-	tw32(MAC_TX_MODE, tp->tx_mode);
-	tr32(MAC_TX_MODE);
+	tw32_f(MAC_TX_MODE, tp->tx_mode);
 	udelay(100);
 
 	tp->rx_mode = RX_MODE_ENABLE;
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	if (tp->link_config.phy_is_low_power) {
@@ -5046,19 +4967,16 @@ static int tg3_reset_hw(struct tg3 *tp)
 	}
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	tw32(MAC_LED_CTRL, 0);
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
 	if (tp->phy_id == PHY_ID_SERDES) {
-		tw32(MAC_RX_MODE, RX_MODE_RESET);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
@@ -5067,10 +4985,9 @@ static int tg3_reset_hw(struct tg3 *tp)
 	/* Prevent chip from dropping frames when flow control
 	 * is enabled.
 	 */
-	tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
-	tr32(MAC_LOW_WMARK_MAX_RX_FRAME);
+	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
-	err = tg3_setup_phy(tp);
+	err = tg3_setup_phy(tp, 1);
 	if (err)
 		return err;
 
@@ -5252,7 +5169,7 @@ static void tg3_timer(unsigned long __op
 				phy_event = 1;
 
 			if (phy_event)
-				tg3_setup_phy(tp);
+				tg3_setup_phy(tp, 0);
 		} else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) {
 			u32 mac_stat = tr32(MAC_STATUS);
 			int need_setup = 0;
@@ -5266,15 +5183,13 @@ static void tg3_timer(unsigned long __op
 				need_setup = 1;
 			}
 			if (need_setup) {
-				tw32(MAC_MODE,
+				tw32_f(MAC_MODE,
 				     (tp->mac_mode &
 				      ~MAC_MODE_PORT_MODE_MASK));
-				tr32(MAC_MODE);
 				udelay(40);
-				tw32(MAC_MODE, tp->mac_mode);
-				tr32(MAC_MODE);
+				tw32_f(MAC_MODE, tp->mac_mode);
 				udelay(40);
-				tg3_setup_phy(tp);
+				tg3_setup_phy(tp, 0);
 			}
 		}
 
@@ -5827,8 +5742,7 @@ static void __tg3_set_rx_mode(struct net
 
 	if (rx_mode != tp->rx_mode) {
 		tp->rx_mode = rx_mode;
-		tw32(MAC_RX_MODE, rx_mode);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, rx_mode);
 		udelay(10);
 	}
 }
@@ -5954,7 +5868,7 @@ static int tg3_set_settings(struct net_d
 	struct tg3 *tp = dev->priv;
   
 	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-					tp->link_config.phy_is_low_power)
+	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
 	spin_lock_irq(&tp->lock);
@@ -5970,7 +5884,7 @@ static int tg3_set_settings(struct net_d
 		tp->link_config.duplex = cmd->duplex;
   	}
   
-	tg3_setup_phy(tp);
+	tg3_setup_phy(tp, 1);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
   
@@ -6295,7 +6209,7 @@ static void __devinit tg3_nvram_init(str
 	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
 		return;
 
-	tw32(GRC_EEPROM_ADDR,
+	tw32_f(GRC_EEPROM_ADDR,
 	     (EEPROM_ADDR_FSM_RESET |
 	      (EEPROM_DEFAULT_CLOCK_PERIOD <<
 	       EEPROM_ADDR_CLKPERD_SHIFT)));
@@ -6305,9 +6219,8 @@ static void __devinit tg3_nvram_init(str
 		udelay(10);
 
 	/* Enable seeprom accesses. */
-	tw32(GRC_LOCAL_CTRL,
+	tw32_f(GRC_LOCAL_CTRL,
 	     tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
-	tr32(GRC_LOCAL_CTRL);
 	udelay(100);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
@@ -6916,6 +6829,12 @@ static int __devinit tg3_get_invariants(
 	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)))
 		tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
 
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
+	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_ADC_BUG;
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
+
 	/* Only 5701 and later support tagged irq status mode.
 	 * Also, 5788 chips cannot use tagged irq status.
 	 *
@@ -6930,8 +6849,7 @@ static int __devinit tg3_get_invariants(
 		tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
 
 	/* Initialize MAC MI mode, polling disabled. */
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	/* Initialize data/descriptor byte/word swapping. */
@@ -7207,14 +7125,12 @@ static int __devinit tg3_do_test_dma(str
 	if (to_device) {
 		test_desc.cqid_sqid = (13 << 8) | 2;
 
-		tw32(RDMAC_MODE, RDMAC_MODE_ENABLE);
-		tr32(RDMAC_MODE);
+		tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
 		udelay(40);
 	} else {
 		test_desc.cqid_sqid = (16 << 8) | 7;
 
-		tw32(WDMAC_MODE, WDMAC_MODE_ENABLE);
-		tr32(WDMAC_MODE);
+		tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
 		udelay(40);
 	}
 	test_desc.flags = 0x00000005;
@@ -7415,17 +7331,18 @@ static int __devinit tg3_test_dma(struct
 			break;
 		}
 
+#if 0
 		/* validate data reached card RAM correctly. */
 		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
 			u32 val;
 			tg3_read_mem(tp, 0x2100 + (i*4), &val);
-			if (val != p[i]) {
-				printk( KERN_ERR "  tg3_test_dma()  Card buffer currupted on write! (%d != %d)\n", val, i);
+			if (le32_to_cpu(val) != p[i]) {
+				printk(KERN_ERR "  tg3_test_dma()  Card buffer corrupted on write! (%d != %d)\n", val, i);
 				/* ret = -ENODEV here? */
 			}
 			p[i] = 0;
 		}
-
+#endif
 		/* Now read it back. */
 		ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
 		if (ret) {
@@ -7740,6 +7657,18 @@ static int __devinit tg3_init_one(struct
 		goto err_out_iounmap;
 	}
 
+	/*
+	 * Reset chip in case UNDI or EFI driver did not shutdown
+	 * DMA self test will enable WDMAC and we'll see (spurious)
+	 * pending DMA on the PCI bus at that point.
+	 */
+	if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+	    (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+		pci_save_state(tp->pdev, tp->pci_cfg_state);
+		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+		tg3_halt(tp);
+	}
+
 	err = tg3_test_dma(tp);
 	if (err) {
 		printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/tg3.h linux-2.4.26-pre6/drivers/net/tg3.h
--- linux-2.4.25/drivers/net/tg3.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/tg3.h	2004-03-25 00:20:32.000000000 +0000
@@ -129,6 +129,9 @@
 #define   CHIPREV_5700_BX		 0x71
 #define   CHIPREV_5700_CX		 0x72
 #define   CHIPREV_5701_AX		 0x00
+#define   CHIPREV_5703_AX		 0x10
+#define   CHIPREV_5704_AX		 0x20
+#define   CHIPREV_5704_BX		 0x21
 #define  GET_METAL_REV(CHIP_REV_ID)	((CHIP_REV_ID) & 0xff)
 #define   METAL_REV_A0			 0x00
 #define   METAL_REV_A1			 0x01
@@ -1889,7 +1892,11 @@ struct tg3 {
 #define TG3_FLAG_ENABLE_ASF		0x00000020
 #define TG3_FLAG_5701_REG_WRITE_BUG	0x00000040
 #define TG3_FLAG_POLL_SERDES		0x00000080
+#if defined(CONFIG_X86)
 #define TG3_FLAG_MBOX_WRITE_REORDER	0x00000100
+#else
+#define TG3_FLAG_MBOX_WRITE_REORDER	0	/* disables code too */
+#endif
 #define TG3_FLAG_PCIX_TARGET_HWBUG	0x00000200
 #define TG3_FLAG_WOL_SPEED_100MB	0x00000400
 #define TG3_FLAG_WOL_ENABLE		0x00000800
@@ -1920,6 +1927,8 @@ struct tg3 {
 #define TG3_FLG2_IS_5788		0x00000008
 #define TG3_FLG2_MAX_RXPEND_64		0x00000010
 #define TG3_FLG2_TSO_CAPABLE		0x00000020
+#define TG3_FLG2_PHY_ADC_BUG		0x00000040
+#define TG3_FLG2_PHY_5704_A0_BUG	0x00000080
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/tulip/tulip_core.c linux-2.4.26-pre6/drivers/net/tulip/tulip_core.c
--- linux-2.4.25/drivers/net/tulip/tulip_core.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/tulip/tulip_core.c	2004-03-25 00:20:28.000000000 +0000
@@ -579,7 +579,7 @@ static void tulip_tx_timeout(struct net_
 					dev->if_port = 2 - dev->if_port;
 				} else
 					dev->if_port = 0;
-			else
+			else if (dev->if_port != 0 || (csr12 & 0x0004) != 0)
 				dev->if_port = 1;
 			tulip_select_media(dev, 0);
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/typhoon-firmware.h linux-2.4.26-pre6/drivers/net/typhoon-firmware.h
--- linux-2.4.25/drivers/net/typhoon-firmware.h	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/typhoon-firmware.h	2004-03-25 00:21:20.000000000 +0000
@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2002 3Com Corporation.  All Rights Reserved.    
+ * Copyright 1999-2003 3Com Corporation.  All Rights Reserved.    
  *
- * Redistribution and use in source and binary forms of the 3CR990img.h
+ * Redistribution and use in source and binary forms of the 3c990img.h
  * microcode software are permitted provided that the following conditions
  * are met:
  * 1. Redistribution of source code must retain the above copyright
@@ -23,385 +23,394 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * USER ACKNOWLEDGES AND AGREES THAT PURCHASE OR USE OF THE 3CR990img.h
+ * USER ACKNOWLEDGES AND AGREES THAT PURCHASE OR USE OF THE 3c990img.h
  * MICROCODE SOFTWARE WILL NOT CREATE OR GIVE GROUNDS FOR A LICENSE BY
  * IMPLICATION, ESTOPPEL, OR OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS
  * (PATENT, COPYRIGHT, TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT)
  * EMBODIED IN ANY OTHER 3COM HARDWARE OR SOFTWARE EITHER SOLELY OR IN
- * COMBINATION WITH THE 3CR990img.h microcode SOFTWARE
+ * COMBINATION WITH THE 3c990img.h MICROCODE SOFTWARE
  */ 
+
 const u8 typhoon_firmware_image[] = {
 0x54, 0x59, 0x50, 0x48, 0x4f, 0x4f, 0x4e, 0x00, 0x02, 0x00, 0x00, 0x00, 
-0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x40, 0x01, 0x00, 0x00, 
-0x6c, 0xef, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x39, 0x00, 0x00, 0xea, 
-0x05, 0x00, 0x00, 0xea, 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 
-0x02, 0x00, 0x00, 0xea, 0x01, 0x00, 0x00, 0xea, 0x32, 0x02, 0x00, 0xea, 
-0xa5, 0x14, 0x00, 0xea, 0x07, 0x00, 0x2d, 0xe9, 0x0e, 0x00, 0xa0, 0xe1, 
-0x00, 0x10, 0x0f, 0xe1, 0xd0, 0x20, 0x9f, 0xe5, 0x12, 0xff, 0x2f, 0xe1, 
-0xfe, 0xff, 0xff, 0xea, 0x01, 0x00, 0x80, 0xe0, 0x04, 0x20, 0x81, 0xe4, 
-0x01, 0x00, 0x50, 0xe1, 0xfc, 0xff, 0xff, 0x1a, 0x0e, 0xf0, 0xa0, 0xe1, 
-0x00, 0xa0, 0xa0, 0xe1, 0x0e, 0xb0, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe3, 
-0xa8, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0x81, 0xe5, 0xa4, 0x10, 0x9f, 0xe5, 
-0x00, 0x00, 0x81, 0xe5, 0x01, 0x16, 0xa0, 0xe3, 0x00, 0x00, 0x91, 0xe5, 
-0x01, 0x00, 0x80, 0xe3, 0x00, 0x00, 0x81, 0xe5, 0xd7, 0x00, 0xa0, 0xe3, 
-0x00, 0xf0, 0x21, 0xe1, 0x88, 0xd0, 0x9f, 0xe5, 0xdb, 0x00, 0xa0, 0xe3, 
-0x00, 0xf0, 0x21, 0xe1, 0x7c, 0xd0, 0x9f, 0xe5, 0xd2, 0x00, 0xa0, 0xe3, 
-0x00, 0xf0, 0x21, 0xe1, 0x74, 0xd0, 0x9f, 0xe5, 0xd1, 0x00, 0xa0, 0xe3, 
-0x00, 0xf0, 0x21, 0xe1, 0x6c, 0xd0, 0x9f, 0xe5, 0x7b, 0x14, 0x00, 0xeb, 
-0xd3, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x60, 0xd0, 0x9f, 0xe5, 
-0x60, 0x00, 0x9f, 0xe5, 0x60, 0x10, 0x9f, 0xe5, 0x60, 0x20, 0x9f, 0xe5, 
-0xdb, 0xff, 0xff, 0xeb, 0x5c, 0x00, 0x9f, 0xe5, 0x5c, 0x10, 0x9f, 0xe5, 
-0x00, 0x20, 0xa0, 0xe3, 0xd7, 0xff, 0xff, 0xeb, 0x54, 0x00, 0x9f, 0xe5, 
-0x54, 0x10, 0x9f, 0xe5, 0xd4, 0xff, 0xff, 0xeb, 0x0a, 0x00, 0xa0, 0xe1, 
-0x0b, 0xf0, 0xa0, 0xe1, 0xd3, 0x10, 0xa0, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 
-0xd4, 0xff, 0xff, 0xeb, 0x3c, 0xa0, 0x9f, 0xe5, 0x1a, 0xff, 0x2f, 0xe1, 
-0xc6, 0xff, 0xff, 0xea, 0xbd, 0x20, 0xff, 0xff, 0x0c, 0x00, 0x10, 0x00, 
-0x1c, 0x00, 0x10, 0x00, 0x3c, 0x38, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80, 
-0xfc, 0x3f, 0x00, 0x80, 0x7c, 0x34, 0x00, 0x80, 0x80, 0x0f, 0x00, 0x00, 
-0x80, 0x30, 0x00, 0x80, 0xad, 0xde, 0xad, 0xde, 0xa8, 0xbc, 0x00, 0x00, 
-0x24, 0xab, 0x20, 0x40, 0x34, 0x29, 0x00, 0x00, 0xa8, 0x04, 0x00, 0x80, 
-0x6d, 0xc8, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0xd8, 0x56, 0x00, 0x00, 0x06, 0x24, 0x00, 0x00, 
-0x60, 0x01, 0xff, 0xff, 0xb0, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x00, 0x25, 
-0xe0, 0x6b, 0x00, 0x28, 0x1d, 0xd0, 0x38, 0x1c, 0x10, 0x49, 0x04, 0xf0, 
-0x37, 0xfd, 0xe1, 0x6b, 0xc0, 0x46, 0x08, 0x60, 0x00, 0x28, 0x14, 0xd0, 
-0x38, 0x01, 0x0d, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 
-0x41, 0x6b, 0x80, 0x29, 0x0b, 0xd2, 0x01, 0x31, 0x41, 0x63, 0xe0, 0x6b, 
-0xc1, 0x69, 0xc0, 0x46, 0xe1, 0x63, 0x39, 0x07, 0x41, 0x60, 0xc7, 0x62, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x28, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 
-0x28, 0x17, 0x00, 0x80, 0xee, 0x05, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x80, 
-0x02, 0x49, 0xca, 0x6b, 0xc0, 0x46, 0xc2, 0x61, 0xc8, 0x63, 0x70, 0x47, 
-0x28, 0x17, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
-0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe1, 
-0x00, 0x10, 0xa0, 0xe1, 0xc0, 0x10, 0x81, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 
-0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 
-0x00, 0x00, 0x0f, 0xe1, 0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
-0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x0f, 0xe1, 0xc0, 0x00, 0xc0, 0xe3, 
+0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xcd, 0x57, 0xc3, 
+0xba, 0x01, 0x2c, 0xe8, 0xcd, 0xef, 0xa9, 0xd9, 0x6f, 0xbb, 0x76, 0x2f, 
+0x86, 0x49, 0xac, 0x1b, 0x40, 0x01, 0x00, 0x00, 0x8a, 0xe4, 0x00, 0x00, 
+0x00, 0x00, 0xff, 0xff, 0x39, 0x00, 0x00, 0xea, 0x05, 0x00, 0x00, 0xea, 
+0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea, 
+0x01, 0x00, 0x00, 0xea, 0x32, 0x02, 0x00, 0xea, 0xc0, 0x14, 0x00, 0xea, 
+0x07, 0x00, 0x2d, 0xe9, 0x0e, 0x00, 0xa0, 0xe1, 0x00, 0x10, 0x0f, 0xe1, 
+0xd0, 0x20, 0x9f, 0xe5, 0x12, 0xff, 0x2f, 0xe1, 0xfe, 0xff, 0xff, 0xea, 
+0x01, 0x00, 0x80, 0xe0, 0x04, 0x20, 0x81, 0xe4, 0x01, 0x00, 0x50, 0xe1, 
+0xfc, 0xff, 0xff, 0x1a, 0x0e, 0xf0, 0xa0, 0xe1, 0x00, 0xa0, 0xa0, 0xe1, 
+0x0e, 0xb0, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe3, 0xa8, 0x10, 0x9f, 0xe5, 
+0x00, 0x00, 0x81, 0xe5, 0xa4, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0x81, 0xe5, 
+0x01, 0x16, 0xa0, 0xe3, 0x00, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x80, 0xe3, 
+0x00, 0x00, 0x81, 0xe5, 0xd7, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
+0x88, 0xd0, 0x9f, 0xe5, 0xdb, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
+0x7c, 0xd0, 0x9f, 0xe5, 0xd2, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
+0x74, 0xd0, 0x9f, 0xe5, 0xd1, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
+0x6c, 0xd0, 0x9f, 0xe5, 0x96, 0x14, 0x00, 0xeb, 0xd3, 0x00, 0xa0, 0xe3, 
+0x00, 0xf0, 0x21, 0xe1, 0x60, 0xd0, 0x9f, 0xe5, 0x60, 0x00, 0x9f, 0xe5, 
+0x60, 0x10, 0x9f, 0xe5, 0x60, 0x20, 0x9f, 0xe5, 0xdb, 0xff, 0xff, 0xeb, 
+0x5c, 0x00, 0x9f, 0xe5, 0x5c, 0x10, 0x9f, 0xe5, 0x00, 0x20, 0xa0, 0xe3, 
+0xd7, 0xff, 0xff, 0xeb, 0x54, 0x00, 0x9f, 0xe5, 0x54, 0x10, 0x9f, 0xe5, 
+0xd4, 0xff, 0xff, 0xeb, 0x0a, 0x00, 0xa0, 0xe1, 0x0b, 0xf0, 0xa0, 0xe1, 
+0xd3, 0x10, 0xa0, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0xd4, 0xff, 0xff, 0xeb, 
+0x3c, 0xa0, 0x9f, 0xe5, 0x1a, 0xff, 0x2f, 0xe1, 0xc6, 0xff, 0xff, 0xea, 
+0x01, 0x21, 0xff, 0xff, 0x0c, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x10, 0x00, 
+0x3c, 0x38, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80, 0xfc, 0x3f, 0x00, 0x80, 
+0x7c, 0x34, 0x00, 0x80, 0x80, 0x0f, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80, 
+0xad, 0xde, 0xad, 0xde, 0x5c, 0xbc, 0x00, 0x00, 0x24, 0xab, 0x20, 0x40, 
+0x48, 0x29, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0x8d, 0xd2, 0x21, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x44, 0x57, 0x00, 0x00, 0x71, 0xaf, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff, 
+0xb0, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x00, 0x25, 0x20, 0x68, 0x00, 0x28, 
+0x1d, 0xd0, 0x38, 0x1c, 0x10, 0x49, 0x04, 0xf0, 0x71, 0xfd, 0x21, 0x68, 
+0xc0, 0x46, 0x08, 0x60, 0x00, 0x28, 0x14, 0xd0, 0x38, 0x01, 0x0d, 0x49, 
+0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x80, 0x29, 
+0x0b, 0xd2, 0x01, 0x31, 0x41, 0x63, 0x20, 0x68, 0xc1, 0x69, 0xc0, 0x46, 
+0x21, 0x60, 0x39, 0x07, 0x41, 0x60, 0xc7, 0x62, 0xb0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x28, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0xe8, 0x17, 0x00, 0x80, 
+0xee, 0x05, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 
+0xc0, 0x46, 0xc2, 0x61, 0x08, 0x60, 0x70, 0x47, 
+0xe8, 0x17, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
+0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe1, 0x00, 0x10, 0xa0, 0xe1, 
+0xc0, 0x10, 0x81, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 
 0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x0f, 0xe1, 
-0x40, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 
-0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0x10, 0xe3, 0x80, 0x00, 0x80, 0xe3, 
-0x00, 0xf0, 0x21, 0xe1, 0x00, 0x00, 0x00, 0x12, 0x1e, 0xff, 0x2f, 0xe1, 
-0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xc0, 0x13, 
+0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 
+0x00, 0x00, 0x0f, 0xe1, 0xc0, 0x00, 0xc0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
+0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x0f, 0xe1, 0x40, 0x00, 0x80, 0xe3, 
 0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x0f, 0xe1, 
-0x80, 0x00, 0xc0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 
-0x91, 0x00, 0x00, 0xe0, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x20, 0x80, 0xe0, 
-0x01, 0x00, 0x80, 0xe0, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0xb5, 0x08, 0x4f, 
-0x64, 0x28, 0x04, 0xd3, 0x64, 0x20, 0x38, 0x63, 0x00, 0x20, 0xc0, 0x43, 
-0x03, 0xe0, 0x38, 0x63, 0x04, 0x49, 0x05, 0xf0, 0xc1, 0xfa, 0x78, 0x63, 
-0xb8, 0x63, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0x88, 0x13, 0x00, 0x00, 0x80, 0xb4, 0x10, 0x4b, 0x00, 0x22, 0x1f, 0x6b, 
-0x64, 0x2f, 0x03, 0xd2, 0x09, 0x68, 0x09, 0x68, 0x49, 0x08, 0x02, 0xd2, 
-0x10, 0x1c, 0x80, 0xbc, 0x70, 0x47, 0x19, 0x1c, 0xdb, 0x6b, 0x4f, 0x6b, 
-0xbb, 0x42, 0x05, 0xd2, 0x40, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x18, 0x18, 
-0xc8, 0x63, 0xf1, 0xe7, 0x41, 0x68, 0x05, 0x4b, 0x19, 0x43, 0x41, 0x60, 
-0x04, 0x48, 0xc1, 0x6b, 0x01, 0x31, 0xc1, 0x63, 0x02, 0x20, 0xe8, 0xe7, 
-0xe8, 0x0d, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x78, 0x2a, 0x00, 0x80, 
-0x90, 0xb5, 0x07, 0x1c, 0x15, 0x4c, 0x00, 0x20, 0x21, 0x6b, 0x64, 0x29, 
-0x0b, 0xd2, 0xb9, 0x6e, 0x49, 0x08, 0x08, 0xd3, 0x21, 0x6c, 0xa2, 0x6b, 
-0x91, 0x42, 0x07, 0xd2, 0xfa, 0x1d, 0x39, 0x32, 0x52, 0x8b, 0x89, 0x18, 
-0x21, 0x64, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x78, 0x6a, 0x39, 0x6b, 
-0xc0, 0x46, 0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xe7, 0xfd, 0x38, 0x1c, 
-0x02, 0xf0, 0xa4, 0xfa, 0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xe1, 0x18, 
-0xc8, 0x72, 0x05, 0x49, 0x0a, 0x6c, 0x12, 0x18, 0x0a, 0x64, 0x04, 0x49, 
-0x8a, 0x6d, 0x12, 0x18, 0x8a, 0x65, 0xe4, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 
-0x78, 0x2a, 0x00, 0x80, 0x10, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x0a, 0x48, 
-0xc0, 0x6d, 0x02, 0x23, 0x18, 0x40, 0x09, 0x4a, 0x00, 0x21, 0x00, 0x28, 
-0x03, 0xd0, 0xd1, 0x63, 0x11, 0x64, 0x80, 0xbc, 0x70, 0x47, 0x06, 0x48, 
-0x07, 0x68, 0x7b, 0x1c, 0x03, 0x60, 0x0a, 0x2f, 0xf7, 0xd3, 0x01, 0x60, 
-0xf3, 0xe7, 0x00, 0x00, 0x10, 0x2a, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 
-0x60, 0x01, 0x00, 0x80, 0x70, 0x47, 0x02, 0x04, 0x12, 0x0c, 0x00, 0x0c, 
-0x10, 0x18, 0x0a, 0x04, 0x12, 0x0c, 0x09, 0x0c, 0x51, 0x18, 0x08, 0x18, 
-0x01, 0x0c, 0x05, 0xd0, 0x01, 0x04, 0x09, 0x0c, 0x00, 0x0c, 0x08, 0x18, 
-0x01, 0x0c, 0xf9, 0xd1, 0x00, 0x04, 0x00, 0x0c, 0x70, 0x47, 0x80, 0xb4, 
-0x00, 0x22, 0x00, 0x29, 0x18, 0xd0, 0x4f, 0x08, 0x7b, 0x1e, 0x00, 0x2f, 
+0x80, 0x00, 0x10, 0xe3, 0x80, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
+0x00, 0x00, 0x00, 0x12, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x50, 0xe3, 
+0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xc0, 0x13, 0x00, 0xf0, 0x21, 0xe1, 
+0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xc0, 0xe3, 
+0x00, 0xf0, 0x21, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x91, 0x00, 0x00, 0xe0, 
+0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x20, 0x80, 0xe0, 0x01, 0x00, 0x80, 0xe0, 
+0x1e, 0xff, 0x2f, 0xe1, 0x80, 0xb5, 0x08, 0x4f, 0x64, 0x28, 0x04, 0xd3, 
+0x64, 0x20, 0x38, 0x63, 0x00, 0x20, 0xc0, 0x43, 0x03, 0xe0, 0x38, 0x63, 
+0x04, 0x49, 0x05, 0xf0, 0xf7, 0xfa, 0x78, 0x63, 0xb8, 0x63, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x88, 0x13, 0x00, 0x00, 
+0x80, 0xb4, 0x10, 0x4b, 0x00, 0x22, 0x1f, 0x6b, 0x64, 0x2f, 0x03, 0xd2, 
+0x09, 0x68, 0x09, 0x68, 0x49, 0x08, 0x02, 0xd2, 0x10, 0x1c, 0x80, 0xbc, 
+0x70, 0x47, 0x19, 0x1c, 0xdb, 0x6b, 0x4f, 0x6b, 0xbb, 0x42, 0x05, 0xd2, 
+0x40, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x18, 0x18, 0xc8, 0x63, 0xf1, 0xe7, 
+0x41, 0x68, 0x05, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x04, 0x48, 0xc1, 0x6b, 
+0x01, 0x31, 0xc1, 0x63, 0x02, 0x20, 0xe8, 0xe7, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 
+0x15, 0x4c, 0x00, 0x20, 0x21, 0x6b, 0x64, 0x29, 0x0b, 0xd2, 0xb9, 0x6e, 
+0x49, 0x08, 0x08, 0xd3, 0x21, 0x6c, 0xa2, 0x6b, 0x91, 0x42, 0x07, 0xd2, 
+0xfa, 0x1d, 0x39, 0x32, 0x52, 0x8b, 0x89, 0x18, 0x21, 0x64, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62, 
+0x38, 0x6b, 0x02, 0xf0, 0x23, 0xfe, 0x38, 0x1c, 0x02, 0xf0, 0xde, 0xfa, 
+0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x73, 0x05, 0x49, 
+0x0a, 0x6c, 0x12, 0x18, 0x0a, 0x64, 0x04, 0x49, 0x8a, 0x6d, 0x12, 0x18, 
+0x8a, 0x65, 0xe4, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 
+0xa4, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x0a, 0x48, 0xc0, 0x6d, 0x02, 0x23, 
+0x18, 0x40, 0x09, 0x4a, 0x00, 0x21, 0x00, 0x28, 0x03, 0xd0, 0xd1, 0x63, 
+0x11, 0x64, 0x80, 0xbc, 0x70, 0x47, 0x06, 0x48, 0x07, 0x68, 0x7b, 0x1c, 
+0x03, 0x60, 0x0a, 0x2f, 0xf7, 0xd3, 0x01, 0x60, 0xf3, 0xe7, 0x00, 0x00, 
+0xa4, 0x2a, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0xe0, 0x01, 0x00, 0x80, 
+0x70, 0x47, 0x02, 0x04, 0x12, 0x0c, 0x00, 0x0c, 0x10, 0x18, 0x0a, 0x04, 
+0x12, 0x0c, 0x09, 0x0c, 0x51, 0x18, 0x08, 0x18, 0x01, 0x0c, 0x05, 0xd0, 
+0x01, 0x04, 0x09, 0x0c, 0x00, 0x0c, 0x08, 0x18, 0x01, 0x0c, 0xf9, 0xd1, 
+0x00, 0x04, 0x00, 0x0c, 0x70, 0x47, 0x80, 0xb4, 0x00, 0x22, 0x00, 0x29, 
+0x18, 0xd0, 0x4f, 0x08, 0x7b, 0x1e, 0x00, 0x2f, 
 0x06, 0xd0, 0x07, 0x88, 0xba, 0x18, 0x02, 0x30, 0x1f, 0x1c, 0x01, 0x3b, 
-0x00, 0x2f, 0xf8, 0xd1, 0x49, 0x08, 0x03, 0xd3, 
-0x00, 0x88, 0x00, 0x06, 0x00, 0x0e, 0x82, 0x18, 0x10, 0x0c, 0x05, 0xd0, 
-0x10, 0x04, 0x00, 0x0c, 0x11, 0x0c, 0x42, 0x18, 0x10, 0x0c, 0xf9, 0xd1, 
-0x10, 0x04, 0x00, 0x0c, 0x80, 0xbc, 0x70, 0x47, 0x80, 0xb5, 0x83, 0x89, 
-0xc7, 0x89, 0xfb, 0x18, 0x07, 0x8a, 0xfb, 0x18, 0x47, 0x8a, 0xfb, 0x18, 
-0x40, 0x7a, 0x00, 0x02, 0xc7, 0x18, 0x38, 0x0c, 0x05, 0xd0, 0x38, 0x04, 
-0x00, 0x0c, 0x3b, 0x0c, 0xc7, 0x18, 0x38, 0x0c, 0xf9, 0xd1, 0x08, 0x1c, 
-0x11, 0x1c, 0xff, 0xf7, 0xc8, 0xff, 0x01, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 
-0xb0, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x02, 0x23, 
-0x82, 0x68, 0x1a, 0x40, 0x00, 0x27, 0x00, 0x2a, 0x0f, 0xd0, 0x0a, 0x4a, 
-0x93, 0x69, 0x01, 0x33, 0x93, 0x61, 0x0a, 0x68, 0x8b, 0x68, 0x9a, 0x18, 
-0x00, 0x68, 0x1c, 0x18, 0x57, 0x81, 0x09, 0x69, 0x10, 0x1c, 0xff, 0xf7, 
-0xac, 0xff, 0xc0, 0x43, 0x60, 0x81, 0x38, 0x1c, 0x90, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x23, 
-0x82, 0x68, 0x1a, 0x40, 0x00, 0x27, 0x00, 0x2a, 0x11, 0xd0, 0x4a, 0x68, 
-0x52, 0x09, 0x0e, 0xd3, 0x09, 0x4a, 0x13, 0x6a, 0x01, 0x33, 0x13, 0x62, 
-0xcb, 0x68, 0x02, 0x68, 0x9c, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x3a, 
-0x1a, 0x43, 0x12, 0x68, 0x00, 0xf0, 0x2e, 0xf8, 0x20, 0x82, 0x38, 0x1c, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x80, 
-0x90, 0xb5, 0x80, 0x23, 0x82, 0x68, 0x1a, 0x40, 0x00, 0x24, 0x00, 0x2a, 
-0x15, 0xd0, 0x4a, 0x68, 0x92, 0x09, 0x12, 0xd3, 0x0b, 0x4a, 0xd3, 0x69, 
-0x01, 0x33, 0xd3, 0x61, 0xcb, 0x68, 0x02, 0x68, 0x9f, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0x08, 0x3a, 0x1a, 0x43, 0x12, 0x68, 0x00, 0xf0, 0x0e, 0xf8, 
-0x00, 0x28, 0x00, 0xd1, 0x04, 0x48, 0xc0, 0x46, 0xf8, 0x80, 0x20, 0x1c, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x80, 
-0xff, 0xff, 0x00, 0x00, 0xb0, 0xb5, 0x14, 0x1c, 0x05, 0x1c, 0x0f, 0x1c, 
-0x38, 0x69, 0xb9, 0x68, 0x41, 0x18, 0x38, 0x68, 0xff, 0xf7, 0x53, 0xff, 
-0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x20, 0x1c, 0xff, 0xf7, 0x39, 0xff, 
-0x04, 0x1c, 0xb8, 0x68, 0x79, 0x69, 0x40, 0x18, 0x69, 0x68, 0x88, 0x42, 
-0x0c, 0xd2, 0x2a, 0x68, 0x12, 0x18, 0x09, 0x1a, 0x10, 0x1c, 0x00, 0xf0, 
-0x05, 0xf9, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x20, 0x1c, 0xff, 0xf7, 
-0x26, 0xff, 0x04, 0x1c, 0xe0, 0x43, 0x00, 0x04, 0x00, 0x0c, 0xb0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x6b, 0xc0, 0x08, 
-0x1a, 0xd3, 0xb8, 0x6a, 0xf9, 0x6b, 0x40, 0x18, 0x79, 0x6c, 0x00, 0xf0, 
-0xed, 0xf8, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x0a, 0x48, 0x07, 0xd0, 
-0x20, 0x23, 0xb9, 0x69, 0x19, 0x43, 0xb9, 0x61, 0x01, 0x6b, 0x01, 0x31, 
-0x01, 0x63, 0x07, 0xe0, 0xff, 0x23, 0x01, 0x33, 0xb9, 0x69, 0x19, 0x43, 
-0xb9, 0x61, 0x41, 0x6a, 0x01, 0x31, 0x41, 0x62, 0x00, 0x20, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x78, 0x2a, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 
-0xb8, 0x6b, 0x41, 0x09, 0x1c, 0xd3, 0xc0, 0x08, 0x1a, 0xd3, 0xf8, 0x1d, 
-0x39, 0x30, 0x00, 0x7b, 0x06, 0x28, 0x15, 0xd1, 0x38, 0x1c, 0x00, 0xf0, 
-0x53, 0xf8, 0x01, 0x1c, 0x0a, 0x48, 0x07, 0xd0, 0x40, 0x23, 0xb9, 0x69, 
+0x00, 0x2f, 0xf8, 0xd1, 0x49, 0x08, 0x03, 0xd3, 0x00, 0x88, 0x00, 0x06, 
+0x00, 0x0e, 0x82, 0x18, 0x10, 0x0c, 0x05, 0xd0, 0x10, 0x04, 0x00, 0x0c, 
+0x11, 0x0c, 0x42, 0x18, 0x10, 0x0c, 0xf9, 0xd1, 0x10, 0x04, 0x00, 0x0c, 
+0x80, 0xbc, 0x70, 0x47, 0x80, 0xb5, 0x83, 0x89, 0xc7, 0x89, 0xfb, 0x18, 
+0x07, 0x8a, 0xfb, 0x18, 0x47, 0x8a, 0xfb, 0x18, 0x40, 0x7a, 0x00, 0x02, 
+0xc7, 0x18, 0x38, 0x0c, 0x05, 0xd0, 0x38, 0x04, 0x00, 0x0c, 0x3b, 0x0c, 
+0xc7, 0x18, 0x38, 0x0c, 0xf9, 0xd1, 0x08, 0x1c, 0x11, 0x1c, 0xff, 0xf7, 
+0xc8, 0xff, 0x01, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0xb0, 0xff, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x02, 0x23, 0x82, 0x68, 0x1a, 0x40, 
+0x00, 0x27, 0x00, 0x2a, 0x0f, 0xd0, 0x0a, 0x4a, 0x93, 0x69, 0x01, 0x33, 
+0x93, 0x61, 0x0a, 0x68, 0x8b, 0x68, 0x9a, 0x18, 0x00, 0x68, 0x1c, 0x18, 
+0x57, 0x81, 0x09, 0x69, 0x10, 0x1c, 0xff, 0xf7, 0xac, 0xff, 0xc0, 0x43, 
+0x60, 0x81, 0x38, 0x1c, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x23, 0x82, 0x68, 0x1a, 0x40, 
+0x00, 0x27, 0x00, 0x2a, 0x11, 0xd0, 0x4a, 0x68, 0x52, 0x09, 0x0e, 0xd3, 
+0x09, 0x4a, 0x13, 0x6a, 0x01, 0x33, 0x13, 0x62, 0xcb, 0x68, 0x02, 0x68, 
+0x9c, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x3a, 0x1a, 0x43, 0x12, 0x68, 
+0x00, 0xf0, 0x2e, 0xf8, 0x20, 0x82, 0x38, 0x1c, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x80, 0x23, 
+0x82, 0x68, 0x1a, 0x40, 0x00, 0x24, 0x00, 0x2a, 0x15, 0xd0, 0x4a, 0x68, 
+0x92, 0x09, 0x12, 0xd3, 0x0b, 0x4a, 0xd3, 0x69, 0x01, 0x33, 0xd3, 0x61, 
+0xcb, 0x68, 0x02, 0x68, 0x9f, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x3a, 
+0x1a, 0x43, 0x12, 0x68, 0x00, 0xf0, 0x0e, 0xf8, 0x00, 0x28, 0x00, 0xd1, 
+0x04, 0x48, 0xc0, 0x46, 0xf8, 0x80, 0x20, 0x1c, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
+0xb0, 0xb5, 0x14, 0x1c, 0x05, 0x1c, 0x0f, 0x1c, 0x38, 0x69, 0xb9, 0x68, 
+0x41, 0x18, 0x38, 0x68, 0xff, 0xf7, 0x53, 0xff, 0xc0, 0x43, 0x01, 0x04, 
+0x09, 0x0c, 0x20, 0x1c, 0xff, 0xf7, 0x39, 0xff, 0x04, 0x1c, 0xb8, 0x68, 
+0x79, 0x69, 0x40, 0x18, 0x69, 0x68, 0x88, 0x42, 0x0c, 0xd2, 0x2a, 0x68, 
+0x12, 0x18, 0x09, 0x1a, 0x10, 0x1c, 0x00, 0xf0, 0x05, 0xf9, 0xc0, 0x43, 
+0x01, 0x04, 0x09, 0x0c, 0x20, 0x1c, 0xff, 0xf7, 0x26, 0xff, 0x04, 0x1c, 
+0xe0, 0x43, 0x00, 0x04, 0x00, 0x0c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x6b, 0xc0, 0x08, 0x1a, 0xd3, 0xb8, 0x6a, 
+0xf9, 0x6b, 0x40, 0x18, 0x79, 0x6c, 0x00, 0xf0, 0xed, 0xf8, 0xc0, 0x43, 
+0x01, 0x04, 0x09, 0x0c, 0x0a, 0x48, 0x07, 0xd0, 0x20, 0x23, 0xb9, 0x69, 
+0x19, 0x43, 0xb9, 0x61, 0x01, 0x6b, 0x01, 0x31, 0x01, 0x63, 0x07, 0xe0, 
+0xff, 0x23, 0x01, 0x33, 0xb9, 0x69, 0x19, 0x43, 0xb9, 0x61, 0x41, 0x6a, 
+0x01, 0x31, 0x41, 0x62, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x0c, 0x2b, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x6b, 0x41, 0x09, 
+0x1c, 0xd3, 0xc0, 0x08, 0x1a, 0xd3, 0xf8, 0x1d, 0x39, 0x30, 0x00, 0x7b, 
+0x06, 0x28, 0x15, 0xd1, 0x38, 0x1c, 0x00, 0xf0, 0x53, 0xf8, 0x01, 0x1c, 
+0x0a, 0x48, 0x07, 0xd0, 0x40, 0x23, 0xb9, 0x69, 
 0x19, 0x43, 0xb9, 0x61, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 0x07, 0xe0, 
-0x01, 0x23, 0x9b, 0x02, 0xb9, 0x69, 0x19, 0x43, 
-0xb9, 0x61, 0xc1, 0x6a, 0x01, 0x31, 0xc1, 0x62, 0x00, 0x20, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x78, 0x2a, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c, 
-0xb8, 0x6b, 0x81, 0x09, 0x2c, 0xd3, 0xc0, 0x08, 0x2a, 0xd3, 0xf8, 0x1d, 
-0x39, 0x30, 0x00, 0x7b, 0x11, 0x28, 0x25, 0xd1, 0xb8, 0x6a, 0x39, 0x6c, 
-0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x06, 0x30, 0x18, 0x43, 0x00, 0x68, 
-0x05, 0x04, 0x2d, 0x0c, 0x0f, 0x4c, 0x11, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
-0x1f, 0xf8, 0x00, 0x28, 0x0c, 0xd0, 0xa8, 0x42, 0x02, 0xd1, 0x0c, 0x4b, 
-0x98, 0x42, 0x07, 0xd0, 0x80, 0x23, 0xb8, 0x69, 0x18, 0x43, 0xb8, 0x61, 
-0x60, 0x6b, 0x01, 0x30, 0x60, 0x63, 0x07, 0xe0, 0x01, 0x23, 0x5b, 0x02, 
-0xb8, 0x69, 0x18, 0x43, 0xb8, 0x61, 0xa0, 0x6a, 0x01, 0x30, 0xa0, 0x62, 
-0x00, 0x20, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x78, 0x2a, 0x00, 0x80, 
-0xff, 0xff, 0x00, 0x00, 0xf0, 0xb5, 0xff, 0xb0, 0x99, 0xb0, 0x04, 0x1c, 
-0xe0, 0x6b, 0x61, 0x6c, 0x09, 0x18, 0x03, 0xaa, 0x85, 0x18, 0xa3, 0x6a, 
-0x00, 0x20, 0x8a, 0x08, 0x01, 0x32, 0x97, 0x92, 0x07, 0xd0, 0x82, 0x00, 
-0x9f, 0x58, 0x03, 0xae, 0xb7, 0x50, 0x97, 0x9a, 0x01, 0x30, 0x82, 0x42, 
-0xf7, 0xd8, 0x60, 0x6a, 0x01, 0x23, 0x9b, 0x07, 0x04, 0x30, 0x18, 0x43, 
-0x00, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x02, 0xaf, 0x3f, 0x88, 0x03, 0xa8, 
-0xff, 0xf7, 0x87, 0xfe, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 
-0xff, 0xf7, 0x6d, 0xfe, 0x07, 0x1c, 0xe0, 0x6b, 0xa1, 0x6c, 0x40, 0x18, 
-0x61, 0x6a, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x31, 0x19, 0x43, 0x09, 0x68, 
-0xc0, 0x46, 0x01, 0x91, 0x01, 0xa9, 0x09, 0x88, 0x01, 0x31, 0x88, 0x42, 
-0x0c, 0xd2, 0xa2, 0x6a, 0x12, 0x18, 0x09, 0x1a, 0x10, 0x1c, 0x00, 0xf0, 
-0x2f, 0xf8, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 0xff, 0xf7, 
-0x50, 0xfe, 0x07, 0x1c, 0xa8, 0x89, 0xe9, 0x89, 0x08, 0x18, 0x29, 0x8a, 
-0x08, 0x18, 0x69, 0x8a, 0x08, 0x18, 0x69, 0x7a, 0x09, 0x02, 0x08, 0x18, 
-0xa1, 0x6c, 0x62, 0x6c, 0x89, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 
-0x12, 0x0a, 0x11, 0x43, 0x09, 0x04, 0x09, 0x0c, 0x09, 0x18, 0x08, 0x0c, 
-0x05, 0xd0, 0x08, 0x04, 0x00, 0x0c, 0x09, 0x0c, 0x41, 0x18, 0x08, 0x0c, 
-0xf9, 0xd1, 0x38, 0x1c, 0xff, 0xf7, 0x2f, 0xfe, 0xc0, 0x43, 0x00, 0x04, 
-0x00, 0x0c, 0x7f, 0xb0, 0x19, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xb0, 0xb4, 0x00, 0x22, 0x00, 0x29, 0x2e, 0xd0, 0x83, 0x07, 0x9b, 0x0f, 
-0xdc, 0x00, 0x47, 0x18, 0x04, 0x25, 0xef, 0x1b, 0xbf, 0x07, 0xbf, 0x0f, 
-0xff, 0x00, 0x80, 0x08, 0x80, 0x00, 0x59, 0x18, 0x03, 0x31, 0x89, 0x08, 
-0x4d, 0x1e, 0x02, 0xc8, 0xe1, 0x40, 0xa1, 0x40, 0x6b, 0x1e, 0x00, 0x2d, 
-0x09, 0xd0, 0x0c, 0x04, 0x24, 0x0c, 0xa2, 0x18, 0x09, 0x0c, 0x8a, 0x18, 
-0x02, 0xc8, 0x1c, 0x1c, 0x01, 0x3b, 0x00, 0x2c, 0xf5, 0xd1, 0xb9, 0x40, 
-0x08, 0x1c, 0xf8, 0x40, 0x01, 0x04, 0x09, 0x0c, 0x89, 0x18, 0x00, 0x0c, 
-0x42, 0x18, 0x10, 0x0c, 0x05, 0xd0, 0x10, 0x04, 0x00, 0x0c, 0x11, 0x0c, 
-0x42, 0x18, 0x10, 0x0c, 0xf9, 0xd1, 0x10, 0x04, 0x00, 0x0c, 0xb0, 0xbc, 
-0x70, 0x47, 0x00, 0x00, 0x90, 0xb4, 0x00, 0x20, 0x01, 0x27, 0x11, 0x49, 
-0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x53, 0x18, 0x9c, 0x68, 0x01, 0x23, 
+0x01, 0x23, 0x9b, 0x02, 0xb9, 0x69, 0x19, 0x43, 0xb9, 0x61, 0xc1, 0x6a, 
+0x01, 0x31, 0xc1, 0x62, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x0c, 0x2b, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c, 0xb8, 0x6b, 0x81, 0x09, 
+0x2c, 0xd3, 0xc0, 0x08, 0x2a, 0xd3, 0xf8, 0x1d, 0x39, 0x30, 0x00, 0x7b, 
+0x11, 0x28, 0x25, 0xd1, 0xb8, 0x6a, 0x39, 0x6c, 0x40, 0x18, 0x01, 0x23, 
+0x9b, 0x07, 0x06, 0x30, 0x18, 0x43, 0x00, 0x68, 0x05, 0x04, 0x2d, 0x0c, 
+0x0f, 0x4c, 0x11, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0x00, 0x28, 
+0x0c, 0xd0, 0xa8, 0x42, 0x02, 0xd1, 0x0c, 0x4b, 0x98, 0x42, 0x07, 0xd0, 
+0x80, 0x23, 0xb8, 0x69, 0x18, 0x43, 0xb8, 0x61, 0x60, 0x6b, 0x01, 0x30, 
+0x60, 0x63, 0x07, 0xe0, 0x01, 0x23, 0x5b, 0x02, 0xb8, 0x69, 0x18, 0x43, 
+0xb8, 0x61, 0xa0, 0x6a, 0x01, 0x30, 0xa0, 0x62, 0x00, 0x20, 0xb0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
+0xf0, 0xb5, 0xff, 0xb0, 0x99, 0xb0, 0x04, 0x1c, 0xe0, 0x6b, 0x61, 0x6c, 
+0x09, 0x18, 0x03, 0xaa, 0x85, 0x18, 0xa3, 0x6a, 0x00, 0x20, 0x8a, 0x08, 
+0x01, 0x32, 0x97, 0x92, 0x07, 0xd0, 0x82, 0x00, 0x9f, 0x58, 0x03, 0xae, 
+0xb7, 0x50, 0x97, 0x9a, 0x01, 0x30, 0x82, 0x42, 0xf7, 0xd8, 0x60, 0x6a, 
+0x01, 0x23, 0x9b, 0x07, 0x04, 0x30, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 
+0x02, 0x90, 0x02, 0xaf, 0x3f, 0x88, 0x03, 0xa8, 0xff, 0xf7, 0x87, 0xfe, 
+0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 0xff, 0xf7, 0x6d, 0xfe, 
+0x07, 0x1c, 0xe0, 0x6b, 0xa1, 0x6c, 0x40, 0x18, 0x61, 0x6a, 0x01, 0x23, 
+0x9b, 0x07, 0x08, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x01, 0x91, 
+0x01, 0xa9, 0x09, 0x88, 0x01, 0x31, 0x88, 0x42, 0x0c, 0xd2, 0xa2, 0x6a, 
+0x12, 0x18, 0x09, 0x1a, 0x10, 0x1c, 0x00, 0xf0, 0x2f, 0xf8, 0xc0, 0x43, 
+0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 0xff, 0xf7, 0x50, 0xfe, 0x07, 0x1c, 
+0xa8, 0x89, 0xe9, 0x89, 0x08, 0x18, 0x29, 0x8a, 0x08, 0x18, 0x69, 0x8a, 
+0x08, 0x18, 0x69, 0x7a, 0x09, 0x02, 0x08, 0x18, 0xa1, 0x6c, 0x62, 0x6c, 
+0x89, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 0x12, 0x0a, 0x11, 0x43, 
+0x09, 0x04, 0x09, 0x0c, 0x09, 0x18, 0x08, 0x0c, 0x05, 0xd0, 0x08, 0x04, 
+0x00, 0x0c, 0x09, 0x0c, 0x41, 0x18, 0x08, 0x0c, 0xf9, 0xd1, 0x38, 0x1c, 
+0xff, 0xf7, 0x2f, 0xfe, 0xc0, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x7f, 0xb0, 
+0x19, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb4, 0x00, 0x22, 
+0x00, 0x29, 0x2e, 0xd0, 0x83, 0x07, 0x9b, 0x0f, 0xdc, 0x00, 0x47, 0x18, 
+0x04, 0x25, 0xef, 0x1b, 0xbf, 0x07, 0xbf, 0x0f, 0xff, 0x00, 0x80, 0x08, 
+0x80, 0x00, 0x59, 0x18, 0x03, 0x31, 0x89, 0x08, 0x4d, 0x1e, 0x02, 0xc8, 
+0xe1, 0x40, 0xa1, 0x40, 0x6b, 0x1e, 0x00, 0x2d, 0x09, 0xd0, 0x0c, 0x04, 
+0x24, 0x0c, 0xa2, 0x18, 0x09, 0x0c, 0x8a, 0x18, 0x02, 0xc8, 0x1c, 0x1c, 
+0x01, 0x3b, 0x00, 0x2c, 0xf5, 0xd1, 0xb9, 0x40, 0x08, 0x1c, 0xf8, 0x40, 
+0x01, 0x04, 0x09, 0x0c, 0x89, 0x18, 0x00, 0x0c, 0x42, 0x18, 0x10, 0x0c, 
+0x05, 0xd0, 0x10, 0x04, 0x00, 0x0c, 0x11, 0x0c, 0x42, 0x18, 0x10, 0x0c, 
+0xf9, 0xd1, 0x10, 0x04, 0x00, 0x0c, 0xb0, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0x90, 0xb4, 0x00, 0x20, 0x01, 0x27, 0x11, 0x49, 0x42, 0x00, 0x12, 0x18, 
+0xd2, 0x00, 0x53, 0x18, 0x9c, 0x68, 0x01, 0x23, 
 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x1b, 0x03, 0x1b, 0x0b, 0x8a, 0x58, 
-0x12, 0x03, 0x12, 0x0b, 0x93, 0x42, 0x0c, 0xd1, 
-0x01, 0x30, 0x04, 0x28, 0xec, 0xd3, 0x08, 0x48, 0xc0, 0x6a, 0x01, 0x03, 
-0x09, 0x0b, 0x07, 0x48, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x0b, 0x81, 0x42, 
-0x02, 0xd0, 0x38, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 0xfb, 0xe7, 
-0x28, 0x03, 0x00, 0x80, 0x00, 0x40, 0x14, 0x40, 0xe8, 0x0d, 0x00, 0x80, 
-0x98, 0xb4, 0x14, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x83, 0x00, 0x13, 0x48, 
-0xc0, 0x58, 0x07, 0x03, 0x3f, 0x0b, 0x12, 0x48, 0xc0, 0x58, 0x02, 0x03, 
-0x12, 0x0b, 0x11, 0x48, 0xc0, 0x58, 0x00, 0x03, 0x00, 0x0b, 0x10, 0x4c, 
-0xe4, 0x58, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x9b, 0x00, 
-0xcc, 0x00, 0x01, 0x21, 0x98, 0x42, 0x01, 0xd1, 0x08, 0x1c, 0x09, 0xe0, 
-0x98, 0x42, 0x03, 0xd9, 0x10, 0x1a, 0xda, 0x1b, 0x80, 0x18, 0x00, 0xe0, 
-0x18, 0x1a, 0x84, 0x42, 0xf4, 0xd3, 0x00, 0x20, 0x98, 0xbc, 0x70, 0x47, 
-0x55, 0x55, 0x55, 0x55, 0xa0, 0x03, 0x00, 0x80, 0xa8, 0x03, 0x00, 0x80, 
-0x88, 0x03, 0x00, 0x80, 0x98, 0x03, 0x00, 0x80, 0x80, 0xb4, 0x13, 0x04, 
-0x00, 0xd0, 0x01, 0x3a, 0x80, 0x00, 0x0b, 0x1c, 0x13, 0x49, 0x0f, 0x58, 
-0xc0, 0x46, 0x3b, 0x60, 0x0b, 0x58, 0xc0, 0x46, 0x5a, 0x60, 0x0a, 0x58, 
-0x08, 0x32, 0x10, 0x4b, 0x1b, 0x58, 0x9a, 0x42, 0x01, 0xd3, 0x0f, 0x4a, 
-0x12, 0x58, 0x0f, 0x4b, 0x1f, 0x58, 0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 
-0x1b, 0x68, 0x9b, 0x00, 0x17, 0x03, 0x3f, 0x0b, 0x9f, 0x42, 0x06, 0xd1, 
-0x0a, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60, 0x01, 0x20, 0x80, 0xbc, 
-0x70, 0x47, 0x08, 0x4b, 0x1b, 0x58, 0xc0, 0x46, 0x1a, 0x60, 0x0a, 0x50, 
-0x00, 0x20, 0xf6, 0xe7, 0x88, 0x03, 0x00, 0x80, 0xa8, 0x03, 0x00, 0x80, 
-0xa0, 0x03, 0x00, 0x80, 0x98, 0x03, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x90, 0x03, 0x00, 0x80, 0xff, 0x5f, 0x2d, 0xe9, 0x48, 0xfe, 0xff, 0xeb, 
-0x01, 0xb6, 0xa0, 0xe3, 0x01, 0xb1, 0x8b, 0xe2, 0x02, 0x8a, 0xa0, 0xe3, 
-0x01, 0x7a, 0xa0, 0xe3, 0x01, 0xa9, 0xa0, 0xe3, 0x01, 0x56, 0xa0, 0xe3, 
-0xc8, 0x60, 0x9f, 0xe5, 0xc8, 0x90, 0x9f, 0xe5, 0x14, 0x40, 0x9b, 0xe5, 
-0x00, 0x00, 0x54, 0xe3, 0x2c, 0x00, 0x00, 0x0a, 0x03, 0x0a, 0x14, 0xe3, 
-0x11, 0x00, 0x00, 0x0a, 0x0c, 0x00, 0x96, 0xe5, 0x00, 0x00, 0x50, 0xe3, 
-0x21, 0x00, 0x00, 0x0a, 0x01, 0x0a, 0x14, 0xe3, 0x05, 0x00, 0x00, 0x0a, 
-0x1c, 0x00, 0x96, 0xe5, 0x01, 0x0a, 0xc0, 0xe3, 0x1c, 0x00, 0x86, 0xe5, 
-0x1c, 0x00, 0x85, 0xe5, 0x14, 0x70, 0x85, 0xe5, 0x06, 0x00, 0x00, 0xea, 
-0x02, 0x0a, 0x14, 0xe3, 0x04, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x96, 0xe5, 
-0x02, 0x0a, 0xc0, 0xe3, 0x1c, 0x00, 0x86, 0xe5, 0x1c, 0x00, 0x85, 0xe5, 
-0x14, 0x80, 0x85, 0xe5, 0x01, 0x09, 0x14, 0xe3, 0x04, 0x00, 0x00, 0x0a, 
-0x1c, 0x00, 0x96, 0xe5, 0x01, 0x09, 0xc0, 0xe3, 0x1c, 0x00, 0x86, 0xe5, 
-0x1c, 0x00, 0x85, 0xe5, 0x14, 0xa0, 0x85, 0xe5, 0x02, 0x00, 0x14, 0xe3, 
-0x40, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x14, 0xe3, 0x54, 0x00, 0x00, 0x1b, 
-0x02, 0x0b, 0x14, 0xe3, 0x67, 0x00, 0x00, 0x1b, 0x01, 0x0b, 0x14, 0xe3, 
-0x20, 0x00, 0x00, 0x1b, 0x18, 0x00, 0x99, 0xe5, 0x01, 0x00, 0x80, 0xe2, 
-0x18, 0x00, 0x89, 0xe5, 0xd5, 0xff, 0xff, 0xea, 0x1c, 0x00, 0x96, 0xe5, 
+0x12, 0x03, 0x12, 0x0b, 0x93, 0x42, 0x0c, 0xd1, 0x01, 0x30, 0x04, 0x28, 
+0xec, 0xd3, 0x08, 0x48, 0xc0, 0x6a, 0x01, 0x03, 0x09, 0x0b, 0x07, 0x48, 
+0x00, 0x6f, 0x00, 0x03, 0x00, 0x0b, 0x81, 0x42, 0x02, 0xd0, 0x38, 0x1c, 
+0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 0xfb, 0xe7, 0xa8, 0x03, 0x00, 0x80, 
+0x00, 0x40, 0x14, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x98, 0xb4, 0x14, 0x4a, 
+0xc0, 0x46, 0x00, 0x92, 0x83, 0x00, 0x13, 0x48, 0xc0, 0x58, 0x07, 0x03, 
+0x3f, 0x0b, 0x12, 0x48, 0xc0, 0x58, 0x02, 0x03, 0x12, 0x0b, 0x11, 0x48, 
+0xc0, 0x58, 0x00, 0x03, 0x00, 0x0b, 0x10, 0x4c, 0xe4, 0x58, 0x01, 0x23, 
+0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x9b, 0x00, 0xcc, 0x00, 0x01, 0x21, 
+0x98, 0x42, 0x01, 0xd1, 0x08, 0x1c, 0x09, 0xe0, 0x98, 0x42, 0x03, 0xd9, 
+0x10, 0x1a, 0xda, 0x1b, 0x80, 0x18, 0x00, 0xe0, 0x18, 0x1a, 0x84, 0x42, 
+0xf4, 0xd3, 0x00, 0x20, 0x98, 0xbc, 0x70, 0x47, 0x55, 0x55, 0x55, 0x55, 
+0x20, 0x04, 0x00, 0x80, 0x28, 0x04, 0x00, 0x80, 0x08, 0x04, 0x00, 0x80, 
+0x18, 0x04, 0x00, 0x80, 0x80, 0xb4, 0x13, 0x04, 0x00, 0xd0, 0x01, 0x3a, 
+0x80, 0x00, 0x0b, 0x1c, 0x13, 0x49, 0x0f, 0x58, 0xc0, 0x46, 0x3b, 0x60, 
+0x0b, 0x58, 0xc0, 0x46, 0x5a, 0x60, 0x0a, 0x58, 0x08, 0x32, 0x10, 0x4b, 
+0x1b, 0x58, 0x9a, 0x42, 0x01, 0xd3, 0x0f, 0x4a, 0x12, 0x58, 0x0f, 0x4b, 
+0x1f, 0x58, 0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 0x1b, 0x68, 0x9b, 0x00, 
+0x17, 0x03, 0x3f, 0x0b, 0x9f, 0x42, 0x06, 0xd1, 0x0a, 0x48, 0xc1, 0x68, 
+0x01, 0x31, 0xc1, 0x60, 0x01, 0x20, 0x80, 0xbc, 0x70, 0x47, 0x08, 0x4b, 
+0x1b, 0x58, 0xc0, 0x46, 0x1a, 0x60, 0x0a, 0x50, 0x00, 0x20, 0xf6, 0xe7, 
+0x08, 0x04, 0x00, 0x80, 0x28, 0x04, 0x00, 0x80, 0x20, 0x04, 0x00, 0x80, 
+0x18, 0x04, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x10, 0x04, 0x00, 0x80, 
+0xff, 0x5f, 0x2d, 0xe9, 0x48, 0xfe, 0xff, 0xeb, 0x01, 0xb6, 0xa0, 0xe3, 
+0x01, 0xb1, 0x8b, 0xe2, 0x02, 0x8a, 0xa0, 0xe3, 0x01, 0x7a, 0xa0, 0xe3, 
+0x01, 0xa9, 0xa0, 0xe3, 0x01, 0x56, 0xa0, 0xe3, 0xc8, 0x60, 0x9f, 0xe5, 
+0xc8, 0x90, 0x9f, 0xe5, 0x14, 0x40, 0x9b, 0xe5, 0x00, 0x00, 0x54, 0xe3, 
+0x2c, 0x00, 0x00, 0x0a, 0x03, 0x0a, 0x14, 0xe3, 0x11, 0x00, 0x00, 0x0a, 
+0x0c, 0x00, 0x96, 0xe5, 0x00, 0x00, 0x50, 0xe3, 0x21, 0x00, 0x00, 0x0a, 
+0x01, 0x0a, 0x14, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x96, 0xe5, 
 0x01, 0x0a, 0xc0, 0xe3, 0x1c, 0x00, 0x86, 0xe5, 0x1c, 0x00, 0x85, 0xe5, 
+0x14, 0x70, 0x85, 0xe5, 0x06, 0x00, 0x00, 0xea, 0x02, 0x0a, 0x14, 0xe3, 
+0x04, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x96, 0xe5, 0x02, 0x0a, 0xc0, 0xe3, 
+0x1c, 0x00, 0x86, 0xe5, 0x1c, 0x00, 0x85, 0xe5, 0x14, 0x80, 0x85, 0xe5, 
+0x01, 0x09, 0x14, 0xe3, 0x04, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x96, 0xe5, 
+0x01, 0x09, 0xc0, 0xe3, 0x1c, 0x00, 0x86, 0xe5, 0x1c, 0x00, 0x85, 0xe5, 
+0x14, 0xa0, 0x85, 0xe5, 0x02, 0x00, 0x14, 0xe3, 0x40, 0x00, 0x00, 0x1b, 
+0x01, 0x00, 0x14, 0xe3, 0x54, 0x00, 0x00, 0x1b, 0x02, 0x0b, 0x14, 0xe3, 
+0x67, 0x00, 0x00, 0x1b, 0x01, 0x0b, 0x14, 0xe3, 0x20, 0x00, 0x00, 0x1b, 
+0x18, 0x00, 0x99, 0xe5, 0x01, 0x00, 0x80, 0xe2, 0x18, 0x00, 0x89, 0xe5, 
+0xd5, 0xff, 0xff, 0xea, 0x1c, 0x00, 0x96, 0xe5, 0x01, 0x0a, 0xc0, 0xe3, 
+0x1c, 0x00, 0x86, 0xe5, 0x1c, 0x00, 0x85, 0xe5, 
 0x14, 0x70, 0x85, 0xe5, 0xe1, 0xff, 0xff, 0xea, 0xff, 0x5f, 0xbd, 0xe8, 
-0x04, 0xf0, 0x5e, 0xe2, 0xe8, 0x0d, 0x00, 0x80, 
-0x08, 0x83, 0x20, 0x40, 0x10, 0x10, 0x1f, 0xe5, 0x14, 0x30, 0x91, 0xe5, 
-0x00, 0x20, 0xc3, 0xe1, 0x14, 0x20, 0x81, 0xe5, 0x01, 0x16, 0xa0, 0xe3, 
-0x0c, 0x20, 0x81, 0xe5, 0x0b, 0x12, 0xa0, 0xe3, 0x00, 0x00, 0x81, 0xe5, 
-0x18, 0x10, 0x9f, 0xe5, 0xb0, 0x24, 0xd1, 0xe1, 0x01, 0x20, 0x82, 0xe2, 
-0xb0, 0x24, 0xc1, 0xe1, 0x3c, 0x20, 0x91, 0xe5, 0x00, 0x00, 0x82, 0xe1, 
-0x3c, 0x00, 0x81, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xa0, 0x82, 0x20, 0x40, 
-0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x01, 0x0b, 0xa0, 0xe3, 
-0x01, 0x16, 0xa0, 0xe3, 0x14, 0x00, 0x81, 0xe5, 0x00, 0x1a, 0x81, 0xe1, 
-0x24, 0x20, 0x91, 0xe5, 0x70, 0x00, 0x1f, 0xe5, 0x00, 0x00, 0x00, 0x00, 
-0x24, 0x20, 0x80, 0xe5, 0x28, 0x10, 0x91, 0xe5, 0x00, 0x00, 0x00, 0x00, 
-0x28, 0x10, 0x80, 0xe5, 0x2c, 0x20, 0x90, 0xe5, 0x01, 0x20, 0x82, 0xe2, 
-0x2c, 0x20, 0x80, 0xe5, 0x3f, 0x00, 0x01, 0xe2, 0x3f, 0x00, 0x50, 0xe3, 
-0x1e, 0xff, 0x2f, 0x11, 0x18, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0x90, 0xe5, 
-0x01, 0x10, 0x81, 0xe2, 0x00, 0x10, 0x80, 0xe5, 0x02, 0x18, 0xa0, 0xe3, 
-0x0b, 0x02, 0xa0, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0xb0, 0x03, 0x00, 0x80, 0x01, 0x06, 0xa0, 0xe3, 0x01, 0x01, 0x80, 0xe2, 
-0x00, 0x10, 0x90, 0xe5, 0x01, 0x08, 0x11, 0xe3, 0x0b, 0x10, 0xa0, 0xe3, 
+0x04, 0xf0, 0x5e, 0xe2, 0x68, 0x0e, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40, 
+0x10, 0x10, 0x1f, 0xe5, 0x14, 0x30, 0x91, 0xe5, 0x00, 0x20, 0xc3, 0xe1, 
+0x14, 0x20, 0x81, 0xe5, 0x01, 0x16, 0xa0, 0xe3, 0x0c, 0x20, 0x81, 0xe5, 
+0x0b, 0x12, 0xa0, 0xe3, 0x00, 0x00, 0x81, 0xe5, 0x18, 0x10, 0x9f, 0xe5, 
+0xb0, 0x24, 0xd1, 0xe1, 0x01, 0x20, 0x82, 0xe2, 0xb0, 0x24, 0xc1, 0xe1, 
+0x3c, 0x20, 0x91, 0xe5, 0x00, 0x00, 0x82, 0xe1, 0x3c, 0x00, 0x81, 0xe5, 
+0x1e, 0xff, 0x2f, 0xe1, 0xa0, 0x82, 0x20, 0x40, 0xff, 0xff, 0xff, 0xea, 
+0xfe, 0xff, 0xff, 0xea, 0x01, 0x0b, 0xa0, 0xe3, 0x01, 0x16, 0xa0, 0xe3, 
+0x14, 0x00, 0x81, 0xe5, 0x00, 0x1a, 0x81, 0xe1, 0x24, 0x20, 0x91, 0xe5, 
+0x70, 0x00, 0x1f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x24, 0x20, 0x80, 0xe5, 
+0x28, 0x10, 0x91, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x28, 0x10, 0x80, 0xe5, 
+0x2c, 0x20, 0x90, 0xe5, 0x01, 0x20, 0x82, 0xe2, 0x2c, 0x20, 0x80, 0xe5, 
+0x3f, 0x00, 0x01, 0xe2, 0x3f, 0x00, 0x50, 0xe3, 0x1e, 0xff, 0x2f, 0x11, 
+0x18, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0x90, 0xe5, 0x01, 0x10, 0x81, 0xe2, 
+0x00, 0x10, 0x80, 0xe5, 0x02, 0x18, 0xa0, 0xe3, 0x0b, 0x02, 0xa0, 0xe3, 
+0x00, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x30, 0x04, 0x00, 0x80, 
+0x01, 0x06, 0xa0, 0xe3, 0x01, 0x01, 0x80, 0xe2, 0x00, 0x10, 0x90, 0xe5, 
+0x01, 0x08, 0x11, 0xe3, 0x0b, 0x10, 0xa0, 0xe3, 0x02, 0x19, 0x81, 0xe2, 
+0x05, 0x00, 0x00, 0x1a, 0x00, 0x20, 0x90, 0xe5, 0x42, 0x28, 0xb0, 0xe1, 
+0x05, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x90, 0xe5, 0x02, 0x0c, 0x10, 0xe3, 
+0x02, 0x00, 0x00, 0x0a, 0x06, 0x07, 0xa0, 0xe3, 0x4c, 0x11, 0x80, 0xe5, 
+0x03, 0x00, 0x00, 0xea, 0x0c, 0x00, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 
+0x40, 0x10, 0x80, 0xe5, 0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 
+0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0xa0, 0xe3, 0x01, 0x01, 0x80, 0xe2, 
+0x00, 0x10, 0x90, 0xe5, 0x01, 0x08, 0x11, 0xe3, 0x0c, 0x10, 0xa0, 0xe3, 
 0x02, 0x19, 0x81, 0xe2, 0x05, 0x00, 0x00, 0x1a, 0x00, 0x20, 0x90, 0xe5, 
 0x42, 0x28, 0xb0, 0xe1, 0x05, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x90, 0xe5, 
 0x02, 0x0c, 0x10, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x06, 0x07, 0xa0, 0xe3, 
-0x4c, 0x11, 0x80, 0xe5, 0x03, 0x00, 0x00, 0xea, 0x0c, 0x00, 0x9f, 0xe5, 
+0x4c, 0x11, 0x80, 0xe5, 0x03, 0x00, 0x00, 0xea, 0x4c, 0x00, 0x1f, 0xe5, 
 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x80, 0xe5, 0xff, 0xff, 0xff, 0xea, 
-0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0xa0, 0xe3, 
-0x01, 0x01, 0x80, 0xe2, 0x00, 0x10, 0x90, 0xe5, 0x01, 0x08, 0x11, 0xe3, 
-0x0c, 0x10, 0xa0, 0xe3, 0x02, 0x19, 0x81, 0xe2, 0x05, 0x00, 0x00, 0x1a, 
-0x00, 0x20, 0x90, 0xe5, 0x42, 0x28, 0xb0, 0xe1, 0x05, 0x00, 0x00, 0x1a, 
-0x00, 0x00, 0x90, 0xe5, 0x02, 0x0c, 0x10, 0xe3, 0x02, 0x00, 0x00, 0x0a, 
-0x06, 0x07, 0xa0, 0xe3, 0x4c, 0x11, 0x80, 0xe5, 0x03, 0x00, 0x00, 0xea, 
-0x4c, 0x00, 0x1f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x80, 0xe5, 
-0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x1b, 0xa0, 0xe3, 
-0x01, 0x06, 0xa0, 0xe3, 0x14, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0x80, 0x21, 0x1f, 0xe5, 0x14, 0x30, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x30, 0x80, 0xe5, 0x1c, 0x00, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x81, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x14, 0x10, 0x82, 0xe5, 
-0x01, 0x06, 0xa0, 0xe3, 0x1c, 0x10, 0x82, 0xe5, 0x0c, 0x10, 0x80, 0xe5, 
-0x1c, 0x10, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x80, 0xe5, 
-0x1e, 0xff, 0x2f, 0xe1, 0xc0, 0x21, 0x1f, 0xe5, 0x00, 0x00, 0x00, 0x00, 
-0x1c, 0x10, 0x82, 0xe5, 0x01, 0x16, 0xa0, 0xe3, 0x14, 0x00, 0x82, 0xe5, 
-0x0c, 0x00, 0x81, 0xe5, 0x1c, 0x00, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 
-0x1c, 0x00, 0x81, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0xb5, 0x0f, 0x1c, 
-0x38, 0x1c, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0x28, 0x02, 0xd0, 0x38, 0x1c, 
-0x00, 0xf0, 0x76, 0xf8, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x80, 0xb5, 0x0f, 0x1c, 0x38, 0x1c, 0x00, 0xf0, 
-0x09, 0xf8, 0x00, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x68, 0xf8, 
-0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb4, 0x07, 0x68, 
-0x3a, 0x78, 0xd2, 0x07, 0xd2, 0x0f, 0x00, 0x24, 0x00, 0x2a, 0x03, 0xd0, 
-0xff, 0x22, 0x01, 0x32, 0x42, 0x60, 0x00, 0xe0, 0x44, 0x60, 0x3a, 0x7b, 
-0x7b, 0x7b, 0x1b, 0x02, 0x1a, 0x43, 0x81, 0x2a, 0x08, 0xd1, 0x01, 0x23, 
-0x5b, 0x02, 0x42, 0x68, 0x1a, 0x43, 0x42, 0x60, 0x04, 0x22, 0xbf, 0x18, 
-0x82, 0x60, 0x00, 0xe0, 0x84, 0x60, 0x3a, 0x7b, 0x7b, 0x7b, 0x1b, 0x02, 
-0x1a, 0x43, 0x08, 0x2a, 0x06, 0xd1, 0x06, 0x23, 0x41, 0x68, 0x19, 0x43, 
-0x41, 0x60, 0x81, 0x68, 0x0e, 0x31, 0x2c, 0xe0, 0x13, 0x02, 0x12, 0x0a, 
-0x12, 0x06, 0x12, 0x0e, 0x1a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x2e, 0x3a, 
-0x16, 0x4b, 0x9a, 0x42, 0x24, 0xd8, 0x01, 0x25, 0x42, 0x68, 0x15, 0x43, 
-0x45, 0x60, 0xba, 0x7b, 0xfb, 0x7b, 0x1b, 0x02, 0x1a, 0x43, 0x12, 0x4b, 
-0x9a, 0x42, 0x19, 0xd1, 0xfb, 0x1d, 0x09, 0x33, 0x44, 0xcb, 0x9b, 0x07, 
-0xdb, 0x0e, 0xda, 0x40, 0x5b, 0x42, 0x20, 0x33, 0x9e, 0x40, 0x16, 0x43, 
-0x03, 0x2e, 0x0f, 0xd1, 0x39, 0x7d, 0x7b, 0x7d, 0x1b, 0x02, 0x19, 0x43, 
-0x08, 0x29, 0x07, 0xd1, 0x04, 0x21, 0x29, 0x43, 0x41, 0x60, 0x81, 0x68, 
-0x16, 0x31, 0x81, 0x60, 0x01, 0x21, 0x01, 0xe0, 0x00, 0x21, 0x84, 0x60, 
-0x08, 0x1c, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xae, 0x05, 0x00, 0x00, 
-0xaa, 0xaa, 0x00, 0x00, 0x80, 0xb4, 0x42, 0x68, 0xd1, 0x08, 0x3f, 0xd3, 
-0x01, 0x68, 0x83, 0x68, 0x59, 0x18, 0x02, 0x39, 0x8f, 0x78, 0x3f, 0x07, 
-0x3f, 0x0f, 0x05, 0x2f, 0x03, 0xd1, 0xda, 0x1d, 0x0d, 0x32, 0xc2, 0x60, 
-0x05, 0xe0, 0xbf, 0x00, 0xdb, 0x19, 0xc3, 0x60, 0x08, 0x23, 0x1a, 0x43, 
-0x42, 0x60, 0x8a, 0x78, 0x12, 0x07, 0x12, 0x0f, 0x92, 0x00, 0x02, 0x61, 
-0x0a, 0x79, 0x4b, 0x79, 0x1b, 0x02, 0x1a, 0x43, 0x13, 0x02, 0x12, 0x0a, 
-0x12, 0x06, 0x12, 0x0e, 0x1a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x42, 0x61, 
-0xca, 0x7a, 0x06, 0x2a, 0x03, 0xd1, 0x10, 0x23, 0x42, 0x68, 0x1a, 0x43, 
-0x10, 0xe0, 0x11, 0x2a, 0x03, 0xd1, 0x20, 0x23, 0x42, 0x68, 0x1a, 0x43, 
-0x0a, 0xe0, 0x33, 0x2a, 0x03, 0xd1, 0x40, 0x23, 0x42, 0x68, 0x1a, 0x43, 
-0x04, 0xe0, 0x32, 0x2a, 0x03, 0xd1, 0x80, 0x23, 0x42, 0x68, 0x1a, 0x43, 
-0x42, 0x60, 0xc9, 0x7a, 0xc0, 0x46, 0x01, 0x76, 0x80, 0xbc, 0x70, 0x47, 
-0x0a, 0x78, 0xc0, 0x46, 0x02, 0x60, 0x4b, 0x78, 0x1b, 0x02, 0x1a, 0x43, 
-0x02, 0x60, 0x8b, 0x78, 0x1b, 0x04, 0x1a, 0x43, 0x02, 0x60, 0xc9, 0x78, 
-0x09, 0x06, 0x11, 0x43, 0x01, 0x60, 0x70, 0x47, 0x80, 0xb5, 0x07, 0x1c, 
-0x48, 0x68, 0x80, 0x09, 0x26, 0xd3, 0xb8, 0x6a, 0xc9, 0x68, 0x40, 0x18, 
-0x01, 0x23, 0x9b, 0x07, 0x02, 0x30, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 
-0x00, 0x0c, 0x11, 0x23, 0x9b, 0x02, 0x98, 0x42, 0x18, 0xd1, 0x78, 0x6a, 
-0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xb0, 0xf8, 
-0x38, 0x1c, 0x01, 0xf0, 0x6d, 0xfd, 0x01, 0x20, 0x07, 0x49, 0xc0, 0x46, 
-0xc8, 0x72, 0x07, 0x49, 0x4a, 0x6c, 0x12, 0x18, 0x4a, 0x64, 0x06, 0x49, 
-0x8a, 0x6d, 0x12, 0x18, 0x8a, 0x65, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x20, 0xfa, 0xe7, 0x98, 0x19, 0x00, 0x80, 0x78, 0x2a, 0x00, 0x80, 
-0x10, 0x2a, 0x00, 0x80, 0x81, 0x07, 0x19, 0xd0, 0x80, 0x08, 0x80, 0x00, 
-0x01, 0x23, 0x9b, 0x07, 0x01, 0x1d, 0x18, 0x43, 
-0x00, 0x68, 0x19, 0x43, 0x09, 0x68, 0x02, 0x02, 0x12, 0x0e, 0x12, 0x06, 
-0x00, 0x0a, 0xff, 0x23, 0x1b, 0x04, 0x18, 0x40, 0x10, 0x43, 0x0a, 0x0a, 
-0x12, 0x06, 0x12, 0x0e, 0x10, 0x43, 0x09, 0x02, 0x1b, 0x0a, 0x19, 0x40, 
-0x08, 0x43, 0x70, 0x47, 0x01, 0x23, 0x9b, 0x07, 0x18, 0x43, 0x00, 0x68, 
-0x01, 0x06, 0x02, 0x02, 0xff, 0x23, 0x1b, 0x04, 0x1a, 0x40, 0x11, 0x43, 
-0x02, 0x0a, 0x1b, 0x0a, 0x1a, 0x40, 0x11, 0x43, 0x00, 0x0e, 0x08, 0x43, 
-0xed, 0xe7, 0x00, 0x00, 0xf0, 0xb5, 0x04, 0x23, 0x81, 0x6b, 0x19, 0x40, 
-0x00, 0x22, 0x00, 0x29, 0x46, 0xd0, 0xc7, 0x1d, 0x39, 0x37, 0x39, 0x7b, 
-0x33, 0x29, 0x01, 0xd0, 0x32, 0x29, 0x3f, 0xd1, 0x01, 0x6b, 0xc0, 0x46, 
-0x4a, 0x65, 0xc4, 0x1d, 0x2d, 0x34, 0xcd, 0x1d, 0x2d, 0x35, 0x00, 0x22, 
-0x93, 0x00, 0xe6, 0x58, 0xc0, 0x46, 0xee, 0x50, 0x01, 0x32, 0x07, 0x2a, 
-0xf8, 0xd3, 0x82, 0x6a, 0xc0, 0x46, 0x4a, 0x63, 0x82, 0x6a, 0xc0, 0x46, 
-0x8a, 0x62, 0x7a, 0x8b, 0xcb, 0x1d, 0x39, 0x33, 0x5a, 0x83, 0x40, 0x6a, 
-0xc0, 0x46, 0x48, 0x62, 0x12, 0x48, 0x01, 0x27, 0x42, 0x68, 0x00, 0x2a, 
-0x10, 0xd1, 0xc2, 0x68, 0x00, 0x2a, 0x13, 0xd1, 0x42, 0x69, 0x00, 0x2a, 
-0x0d, 0xd1, 0x01, 0x61, 0xc1, 0x60, 0x01, 0x6a, 0x02, 0x29, 0x02, 0xd3, 
-0x20, 0x30, 0x07, 0x71, 0x0c, 0xe0, 0x00, 0xf0, 0x13, 0xf8, 0x09, 0xe0, 
-0xc2, 0x68, 0x00, 0x2a, 0x02, 0xd1, 0x01, 0x61, 0xc1, 0x60, 0x03, 0xe0, 
-0x02, 0x69, 0xc0, 0x46, 0x51, 0x65, 0x01, 0x61, 0x38, 0x1c, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x10, 0x1c, 0xfa, 0xe7, 0xec, 0x05, 0x00, 0x80, 
-0x80, 0xb5, 0x1e, 0x49, 0x00, 0x22, 0xcb, 0x68, 0x00, 0x2b, 0x34, 0xd0, 
-0xc8, 0x1d, 0xf9, 0x30, 0x83, 0x62, 0xcb, 0x68, 0x9b, 0x6a, 0xc0, 0x46, 
-0xc3, 0x62, 0xcf, 0x69, 0x7b, 0x00, 0xdf, 0x19, 0x7f, 0x02, 0x17, 0x4b, 
-0xff, 0x18, 0xff, 0x37, 0x65, 0x37, 0x83, 0x63, 0x07, 0x63, 0xcb, 0x1d, 
-0xff, 0x33, 0x5a, 0x33, 0x1a, 0x72, 0xcb, 0x69, 0x00, 0x2b, 0x01, 0xd0, 
-0xca, 0x61, 0x01, 0xe0, 0x01, 0x23, 0xcb, 0x61, 0x0f, 0x1c, 0xc9, 0x68, 
-0x49, 0x6a, 0x09, 0x89, 0x01, 0x31, 0x41, 0x63, 0xf8, 0x1d, 0xff, 0x30, 
-0x3a, 0x30, 0x42, 0x60, 0x02, 0x82, 0x82, 0x60, 0xc2, 0x60, 0x38, 0x1c, 
-0x00, 0xf0, 0xc4, 0xfa, 0x38, 0x6a, 0x01, 0x30, 0x38, 0x62, 0x38, 0x1c, 
-0x00, 0xf0, 0x0a, 0xf8, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x10, 0x1c, 
-0xfa, 0xe7, 0x00, 0x00, 0xec, 0x05, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 
-0xf0, 0xb5, 0x07, 0x1c, 0xf9, 0x1d, 0xf9, 0x31, 0x88, 0x6a, 0xc2, 0x1d, 
-0x2d, 0x32, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x32, 0x1a, 0x43, 0xc8, 0x6a, 
-0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x80, 0x18, 0x82, 0x79, 0xc3, 0x79, 
-0x1b, 0x02, 0x1a, 0x43, 0x13, 0x02, 0x12, 0x0a, 0x12, 0x06, 0x12, 0x0e, 
-0x1a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x02, 0x38, 0x92, 0x04, 0x92, 0x0c, 
-0x00, 0x26, 0x25, 0x4d, 0xec, 0x1d, 0xff, 0x34, 0x3a, 0x34, 0x00, 0x2a, 
-0x04, 0xd0, 0x20, 0x8a, 0x01, 0x23, 0x9b, 0x02, 0x18, 0x43, 0x2b, 0xe0, 
-0x01, 0x23, 0x9b, 0x07, 0xc2, 0x1d, 0x0d, 0x32, 0x1a, 0x43, 0x12, 0x68, 
-0x12, 0x04, 0x12, 0x30, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 
-0x10, 0x43, 0x03, 0x1c, 0xf8, 0x1d, 0xff, 0x30, 0x4a, 0x30, 0x82, 0x78, 
-0xc8, 0x6b, 0x19, 0x1c, 0x01, 0xf0, 0xd8, 0xff, 0x00, 0x28, 0x04, 0xda, 
-0x20, 0x8a, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43, 
-0x0e, 0xe0, 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x08, 0x60, 0x01, 0x04, 
-0x09, 0x0c, 0x38, 0x1c, 0x00, 0xf0, 0x1c, 0xf8, 0x00, 0x28, 0x14, 0xd1, 
-0x20, 0x8a, 0x01, 0x23, 0x5b, 0x02, 0x18, 0x43, 0x20, 0x82, 0x21, 0x8a, 
-0x38, 0x1c, 0x00, 0xf0, 0x98, 0xfb, 0xe8, 0x68, 0x01, 0x23, 0x9b, 0x07, 
-0x54, 0x30, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xe8, 0x60, 0x30, 0x1c, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0xfa, 0xe7, 0x00, 0x00, 
-0xec, 0x05, 0x00, 0x80, 0xf8, 0xb5, 0x07, 0x1c, 0xfc, 0x1d, 0xf9, 0x34, 
-0xa0, 0x6b, 0xa6, 0x6a, 0xc5, 0x1d, 0x0d, 0x35, 0x33, 0x48, 0xc0, 0x6a, 
-0x4b, 0x00, 0x59, 0x18, 0x49, 0x01, 0x42, 0x18, 0x01, 0x20, 0x80, 0x07, 
-0x10, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x90, 0x01, 0x23, 
-0x9b, 0x07, 0xd0, 0x1d, 0x05, 0x30, 0x18, 0x43, 0x00, 0x68, 0x38, 0x1c, 
-0x29, 0x1c, 0x00, 0xf0, 0xb8, 0xfa, 0xa8, 0x88, 0x40, 0x07, 0x01, 0xd0, 
-0x00, 0x20, 0x47, 0xe0, 0x00, 0x98, 0x01, 0x28, 0x25, 0xd1, 0xe0, 0x6a, 
+0xfe, 0xff, 0xff, 0xea, 0x02, 0x1b, 0xa0, 0xe3, 0x01, 0x06, 0xa0, 0xe3, 
+0x14, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0x21, 0x1f, 0xe5, 
+0x14, 0x30, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0xe5, 
+0x1c, 0x00, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xe5, 
+0x00, 0x10, 0xa0, 0xe3, 0x14, 0x10, 0x82, 0xe5, 0x01, 0x06, 0xa0, 0xe3, 
+0x1c, 0x10, 0x82, 0xe5, 0x0c, 0x10, 0x80, 0xe5, 0x1c, 0x10, 0x92, 0xe5, 
+0x00, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
+0xc0, 0x21, 0x1f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x82, 0xe5, 
+0x01, 0x16, 0xa0, 0xe3, 0x14, 0x00, 0x82, 0xe5, 0x0c, 0x00, 0x81, 0xe5, 
+0x1c, 0x00, 0x92, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x81, 0xe5, 
+0x1e, 0xff, 0x2f, 0xe1, 0x80, 0xb5, 0x0f, 0x1c, 0x38, 0x1c, 0x00, 0xf0, 
+0x17, 0xf8, 0x00, 0x28, 0x02, 0xd0, 0x38, 0x1c, 
+0x00, 0xf0, 0x92, 0xf8, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0xb5, 0x0f, 0x1c, 0x38, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x00, 0x28, 
+0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x84, 0xf8, 0x00, 0x20, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb4, 0x07, 0x68, 0x3a, 0x78, 0xd2, 0x07, 
+0xd2, 0x0f, 0x00, 0x24, 0x00, 0x2a, 0x03, 0xd0, 0xff, 0x22, 0x01, 0x32, 
+0x42, 0x60, 0x00, 0xe0, 0x44, 0x60, 0x3a, 0x7b, 0x7b, 0x7b, 0x1b, 0x02, 
+0x1a, 0x43, 0x81, 0x2a, 0x08, 0xd1, 0x01, 0x23, 0x5b, 0x02, 0x42, 0x68, 
+0x1a, 0x43, 0x42, 0x60, 0x04, 0x22, 0xbf, 0x18, 0x82, 0x60, 0x00, 0xe0, 
+0x84, 0x60, 0x3a, 0x7b, 0x7b, 0x7b, 0x1b, 0x02, 0x1a, 0x43, 0x08, 0x2a, 
+0x06, 0xd1, 0x06, 0x23, 0x41, 0x68, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68, 
+0x0e, 0x31, 0x3c, 0xe0, 0xc1, 0x23, 0xdb, 0x00, 0x9a, 0x42, 0x03, 0xd1, 
+0x41, 0x68, 0x24, 0x4b, 0x19, 0x43, 0x3e, 0xe0, 0x23, 0x4b, 0x9a, 0x42, 
+0x04, 0xd1, 0x01, 0x23, 0x1b, 0x03, 0x41, 0x68, 0x19, 0x43, 0x36, 0xe0, 
+0x13, 0x02, 0x12, 0x0a, 0x12, 0x06, 0x12, 0x0e, 0x1a, 0x43, 0x12, 0x04, 
+0x12, 0x0c, 0x2e, 0x3a, 0x1c, 0x4b, 0x9a, 0x42, 0x2d, 0xd8, 0x01, 0x25, 
+0x42, 0x68, 0x15, 0x43, 0x45, 0x60, 0xba, 0x7b, 0xfb, 0x7b, 0x1b, 0x02, 
+0x1a, 0x43, 0x18, 0x4b, 0x9a, 0x42, 0x22, 0xd1, 0xfb, 0x1d, 0x09, 0x33, 
+0x44, 0xcb, 0x9b, 0x07, 0xdb, 0x0e, 0xda, 0x40, 0x5b, 0x42, 0x20, 0x33, 
+0x9e, 0x40, 0x16, 0x43, 0x03, 0x2e, 0x18, 0xd1, 0x39, 0x7d, 0x7b, 0x7d, 
+0x1b, 0x02, 0x19, 0x43, 0x08, 0x29, 0x07, 0xd1, 0x04, 0x21, 0x29, 0x43, 
+0x41, 0x60, 0x81, 0x68, 0x16, 0x31, 0x81, 0x60, 0x01, 0x21, 0x0a, 0xe0, 
+0xc1, 0x23, 0xdb, 0x00, 0x99, 0x42, 0x04, 0xd1, 0x01, 0x21, 0x89, 0x03, 
+0x29, 0x43, 0x41, 0x60, 0x00, 0xe0, 0x84, 0x60, 0x00, 0x21, 0x08, 0x1c, 
+0xf0, 0xbc, 0x70, 0x47, 0x02, 0x40, 0x00, 0x00, 0x81, 0x80, 0x00, 0x00, 
+0xae, 0x05, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x80, 0xb4, 0x42, 0x68, 
+0xd1, 0x08, 0x3f, 0xd3, 0x01, 0x68, 0x83, 0x68, 0x59, 0x18, 0x02, 0x39, 
+0x8f, 0x78, 0x3f, 0x07, 0x3f, 0x0f, 0x05, 0x2f, 0x03, 0xd1, 0xda, 0x1d, 
+0x0d, 0x32, 0xc2, 0x60, 0x05, 0xe0, 0xbf, 0x00, 0xdb, 0x19, 0xc3, 0x60, 
+0x08, 0x23, 0x1a, 0x43, 0x42, 0x60, 0x8a, 0x78, 0x12, 0x07, 0x12, 0x0f, 
+0x92, 0x00, 0x02, 0x61, 0x0a, 0x79, 0x4b, 0x79, 0x1b, 0x02, 0x1a, 0x43, 
+0x13, 0x02, 0x12, 0x0a, 0x12, 0x06, 0x12, 0x0e, 0x1a, 0x43, 0x12, 0x04, 
+0x12, 0x0c, 0x42, 0x61, 0xca, 0x7a, 0x06, 0x2a, 0x03, 0xd1, 0x10, 0x23, 
+0x42, 0x68, 0x1a, 0x43, 0x10, 0xe0, 0x11, 0x2a, 0x03, 0xd1, 0x20, 0x23, 
+0x42, 0x68, 0x1a, 0x43, 0x0a, 0xe0, 0x33, 0x2a, 0x03, 0xd1, 0x40, 0x23, 
+0x42, 0x68, 0x1a, 0x43, 0x04, 0xe0, 0x32, 0x2a, 0x03, 0xd1, 0x80, 0x23, 
+0x42, 0x68, 0x1a, 0x43, 0x42, 0x60, 0xc9, 0x7a, 0xc0, 0x46, 0x01, 0x76, 
+0x80, 0xbc, 0x70, 0x47, 0x0a, 0x78, 0xc0, 0x46, 0x02, 0x60, 0x4b, 0x78, 
+0x1b, 0x02, 0x1a, 0x43, 0x02, 0x60, 0x8b, 0x78, 0x1b, 0x04, 0x1a, 0x43, 
+0x02, 0x60, 0xc9, 0x78, 0x09, 0x06, 0x11, 0x43, 0x01, 0x60, 0x70, 0x47, 
+0x80, 0xb5, 0x07, 0x1c, 0x48, 0x68, 0x80, 0x09, 0x26, 0xd3, 0xb8, 0x6a, 
+0xc9, 0x68, 0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x02, 0x30, 0x18, 0x43, 
+0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x11, 0x23, 0x9b, 0x02, 0x98, 0x42, 
+0x18, 0xd1, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 
+0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xd0, 0xf8, 0x38, 0x1c, 0x01, 0xf0, 
+0x8b, 0xfd, 0x01, 0x20, 0x07, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x07, 0x49, 
+0x4a, 0x6c, 0x12, 0x18, 0x4a, 0x64, 0x06, 0x49, 0x8a, 0x6d, 0x12, 0x18, 
+0x8a, 0x65, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0xfa, 0xe7, 
+0x18, 0x1a, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80, 
+0x81, 0x07, 0x19, 0xd0, 0x80, 0x08, 0x80, 0x00, 0x01, 0x23, 0x9b, 0x07, 
+0x01, 0x1d, 0x18, 0x43, 0x00, 0x68, 0x19, 0x43, 0x09, 0x68, 0x02, 0x02, 
+0x12, 0x0e, 0x12, 0x06, 0x00, 0x0a, 0xff, 0x23, 0x1b, 0x04, 0x18, 0x40, 
+0x10, 0x43, 0x0a, 0x0a, 0x12, 0x06, 0x12, 0x0e, 0x10, 0x43, 0x09, 0x02, 
+0x1b, 0x0a, 0x19, 0x40, 0x08, 0x43, 0x70, 0x47, 0x01, 0x23, 0x9b, 0x07, 
+0x18, 0x43, 0x00, 0x68, 0x01, 0x06, 0x02, 0x02, 0xff, 0x23, 0x1b, 0x04, 
+0x1a, 0x40, 0x11, 0x43, 0x02, 0x0a, 0x1b, 0x0a, 0x1a, 0x40, 0x11, 0x43, 
+0x00, 0x0e, 0x08, 0x43, 0xed, 0xe7, 0x00, 0x00, 0xf0, 0xb5, 0x04, 0x23, 
+0x81, 0x6b, 0x19, 0x40, 0x00, 0x22, 0x00, 0x29, 0x46, 0xd0, 0xc7, 0x1d, 
+0x39, 0x37, 0x39, 0x7b, 0x33, 0x29, 0x01, 0xd0, 0x32, 0x29, 0x3f, 0xd1, 
+0x01, 0x6b, 0xc0, 0x46, 0x4a, 0x65, 0xc4, 0x1d, 0x2d, 0x34, 0xcd, 0x1d, 
+0x2d, 0x35, 0x00, 0x22, 0x93, 0x00, 0xe6, 0x58, 0xc0, 0x46, 0xee, 0x50, 
+0x01, 0x32, 0x07, 0x2a, 0xf8, 0xd3, 0x82, 0x6a, 0xc0, 0x46, 0x4a, 0x63, 
+0x82, 0x6a, 0xc0, 0x46, 0x8a, 0x62, 0x7a, 0x8b, 0xcb, 0x1d, 0x39, 0x33, 
+0x5a, 0x83, 0x40, 0x6a, 0xc0, 0x46, 0x48, 0x62, 0x12, 0x48, 0x01, 0x27, 
+0x42, 0x68, 0x00, 0x2a, 0x10, 0xd1, 0xc2, 0x68, 0x00, 0x2a, 0x13, 0xd1, 
+0x42, 0x69, 0x00, 0x2a, 0x0d, 0xd1, 0x01, 0x61, 0xc1, 0x60, 0x01, 0x6a, 
+0x02, 0x29, 0x02, 0xd3, 0x20, 0x30, 0x07, 0x71, 0x0c, 0xe0, 0x00, 0xf0, 
+0x13, 0xf8, 0x09, 0xe0, 0xc2, 0x68, 0x00, 0x2a, 0x02, 0xd1, 0x01, 0x61, 
+0xc1, 0x60, 0x03, 0xe0, 0x02, 0x69, 0xc0, 0x46, 0x51, 0x65, 0x01, 0x61, 
+0x38, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x10, 0x1c, 0xfa, 0xe7, 
+0x6c, 0x06, 0x00, 0x80, 0x80, 0xb5, 0x1e, 0x49, 0x00, 0x22, 0xcb, 0x68, 
+0x00, 0x2b, 0x34, 0xd0, 0xc8, 0x1d, 0xf9, 0x30, 0x83, 0x62, 0xcb, 0x68, 
+0x9b, 0x6a, 0xc0, 0x46, 0xc3, 0x62, 0xcf, 0x69, 0x7b, 0x00, 0xdf, 0x19, 
+0x7f, 0x02, 0x17, 0x4b, 0xff, 0x18, 0xff, 0x37, 0x65, 0x37, 0x83, 0x63, 
+0x07, 0x63, 0xcb, 0x1d, 0xff, 0x33, 0x5a, 0x33, 0x1a, 0x72, 0xcb, 0x69, 
+0x00, 0x2b, 0x01, 0xd0, 0xca, 0x61, 0x01, 0xe0, 0x01, 0x23, 0xcb, 0x61, 
+0x0f, 0x1c, 0xc9, 0x68, 0x49, 0x6a, 0x09, 0x89, 0x01, 0x31, 0x41, 0x63, 
+0xf8, 0x1d, 0xff, 0x30, 0x3a, 0x30, 0x42, 0x60, 0x02, 0x82, 0x82, 0x60, 
+0xc2, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xce, 0xfa, 0x38, 0x6a, 0x01, 0x30, 
+0x38, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x0a, 0xf8, 0x80, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x10, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 
+0x1c, 0xad, 0x20, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 0xf9, 0x1d, 0xf9, 0x31, 
+0x88, 0x6a, 0xc2, 0x1d, 0x2d, 0x32, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x32, 
+0x1a, 0x43, 0xc8, 0x6a, 0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x80, 0x18, 
+0x82, 0x79, 0xc3, 0x79, 0x1b, 0x02, 0x1a, 0x43, 0x13, 0x02, 0x12, 0x0a, 
+0x12, 0x06, 0x12, 0x0e, 0x1a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x02, 0x38, 
+0x92, 0x04, 0x92, 0x0c, 0x00, 0x26, 0x25, 0x4d, 
+0xec, 0x1d, 0xff, 0x34, 0x3a, 0x34, 0x00, 0x2a, 0x04, 0xd0, 0x20, 0x8a, 
+0x01, 0x23, 0x9b, 0x02, 0x18, 0x43, 0x2b, 0xe0, 0x01, 0x23, 0x9b, 0x07, 
+0xc2, 0x1d, 0x0d, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 0x12, 0x30, 
+0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x10, 0x43, 0x03, 0x1c, 
+0xf8, 0x1d, 0xff, 0x30, 0x4a, 0x30, 0x82, 0x78, 0xc8, 0x6b, 0x19, 0x1c, 
+0x01, 0xf0, 0xf8, 0xff, 0x00, 0x28, 0x04, 0xda, 0x20, 0x8a, 0xff, 0x23, 
+0x01, 0x33, 0x18, 0x43, 0x0e, 0xe0, 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 
+0x08, 0x60, 0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 0x00, 0xf0, 0x1c, 0xf8, 
+0x00, 0x28, 0x14, 0xd1, 0x20, 0x8a, 0x01, 0x23, 0x5b, 0x02, 0x18, 0x43, 
+0x20, 0x82, 0x21, 0x8a, 0x38, 0x1c, 0x00, 0xf0, 0xa2, 0xfb, 0xe8, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x54, 0x30, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 
+0xe8, 0x60, 0x30, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 
+0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0xf8, 0xb5, 0x07, 0x1c, 
+0xfc, 0x1d, 0xf9, 0x34, 0xa0, 0x6b, 0xa6, 0x6a, 0xc5, 0x1d, 0x0d, 0x35, 
+0x38, 0x48, 0xc0, 0x6a, 0x4b, 0x00, 0x59, 0x18, 0x49, 0x01, 0x42, 0x18, 
+0x01, 0x20, 0x80, 0x07, 0x10, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 
+0x00, 0x90, 0x01, 0x23, 0x9b, 0x07, 0xd0, 0x1d, 0x05, 0x30, 0x18, 0x43, 
+0x00, 0x68, 0x38, 0x1c, 0x29, 0x1c, 0x00, 0xf0, 0xc2, 0xfa, 0xa8, 0x88, 
+0x41, 0x07, 0x01, 0xd0, 0x00, 0x20, 0x51, 0xe0, 0x29, 0x89, 0x09, 0x18, 
+0x60, 0x6b, 0x81, 0x42, 0xf8, 0xd8, 0x69, 0x89, 0xea, 0x88, 0x89, 0x18, 
+0x81, 0x42, 0xf3, 0xd8, 0x00, 0x98, 0x01, 0x28, 0x25, 0xd1, 0xe0, 0x6a, 
 0xf1, 0x6b, 0x40, 0x18, 0x71, 0x6c, 0xfa, 0x1d, 0xcd, 0x32, 0x01, 0xf0, 
-0x2b, 0xf9, 0xfa, 0x1d, 0xff, 0x32, 0x3a, 0x32, 0xe0, 0x6a, 0x51, 0x69, 
+0x29, 0xf9, 0xfa, 0x1d, 0xff, 0x32, 0x3a, 0x32, 0xe0, 0x6a, 0x51, 0x69, 
 0x40, 0x18, 0xc3, 0x1d, 0x03, 0x33, 0x00, 0x20, 0x81, 0x00, 0x5e, 0x58, 
 0xc9, 0x19, 0xff, 0x31, 0x01, 0x31, 0x4e, 0x61, 0x01, 0x30, 0x04, 0x28, 
 0xf6, 0xd3, 0xe0, 0x6a, 0x51, 0x69, 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 
 0x00, 0x20, 0x00, 0x22, 0x43, 0x00, 0xca, 0x52, 0x01, 0x30, 0x06, 0x28, 
-0xfa, 0xd3, 0x29, 0x1c, 0x11, 0x4a, 0x00, 0x20, 0xff, 0xf7, 0xd4, 0xfb, 
+0xfa, 0xd3, 0x29, 0x1c, 0x11, 0x4a, 0x00, 0x20, 0xff, 0xf7, 0xae, 0xfb, 
 0x01, 0x22, 0x52, 0x04, 0x60, 0x6b, 0x02, 0x43, 0x01, 0x20, 0x21, 0x6b, 
-0xff, 0xf7, 0xcc, 0xfb, 0x01, 0x22, 0x52, 0x04, 0x60, 0x6b, 0x02, 0x43, 
-0x00, 0x20, 0xe1, 0x6a, 0xff, 0xf7, 0xc4, 0xfb, 0xa1, 0x6b, 0x08, 0x4a, 
-0x01, 0x20, 0xff, 0xf7, 0xbf, 0xfb, 0x03, 0x20, 0x06, 0x49, 0xc0, 0x46, 
+0xff, 0xf7, 0xa6, 0xfb, 0x01, 0x22, 0x52, 0x04, 0x60, 0x6b, 0x02, 0x43, 
+0x00, 0x20, 0xe1, 0x6a, 0xff, 0xf7, 0x9e, 0xfb, 0xa1, 0x6b, 0x08, 0x4a, 
+0x01, 0x20, 0xff, 0xf7, 0x99, 0xfb, 0x03, 0x20, 0x06, 0x49, 0xc0, 0x46, 
 0x48, 0x62, 0x01, 0x20, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xc8, 0x29, 0x00, 0x80, 0x54, 0x00, 0x03, 0x00, 0x14, 0x00, 0x0f, 0x00, 
-0xec, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x8d, 0xb0, 0x00, 0x20, 0xb5, 0x4a, 
+0x4c, 0x2a, 0x00, 0x80, 0x54, 0x00, 0x03, 0x00, 0x14, 0x00, 0x0f, 0x00, 
+0x6c, 0x07, 0x00, 0x80, 0xf0, 0xb5, 0x8d, 0xb0, 0x00, 0x20, 0xb5, 0x4a, 
 0xd5, 0x1d, 0xf9, 0x35, 0x68, 0x62, 0x01, 0x20, 0x00, 0x05, 0xb3, 0x49, 
 0xc0, 0x46, 0x08, 0x60, 0xa8, 0x6a, 0xc4, 0x1d, 0x2d, 0x34, 0xb1, 0x48, 
 0xc0, 0x6a, 0xd7, 0x1d, 0xff, 0x37, 0x3a, 0x37, 0x39, 0x68, 0x4b, 0x00, 
@@ -409,18 +418,18 @@ const u8 typhoon_firmware_image[] = {
 0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0x08, 0x30, 0x18, 0x43, 0x00, 0x68, 
 0xc0, 0x46, 0x09, 0x90, 0xff, 0x23, 0x1b, 0x02, 0x18, 0x40, 0x00, 0x0a, 
 0x0a, 0x90, 0x0a, 0x98, 0xa4, 0x4e, 0x01, 0x28, 0x59, 0xd1, 0x28, 0x6b, 
-0xa2, 0x68, 0x80, 0x18, 0xa2, 0x4a, 0x21, 0x69, 0x09, 0x04, 0x09, 0x0c, 
-0x01, 0xf0, 0x1e, 0xf9, 0x28, 0x6b, 0x79, 0x69, 0x40, 0x18, 0xc1, 0x1d, 
-0x05, 0x31, 0x00, 0x20, 0x82, 0x00, 0x98, 0x4b, 0xd3, 0x18, 0xff, 0x33, 
-0x01, 0x33, 0x5b, 0x69, 0xc0, 0x46, 0x8b, 0x50, 0x01, 0x30, 0x04, 0x28, 
-0xf4, 0xd3, 0x00, 0x20, 0x31, 0x1c, 0x82, 0x00, 0x56, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x04, 0xae, 0xb3, 0x50, 0x01, 0x30, 
-0x03, 0x28, 0xf4, 0xd3, 0x00, 0x20, 0x08, 0x90, 0x90, 0x49, 0x42, 0x00, 
-0x8b, 0x5a, 0xb2, 0x5a, 0x93, 0x42, 0x13, 0xd0, 0x8e, 0x48, 0xc1, 0x89, 
-0x01, 0x31, 0xc1, 0x81, 0xb8, 0x68, 0x00, 0x28, 
+0xa2, 0x68, 0x80, 0x18, 0xa2, 0x4a, 0x21, 0x69, 
+0x09, 0x04, 0x09, 0x0c, 0x01, 0xf0, 0x1c, 0xf9, 0x28, 0x6b, 0x79, 0x69, 
+0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20, 0x82, 0x00, 0x98, 0x4b, 
+0xd3, 0x18, 0xff, 0x33, 0x01, 0x33, 0x5b, 0x69, 0xc0, 0x46, 0x8b, 0x50, 
+0x01, 0x30, 0x04, 0x28, 0xf4, 0xd3, 0x00, 0x20, 0x31, 0x1c, 0x82, 0x00, 
+0x56, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x04, 0xae, 
+0xb3, 0x50, 0x01, 0x30, 0x03, 0x28, 0xf4, 0xd3, 0x00, 0x20, 0x08, 0x90, 
+0x90, 0x49, 0x42, 0x00, 0x8b, 0x5a, 0xb2, 0x5a, 0x93, 0x42, 0x13, 0xd0, 
+0x8e, 0x48, 0xc1, 0x89, 0x01, 0x31, 0xc1, 0x81, 0xb8, 0x68, 0x00, 0x28, 
 0x03, 0xd1, 0x38, 0x8a, 0x10, 0x23, 0x18, 0x43, 0x71, 0xe0, 0x38, 0x8a, 
 0x40, 0x23, 0x18, 0x43, 0x6d, 0xe0, 0x00, 0xf0, 0x11, 0xf9, 0x01, 0xf0, 
-0x47, 0xff, 0xf5, 0xe0, 0x01, 0x30, 0x06, 0x28, 0xe3, 0xd3, 0x08, 0x98, 
+0x5d, 0xff, 0xf5, 0xe0, 0x01, 0x30, 0x06, 0x28, 0xe3, 0xd3, 0x08, 0x98, 
 0x00, 0x28, 0x0c, 0xd1, 0xb8, 0x68, 0x41, 0x1c, 0xb9, 0x60, 0x00, 0x28, 
 0x03, 0xd1, 0x38, 0x8a, 0x01, 0x23, 0x18, 0x43, 0x02, 0xe0, 0x38, 0x8a, 
 0x04, 0x23, 0x18, 0x43, 0x38, 0x82, 0x78, 0x68, 0x01, 0x30, 0x78, 0x60, 
@@ -452,20 +461,20 @@ const u8 typhoon_firmware_image[] = {
 0x01, 0x23, 0x9b, 0x07, 0xe0, 0x1d, 0x01, 0x30, 0x18, 0x43, 0x00, 0x68, 
 0xe1, 0x1d, 0x0d, 0x31, 0x19, 0x43, 0x09, 0x68, 0x40, 0x18, 0x00, 0x04, 
 0x00, 0x0c, 0xf9, 0x68, 0x4a, 0x1c, 0xfa, 0x60, 0x00, 0x29, 0xbc, 0xd1, 
-0xb6, 0xe7, 0x01, 0x23, 0x9b, 0x07, 0xe1, 0x1d, 0x05, 0x31, 0x19, 0x43, 
-0x09, 0x68, 0x09, 0x06, 0x09, 0x0e, 0xa1, 0x60, 0xe8, 0x6a, 0xc0, 0x46, 
-0x20, 0x60, 0x20, 0x1c, 0xff, 0xf7, 0x92, 0xfc, 0x20, 0x7e, 0x33, 0x28, 
-0x01, 0xd0, 0x32, 0x28, 0x11, 0xd1, 0x01, 0x21, 0x14, 0x4c, 0xc0, 0x46, 
-0xf9, 0x60, 0xb9, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x85, 0xf8, 0x28, 0x6b, 
-0xa9, 0x6a, 0xc0, 0x46, 0x88, 0x62, 0x20, 0x1c, 0xff, 0xf7, 0xca, 0xfd, 
-0x00, 0x28, 0x11, 0xd1, 0x0e, 0xe0, 0x00, 0x20, 0x30, 0x72, 0x11, 0xe0, 
-0x33, 0x29, 0x01, 0xd0, 0x32, 0x29, 0x0d, 0xd1, 0x07, 0x1c, 0x00, 0xf0, 
-0x71, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0xba, 0xfd, 
-0x00, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x50, 0xfe, 0x0d, 0xb0, 0xf0, 0xbc, 
+0xb6, 0xe7, 0x01, 0x23, 0x9b, 0x07, 0xe1, 0x1d, 
+0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0x09, 0x06, 0x09, 0x0e, 0xa1, 0x60, 
+0xe8, 0x6a, 0xc0, 0x46, 0x20, 0x60, 0x20, 0x1c, 0xff, 0xf7, 0x88, 0xfc, 
+0x20, 0x7e, 0x33, 0x28, 0x01, 0xd0, 0x32, 0x28, 0x11, 0xd1, 0x01, 0x21, 
+0x14, 0x4c, 0xc0, 0x46, 0xf9, 0x60, 0xb9, 0x60, 0x20, 0x1c, 0x00, 0xf0, 
+0x85, 0xf8, 0x28, 0x6b, 0xa9, 0x6a, 0xc0, 0x46, 0x88, 0x62, 0x20, 0x1c, 
+0xff, 0xf7, 0xc0, 0xfd, 0x00, 0x28, 0x11, 0xd1, 0x0e, 0xe0, 0x00, 0x20, 
+0x30, 0x72, 0x11, 0xe0, 0x33, 0x29, 0x01, 0xd0, 0x32, 0x29, 0x0d, 0xd1, 
+0x07, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0xb0, 0xfd, 
+0x00, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x66, 0xfe, 0x0d, 0xb0, 0xf0, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x00, 0xf0, 0x12, 0xf8, 0xf6, 0xe7, 0x00, 0x00, 
-0xec, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xc8, 0x29, 0x00, 0x80, 
-0x1c, 0xad, 0x20, 0x40, 0xc0, 0x06, 0x00, 0x80, 0x02, 0x07, 0x00, 0x80, 
-0x78, 0x2a, 0x00, 0x80, 0xec, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x25, 0x48, 
+0x6c, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x4c, 0x2a, 0x00, 0x80, 
+0x1c, 0xad, 0x20, 0x40, 0x40, 0x07, 0x00, 0x80, 0x82, 0x07, 0x00, 0x80, 
+0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x07, 0x00, 0x80, 0xf0, 0xb5, 0x25, 0x48, 
 0x41, 0x68, 0x01, 0x31, 0x41, 0x60, 0x24, 0x4f, 0xf9, 0x1d, 0xf9, 0x31, 
 0x00, 0x24, 0x88, 0x6a, 0xfa, 0x68, 0xc0, 0x46, 0x94, 0x61, 0x04, 0x22, 
 0xfb, 0x68, 0xc0, 0x46, 0xda, 0x60, 0x10, 0x22, 0xfb, 0x68, 0xc0, 0x46, 
@@ -476,10 +485,10 @@ const u8 typhoon_firmware_image[] = {
 0x4a, 0x6b, 0xfb, 0x68, 0xc0, 0x46, 0xda, 0x81, 0x0a, 0x6b, 0xc0, 0x46, 
 0x82, 0x62, 0xc4, 0x62, 0xc3, 0x1d, 0x39, 0x33, 0x4a, 0x6b, 0xc0, 0x46, 
 0x5a, 0x83, 0x04, 0x23, 0x02, 0x68, 0x1a, 0x43, 0x02, 0x60, 0x88, 0x6a, 
-0x01, 0xf0, 0x14, 0xfa, 0xf8, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x54, 0x30, 
+0x01, 0xf0, 0x28, 0xfa, 0xf8, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x54, 0x30, 
 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x80, 0xec, 0x05, 0x00, 0x80, 
-0x2c, 0x07, 0x00, 0x80, 0x80, 0xb5, 0xc1, 0x1d, 0xf9, 0x31, 0x8a, 0x6a, 
+0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0xac, 0x07, 0x00, 0x80, 0x80, 0xb5, 0xc1, 0x1d, 0xf9, 0x31, 0x8a, 0x6a, 
 0x01, 0x23, 0x9b, 0x07, 0xd1, 0x1d, 0x45, 0x31, 0x19, 0x43, 0x09, 0x68, 
 0x0b, 0x06, 0x1b, 0x0e, 0x01, 0x27, 0xc1, 0x1d, 0xff, 0x31, 0x4a, 0x31, 
 0x33, 0x2b, 0x05, 0xd1, 0x8b, 0x70, 0x01, 0x1c, 0x10, 0x1c, 0x00, 0xf0, 
@@ -495,15 +504,15 @@ const u8 typhoon_firmware_image[] = {
 0xf8, 0x1d, 0x01, 0x30, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0xb9, 0x1d, 
 0x19, 0x43, 0xd0, 0x63, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x08, 0x43, 
 0xd0, 0x63, 0x90, 0xbc, 0x70, 0x47, 0xb0, 0xb5, 0xca, 0x1d, 0xf9, 0x32, 
-0xc5, 0x1d, 0x2d, 0x35, 0x32, 0x20, 0xcf, 0x1d, 0xff, 0x37, 0x4a, 0x37, 
-0xd3, 0x6a, 0xc0, 0x46, 0xb8, 0x70, 0xcc, 0x1d, 0xff, 0x34, 0x3a, 0x34, 
-0xe8, 0x68, 0xc0, 0x46, 0x60, 0x61, 0x10, 0x30, 0xe8, 0x60, 0x60, 0x69, 
-0xc0, 0x18, 0x87, 0x1e, 0x01, 0x23, 0x9b, 0x07, 0x38, 0x1d, 0x18, 0x43, 
-0x00, 0x68, 0x00, 0x04, 0xb9, 0x1c, 0x19, 0x43, 0xd0, 0x63, 0x09, 0x68, 
-0x09, 0x04, 0x09, 0x0c, 0x08, 0x43, 0xd0, 0x63, 0xf8, 0x1d, 0x03, 0x30, 
-0xff, 0xf7, 0x06, 0xfc, 0x20, 0x62, 0xf8, 0x1d, 0x07, 0x30, 0xff, 0xf7, 
-0x01, 0xfc, 0x60, 0x62, 0x00, 0x20, 0x28, 0x76, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0xf7, 0xb5, 0x81, 0xb0, 0x01, 0x98, 
+0xc5, 0x1d, 0x2d, 0x35, 0x32, 0x20, 0xcf, 0x1d, 
+0xff, 0x37, 0x4a, 0x37, 0xd3, 0x6a, 0xc0, 0x46, 0xb8, 0x70, 0xcc, 0x1d, 
+0xff, 0x34, 0x3a, 0x34, 0xe8, 0x68, 0xc0, 0x46, 0x60, 0x61, 0x10, 0x30, 
+0xe8, 0x60, 0x60, 0x69, 0xc0, 0x18, 0x87, 0x1e, 0x01, 0x23, 0x9b, 0x07, 
+0x38, 0x1d, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0xb9, 0x1c, 0x19, 0x43, 
+0xd0, 0x63, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x08, 0x43, 0xd0, 0x63, 
+0xf8, 0x1d, 0x03, 0x30, 0xff, 0xf7, 0xfc, 0xfb, 0x20, 0x62, 0xf8, 0x1d, 
+0x07, 0x30, 0xff, 0xf7, 0xf7, 0xfb, 0x60, 0x62, 0x00, 0x20, 0x28, 0x76, 
+0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf7, 0xb5, 0x81, 0xb0, 0x01, 0x98, 
 0xc7, 0x1d, 0xf9, 0x37, 0xb8, 0x6a, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
 0x05, 0x34, 0x23, 0x43, 0x1c, 0x68, 0xff, 0x23, 0xfe, 0x33, 0x23, 0x40, 
 0x7f, 0x6b, 0x3f, 0x04, 0x3b, 0x43, 0x0b, 0x60, 0x34, 0x30, 0x1c, 0x1c, 
@@ -537,86 +546,85 @@ const u8 typhoon_firmware_image[] = {
 0x04, 0x23, 0x90, 0x6a, 0xc0, 0x46, 0xc3, 0x60, 0x10, 0x23, 0x83, 0x61, 
 0xcb, 0x0a, 0x01, 0xd3, 0x18, 0x23, 0x83, 0x61, 0xc1, 0x83, 0x51, 0x6b, 
 0xc0, 0x46, 0xc1, 0x81, 0x51, 0x6b, 0xc2, 0x1d, 0x39, 0x32, 0x51, 0x83, 
-0x04, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x01, 0xf0, 0xa4, 0xf8, 
-0x08, 0xbc, 0x18, 0x47, 0x78, 0x2a, 0x00, 0x80, 0xb0, 0xb5, 0x1b, 0x4c, 
-0x20, 0x6a, 0x02, 0x28, 0x1b, 0xd2, 0x00, 0x20, 0xe7, 0x1d, 0x19, 0x37, 
-0x38, 0x71, 0xe1, 0x68, 0xe0, 0x1d, 0xf9, 0x30, 0x00, 0x29, 0x15, 0xd0, 
-0x42, 0x6a, 0x00, 0x2a, 0x12, 0xd1, 0x01, 0x25, 0x0a, 0xe0, 0xff, 0xf7, 
-0x93, 0xfb, 0x00, 0x28, 0x09, 0xd1, 0x20, 0x6a, 0x02, 0x28, 0x00, 0xd3, 
-0x3d, 0x71, 0xe0, 0x68, 0x00, 0x28, 0x02, 0xd0, 0x38, 0x79, 0x00, 0x28, 
-0xf1, 0xd0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0x6a, 0x00, 0x28, 
-0xf9, 0xd1, 0x00, 0x29, 0xf7, 0xd1, 0x60, 0x69, 0x00, 0x28, 0x04, 0xd0, 
-0x06, 0x48, 0x00, 0x68, 0x03, 0xf0, 0x8e, 0xfc, 
+0x04, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x01, 0xf0, 0xb8, 0xf8, 
+0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 
+0xb0, 0xb5, 0x1b, 0x4c, 0x20, 0x6a, 0x02, 0x28, 0x1b, 0xd2, 0x00, 0x20, 
+0xe7, 0x1d, 0x19, 0x37, 0x38, 0x71, 0xe1, 0x68, 0xe0, 0x1d, 0xf9, 0x30, 
+0x00, 0x29, 0x15, 0xd0, 0x42, 0x6a, 0x00, 0x2a, 0x12, 0xd1, 0x01, 0x25, 
+0x0a, 0xe0, 0xff, 0xf7, 0x89, 0xfb, 0x00, 0x28, 0x09, 0xd1, 0x20, 0x6a, 
+0x02, 0x28, 0x00, 0xd3, 0x3d, 0x71, 0xe0, 0x68, 0x00, 0x28, 0x02, 0xd0, 
+0x38, 0x79, 0x00, 0x28, 0xf1, 0xd0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x40, 0x6a, 0x00, 0x28, 0xf9, 0xd1, 0x00, 0x29, 0xf7, 0xd1, 0x60, 0x69, 
+0x00, 0x28, 0x04, 0xd0, 0x06, 0x48, 0x00, 0x68, 0x03, 0xf0, 0x9e, 0xfc, 
 0xef, 0xe7, 0x60, 0x68, 0x00, 0x28, 0xec, 0xd0, 0x00, 0xf0, 0x50, 0xf8, 
-0xe9, 0xe7, 0x00, 0x00, 0xec, 0x05, 0x00, 0x80, 0xb4, 0x03, 0x00, 0x80, 
+0xe9, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x34, 0x04, 0x00, 0x80, 
 0xb0, 0xb5, 0x07, 0x1c, 0x20, 0x23, 0xb8, 0x68, 0x18, 0x40, 0x00, 0x25, 
 0x00, 0x28, 0x03, 0xd1, 0x28, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0xc4, 0x23, 0x48, 0x68, 0x18, 0x40, 0x01, 0x24, 0x00, 0x28, 0x03, 0xd1, 
-0x38, 0x6a, 0x00, 0xf0, 0x0d, 0xfc, 0x2f, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 
-0x1d, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x7e, 0xfa, 0xb8, 0x68, 0xc0, 0x08, 
-0x02, 0xd3, 0x38, 0x6a, 0x00, 0xf0, 0xd2, 0xfb, 0xb8, 0x68, 0x39, 0x6a, 
+0x38, 0x6a, 0x00, 0xf0, 0x09, 0xfc, 0x2f, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 
+0x19, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x78, 0xfa, 0xb8, 0x68, 0xc0, 0x08, 
+0x02, 0xd3, 0x38, 0x6a, 0x00, 0xf0, 0xce, 0xfb, 0xb8, 0x68, 0x39, 0x6a, 
 0xc0, 0x46, 0x88, 0x60, 0x38, 0x6a, 0xc0, 0x46, 0xc5, 0x60, 0x0f, 0x48, 
 0x41, 0x68, 0x00, 0x29, 0x11, 0xd1, 0xc1, 0x68, 0x00, 0x29, 0x09, 0xd1, 
 0x41, 0x69, 0x00, 0x29, 0x06, 0xd1, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 
 0x41, 0x60, 0x00, 0xf0, 0x11, 0xf8, 0x0b, 0xe0, 0x39, 0x6a, 0xc0, 0x46, 
 0x81, 0x60, 0x41, 0x60, 0x06, 0xe0, 0x39, 0x6a, 0x82, 0x68, 0xc0, 0x46, 
 0xd1, 0x60, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 0x20, 0x1c, 0xc0, 0xe7, 
-0xec, 0x05, 0x00, 0x80, 0x90, 0xb5, 0x0b, 0x4c, 0x67, 0x68, 0x00, 0x2f, 
+0x6c, 0x06, 0x00, 0x80, 0x90, 0xb5, 0x0b, 0x4c, 0x67, 0x68, 0x00, 0x2f, 
 0x0f, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x28, 0x0a, 0xd1, 
 0x60, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x60, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
-0xc7, 0xfb, 0x00, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 
-0xfa, 0xe7, 0x00, 0x00, 0xec, 0x05, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 
+0xc3, 0xfb, 0x00, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 
+0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 
 0xfe, 0x1d, 0x49, 0x36, 0x30, 0x78, 0x40, 0x00, 0xc0, 0x19, 0x85, 0x8b, 
-0x2d, 0x4b, 0x9d, 0x42, 0x56, 0xd0, 0x2d, 0x4c, 0x38, 0x1c, 0x21, 0x1c, 
-0x2a, 0x1c, 0x00, 0xf0, 0x23, 0xf9, 0xa0, 0x88, 0x40, 0x07, 0x4d, 0xd1, 
-0x29, 0x48, 0x80, 0x6a, 0x58, 0x21, 0x69, 0x43, 0x40, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x25, 0x4d, 
-0x01, 0x28, 0x1a, 0xd1, 0x30, 0x78, 0xc0, 0x19, 0xc1, 0x1d, 0x19, 0x31, 
-0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x09, 0x7b, 0xea, 0x1d, 0x21, 0x32, 
-0x00, 0xf0, 0xe2, 0xfc, 0x30, 0x78, 0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 
-0x39, 0x68, 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20, 0x00, 0x22, 
-0x43, 0x00, 0xca, 0x52, 0x01, 0x30, 0x06, 0x28, 0xfa, 0xd3, 0x21, 0x1c, 
-0x16, 0x4a, 0x00, 0x20, 0xfe, 0xf7, 0x9a, 0xff, 0x01, 0x22, 0x52, 0x04, 
-0x78, 0x68, 0x02, 0x43, 0x01, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x92, 0xff, 
-0x01, 0x22, 0x52, 0x04, 0x78, 0x68, 0x02, 0x43, 0x00, 0x20, 0x39, 0x68, 
-0xfe, 0xf7, 0x8a, 0xff, 0x0d, 0x49, 0x0e, 0x4a, 0x01, 0x20, 0xfe, 0xf7, 
-0x85, 0xff, 0x01, 0x20, 0xe9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x02, 0x21, 
-0xea, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x20, 0xfa, 0xe7, 0xff, 0xff, 0x00, 0x00, 0x98, 0xad, 0x20, 0x40, 
-0xc8, 0x29, 0x00, 0x80, 0xec, 0x05, 0x00, 0x80, 0x54, 0x00, 0x03, 0x00, 
-0x84, 0xad, 0x20, 0x40, 0x14, 0x00, 0x07, 0x00, 0xf0, 0xb5, 0x83, 0xb0, 
-0x00, 0x21, 0x58, 0x48, 0xc2, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0x01, 0x21, 
-0xc9, 0x04, 0x56, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0xc1, 0x1d, 0x19, 0x31, 
-0x49, 0x79, 0x00, 0x29, 0x04, 0xd1, 0x53, 0x48, 0x00, 0x68, 0x03, 0xf0, 
-0x97, 0xfb, 0x98, 0xe0, 0x4e, 0x48, 0x47, 0x68, 0xfc, 0x1d, 0x49, 0x34, 
-0x22, 0x78, 0x50, 0x00, 0xc0, 0x19, 0x80, 0x8b, 
-0x4d, 0x49, 0x89, 0x6a, 0x58, 0x23, 0x58, 0x43, 0x0d, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0xe9, 0x1d, 0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0x08, 0x35, 
+0x33, 0x4c, 0x34, 0x4b, 0x9d, 0x42, 0x3c, 0xd0, 0x38, 0x1c, 0x21, 0x1c, 
+0x2a, 0x1c, 0x00, 0xf0, 0x1d, 0xf9, 0x31, 0x48, 0x80, 0x6a, 0x58, 0x21, 
+0x69, 0x43, 0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x18, 0x43, 0x00, 0x68, 
+0x00, 0x04, 0x00, 0x0c, 0x2c, 0x4d, 0x01, 0x28, 0x1a, 0xd1, 0x30, 0x78, 
+0xc0, 0x19, 0xc1, 0x1d, 0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 
+0x09, 0x7b, 0xea, 0x1d, 0x21, 0x32, 0x00, 0xf0, 0xe3, 0xfc, 0x30, 0x78, 
+0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 0x40, 0x18, 0xc1, 0x1d, 
+0x05, 0x31, 0x00, 0x20, 0x00, 0x23, 0x42, 0x00, 0x8b, 0x52, 0x01, 0x30, 
+0x06, 0x28, 0xfa, 0xd3, 0xa0, 0x88, 0x41, 0x07, 0x0b, 0xd1, 0x21, 0x89, 
+0x09, 0x18, 0x78, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x81, 0x42, 0x04, 0xd8, 
+0x61, 0x89, 0xe2, 0x88, 0x89, 0x18, 0x81, 0x42, 0x03, 0xd9, 0x00, 0x20, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x21, 0x1c, 0x14, 0x4a, 0x00, 0x20, 
+0xfe, 0xf7, 0x64, 0xff, 0x01, 0x22, 0x52, 0x04, 0x78, 0x68, 0x02, 0x43, 
+0x01, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x5c, 0xff, 0x01, 0x22, 0x52, 0x04, 
+0x78, 0x68, 0x02, 0x43, 0x00, 0x20, 0x39, 0x68, 
+0xfe, 0xf7, 0x54, 0xff, 0x0b, 0x49, 0x0c, 0x4a, 0x01, 0x20, 0xfe, 0xf7, 
+0x4f, 0xff, 0x01, 0x20, 0xe9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x02, 0x21, 
+0xea, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0xd9, 0xe7, 0x98, 0xad, 0x20, 0x40, 
+0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0x54, 0x00, 0x03, 0x00, 0x84, 0xad, 0x20, 0x40, 0x14, 0x00, 0x07, 0x00, 
+0xf0, 0xb5, 0x83, 0xb0, 0x00, 0x21, 0x4f, 0x48, 0xc2, 0x1d, 0xf9, 0x32, 
+0x51, 0x62, 0x01, 0x21, 0xc9, 0x04, 0x4d, 0x4a, 0xc0, 0x46, 0x11, 0x60, 
+0xc1, 0x1d, 0x19, 0x31, 0x49, 0x79, 0x00, 0x29, 0x04, 0xd1, 0x4a, 0x48, 
+0x00, 0x68, 0x03, 0xf0, 0x9b, 0xfb, 0x87, 0xe0, 0x45, 0x48, 0x47, 0x68, 
+0xfc, 0x1d, 0x49, 0x34, 0x21, 0x78, 0x48, 0x00, 0xc0, 0x19, 0x80, 0x8b, 
+0x44, 0x4a, 0x92, 0x6a, 0x58, 0x23, 0x58, 0x43, 0x15, 0x18, 0x01, 0x23, 
+0x9b, 0x07, 0xea, 0x1d, 0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x08, 0x35, 
 0x2b, 0x43, 0x1d, 0x68, 0xff, 0x23, 0x1b, 0x02, 0x2b, 0x40, 0x1b, 0x0a, 
-0x45, 0x4d, 0x01, 0x2b, 0x24, 0xd1, 0xd0, 0x19, 0xc1, 0x1d, 0x19, 0x31, 
-0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x42, 0x4a, 0x09, 0x7b, 0x00, 0xf0, 
-0xd3, 0xfc, 0x20, 0x78, 0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 
+0x3c, 0x4d, 0x01, 0x2b, 0x24, 0xd1, 0xc8, 0x19, 0xc1, 0x1d, 0x19, 0x31, 
+0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x39, 0x4a, 0x09, 0x7b, 0x00, 0xf0, 
+0xc5, 0xfc, 0x20, 0x78, 0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 
 0x41, 0x18, 0x00, 0x20, 0x82, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46, 
 0xb3, 0x50, 0x01, 0x30, 0x03, 0x28, 0xf7, 0xd3, 0xca, 0x1d, 0x05, 0x32, 
 0x69, 0x46, 0x00, 0x20, 0x43, 0x00, 0xcd, 0x5a, 0xc0, 0x46, 0xd5, 0x52, 
-0x01, 0x30, 0x06, 0x28, 0xf8, 0xd3, 0x3e, 0xe0, 0x02, 0x2b, 0x3c, 0xd1, 
-0x09, 0x0a, 0x3a, 0xd3, 0x00, 0x21, 0x8a, 0x00, 0x53, 0x19, 0x9b, 0x6e, 
+0x01, 0x30, 0x06, 0x28, 0xf8, 0xd3, 0x2d, 0xe0, 0x02, 0x2b, 0x2b, 0xd1, 
+0x11, 0x0a, 0x29, 0xd3, 0x00, 0x21, 0x8a, 0x00, 0x53, 0x19, 0x9b, 0x6e, 
 0x6e, 0x46, 0xb3, 0x50, 0x01, 0x31, 0x03, 0x29, 0xf7, 0xd3, 0x21, 0x78, 
 0x49, 0x00, 0xc9, 0x19, 0x09, 0x8f, 0x3a, 0x68, 0x8b, 0x18, 0x6a, 0x46, 
 0x00, 0x21, 0x4d, 0x00, 0x56, 0x5b, 0xc0, 0x46, 0x5e, 0x53, 0x01, 0x31, 
-0x06, 0x29, 0xf8, 0xd3, 0x22, 0x49, 0x8a, 0x6a, 0x12, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0xd5, 0x1d, 0x49, 0x35, 0x2b, 0x43, 0x6e, 0x46, 0x1d, 0x68, 
-0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x6b, 0x40, 0x1e, 0x4d, 
-0xee, 0x68, 0x73, 0x40, 0x13, 0x65, 0x89, 0x6a, 0x08, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0xc1, 0x1d, 0x4d, 0x31, 0x19, 0x43, 0x09, 0x68, 0x6a, 0x46, 
-0x08, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x51, 0x40, 0xaa, 0x69, 0x51, 0x40, 
-0x41, 0x65, 0x20, 0x78, 0x41, 0x1e, 0x21, 0x70, 0x00, 0x28, 0x0d, 0xd0, 
-0x38, 0x1c, 0xff, 0xf7, 0xef, 0xfe, 0x00, 0x28, 0x0d, 0xd1, 0x09, 0x4a, 
-0x50, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
-0xa3, 0xfa, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 0x72, 0xfa, 0x01, 0xf0, 
-0xc3, 0xfa, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xec, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xb8, 0x03, 0x00, 0x80, 
-0xc8, 0x29, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 0x14, 0x06, 0x00, 0x80, 
+0x06, 0x29, 0xf8, 0xd3, 0x19, 0x49, 0x8a, 0x6a, 0x13, 0x18, 0x1a, 0x6d, 
+0x00, 0x9d, 0x55, 0x40, 0x19, 0x4a, 0xd6, 0x68, 0x75, 0x40, 0x1d, 0x65, 
+0x89, 0x6a, 0x08, 0x18, 0x41, 0x6d, 0x02, 0x9b, 0x59, 0x40, 0x92, 0x69, 
+0x51, 0x40, 0x41, 0x65, 0x20, 0x78, 0x41, 0x1e, 0x21, 0x70, 0x00, 0x28, 
+0x0d, 0xd0, 0x38, 0x1c, 0xff, 0xf7, 0xf4, 0xfe, 0x00, 0x28, 0x0d, 0xd1, 
+0x08, 0x4a, 0x50, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x38, 0x1c, 
+0x00, 0xf0, 0xa4, 0xfa, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 0x73, 0xfa, 
+0x01, 0xf0, 0xde, 0xfa, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x6c, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x38, 0x04, 0x00, 0x80, 
+0x4c, 0x2a, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 0x94, 0x06, 0x00, 0x80, 
 0x08, 0x83, 0x20, 0x40, 0xf0, 0xb5, 0x82, 0xb0, 0x69, 0x4b, 0x9f, 0x6a, 
 0x58, 0x23, 0x5a, 0x43, 0xba, 0x18, 0xc3, 0x1d, 0x49, 0x33, 0x1f, 0x78, 
 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x01, 0x34, 0x23, 0x43, 0x1d, 0x68, 
@@ -625,14 +633,14 @@ const u8 typhoon_firmware_image[] = {
 0xff, 0x26, 0x36, 0x02, 0x2e, 0x40, 0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 
 0x74, 0xd1, 0x6b, 0x0c, 0x2b, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79, 
 0xc0, 0x46, 0x4b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 0x4c, 0x89, 
-0x1b, 0x1b, 0xcb, 0x80, 0x00, 0x24, 0xa6, 0x00, 0x01, 0x96, 0xb3, 0x18, 
-0xde, 0x1d, 0x09, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 
-0x01, 0x9e, 0x76, 0x18, 0x73, 0x61, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 
-0x00, 0x24, 0xa6, 0x00, 0x00, 0x96, 0xb3, 0x18, 0xde, 0x1d, 0x1d, 0x36, 
-0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0x76, 0x18, 
-0xb3, 0x62, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 0x06, 0xe0, 0x00, 0x23, 
-0x4b, 0x81, 0xcb, 0x80, 0x40, 0x23, 0x9c, 0x43, 0x0c, 0x60, 0x23, 0x1c, 
-0x6b, 0x0e, 0x4a, 0xd3, 0xc3, 0x19, 0x20, 0x33, 
+0x1b, 0x1b, 0xcb, 0x80, 0x00, 0x24, 0xa6, 0x00, 
+0x01, 0x96, 0xb3, 0x18, 0xde, 0x1d, 0x09, 0x36, 0x01, 0x23, 0x9b, 0x07, 
+0x33, 0x43, 0x1b, 0x68, 0x01, 0x9e, 0x76, 0x18, 0x73, 0x61, 0x01, 0x34, 
+0x05, 0x2c, 0xf0, 0xd3, 0x00, 0x24, 0xa6, 0x00, 0x00, 0x96, 0xb3, 0x18, 
+0xde, 0x1d, 0x1d, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 
+0x00, 0x9e, 0x76, 0x18, 0xb3, 0x62, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 
+0x06, 0xe0, 0x00, 0x23, 0x4b, 0x81, 0xcb, 0x80, 0x40, 0x23, 0x9c, 0x43, 
+0x0c, 0x60, 0x23, 0x1c, 0x6b, 0x0e, 0x4a, 0xd3, 0xc3, 0x19, 0x20, 0x33, 
 0x1b, 0x79, 0x10, 0x33, 0x0b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 
 0x0f, 0x89, 0xdb, 0x1b, 0x8b, 0x80, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
 0x35, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x63, 0x01, 0x23, 
@@ -653,29 +661,29 @@ const u8 typhoon_firmware_image[] = {
 0x05, 0x28, 0xf2, 0xd3, 0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d, 
 0x1d, 0x34, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18, 
 0xbb, 0x62, 0x01, 0x30, 0x05, 0x28, 0xf2, 0xd3, 0x02, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xc8, 0x29, 0x00, 0x80, 0x80, 0xb4, 0x1f, 0x1c, 
+0x08, 0xbc, 0x18, 0x47, 0x4c, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x1f, 0x1c, 
 0x3b, 0x0c, 0x18, 0xd2, 0x17, 0x6d, 0x11, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 
 0x52, 0x6d, 0xc0, 0x46, 0x1a, 0x61, 0xc7, 0x60, 0x1a, 0x69, 0xc0, 0x46, 
 0x02, 0x61, 0xd8, 0x68, 0xc0, 0x46, 0x08, 0x80, 0xd8, 0x68, 0x00, 0x0c, 
 0x48, 0x80, 0x18, 0x69, 0xc0, 0x46, 0x88, 0x80, 0x18, 0x69, 0x00, 0x0c, 
 0xc8, 0x80, 0x80, 0xbc, 0x70, 0x47, 0x4a, 0x88, 0x12, 0x04, 0x0b, 0x88, 
 0x1a, 0x43, 0xc2, 0x60, 0x8a, 0x88, 0xc9, 0x88, 0x09, 0x04, 0x11, 0x43, 
-0x01, 0x61, 0xf2, 0xe7, 0xac, 0x06, 0x00, 0x80, 0xf1, 0xb5, 0x88, 0xb0, 
+0x01, 0x61, 0xf2, 0xe7, 0x2c, 0x07, 0x00, 0x80, 0xf1, 0xb5, 0x88, 0xb0, 
 0x00, 0x22, 0x08, 0x98, 0x00, 0x6a, 0x08, 0x9b, 0x99, 0x68, 0x49, 0x0a, 
 0x02, 0xd3, 0x01, 0x27, 0xff, 0x03, 0x00, 0xe0, 0x00, 0x27, 0x03, 0x8b, 
-0x00, 0x2b, 0x19, 0xd0, 0xa2, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 
+0x00, 0x2b, 0x19, 0xd0, 0xa3, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 
 0x63, 0x43, 0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 
 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x02, 0xd1, 0x08, 0x23, 
 0x1f, 0x43, 0x07, 0xe0, 0x41, 0x8b, 0x00, 0x29, 0x02, 0xd0, 0x0c, 0x23, 
 0x1f, 0x43, 0x01, 0xe0, 0x04, 0x23, 0x1f, 0x43, 0x83, 0x8a, 0x00, 0x2b, 
-0x18, 0xd0, 0x94, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 
-0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 0x09, 0x68, 
-0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x01, 0xd1, 0x0f, 0x43, 0x07, 0xe0, 
-0xc1, 0x8a, 0x00, 0x29, 0x02, 0xd0, 0x03, 0x23, 0x1f, 0x43, 0x01, 0xe0, 
-0x01, 0x23, 0x1f, 0x43, 0xc1, 0x1d, 0x39, 0x31, 0x07, 0x91, 0x4b, 0x89, 
-0x0c, 0x89, 0x1c, 0x19, 0x24, 0x04, 0x24, 0x0c, 0x08, 0x9d, 0x2d, 0x68, 
-0xc0, 0x46, 0x01, 0x95, 0xc9, 0x88, 0x7d, 0x08, 0x1a, 0xd3, 0x1a, 0x1c, 
-0xc3, 0x1d, 0x19, 0x33, 0x1a, 0x72, 0x07, 0x9a, 
+0x18, 0xd0, 0x95, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 
+0x58, 0x23, 0x63, 0x43, 0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 
+0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x01, 0xd1, 
+0x0f, 0x43, 0x07, 0xe0, 0xc1, 0x8a, 0x00, 0x29, 0x02, 0xd0, 0x03, 0x23, 
+0x1f, 0x43, 0x01, 0xe0, 0x01, 0x23, 0x1f, 0x43, 0xc1, 0x1d, 0x39, 0x31, 
+0x07, 0x91, 0x4b, 0x89, 0x0c, 0x89, 0x1c, 0x19, 0x24, 0x04, 0x24, 0x0c, 
+0x08, 0x9d, 0x2d, 0x68, 0xc0, 0x46, 0x01, 0x95, 0xc9, 0x88, 0x7d, 0x08, 
+0x1a, 0xd3, 0x1a, 0x1c, 0xc3, 0x1d, 0x19, 0x33, 0x1a, 0x72, 0x07, 0x9a, 
 0x92, 0x89, 0xc0, 0x46, 0x1a, 0x73, 0x07, 0x9a, 0x12, 0x89, 0xc0, 0x46, 
 0x02, 0x86, 0x04, 0x87, 0x82, 0x8a, 0x01, 0x3a, 0x82, 0x83, 0x01, 0x22, 
 0x19, 0x71, 0x08, 0x9b, 0x1b, 0x68, 0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 
@@ -684,7 +692,7 @@ const u8 typhoon_firmware_image[] = {
 0x07, 0x9b, 0x9b, 0x89, 0xc0, 0x46, 0x2b, 0x73, 0x07, 0x9b, 0x1b, 0x89, 
 0x2e, 0x1c, 0x55, 0x00, 0x2d, 0x18, 0x05, 0x95, 0x2b, 0x86, 0x00, 0x2a, 
 0x01, 0xd0, 0xc3, 0x8a, 0x00, 0xe0, 0x83, 0x8a, 0x01, 0x3b, 0x05, 0x9d, 
-0xc0, 0x46, 0xab, 0x83, 0x31, 0x71, 0x64, 0x4b, 0x9d, 0x6a, 0x05, 0x9b, 
+0xc0, 0x46, 0xab, 0x83, 0x31, 0x71, 0x65, 0x4b, 0x9d, 0x6a, 0x05, 0x9b, 
 0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18, 0xdd, 0x1d, 0x01, 0x35, 
 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 0x2b, 0x0e, 0x5b, 0x06, 
 0x01, 0xd1, 0x08, 0x31, 0x00, 0xe0, 0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 
@@ -692,7 +700,7 @@ const u8 typhoon_firmware_image[] = {
 0x24, 0x0c, 0x05, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 
 0x1b, 0x19, 0x10, 0x3b, 0x9b, 0x7b, 0x06, 0x9d, 0x40, 0x35, 0x2b, 0x70, 
 0x2b, 0x78, 0x02, 0x33, 0xe3, 0x1a, 0x1c, 0x04, 0x24, 0x0c, 0x01, 0x32, 
-0xbb, 0x08, 0x9b, 0x07, 0x6b, 0xd0, 0x83, 0x18, 0x20, 0x33, 0x04, 0x93, 
+0xbb, 0x08, 0x9b, 0x07, 0x6d, 0xd0, 0x83, 0x18, 0x20, 0x33, 0x04, 0x93, 
 0x19, 0x72, 0x01, 0x9b, 0x5d, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 
 0x1b, 0x68, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9e, 0xc0, 0x46, 
 0x33, 0x73, 0x00, 0x95, 0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 
@@ -701,102 +709,103 @@ const u8 typhoon_firmware_image[] = {
 0x2b, 0x43, 0x55, 0x00, 0x2d, 0x18, 0x2b, 0x86, 0x04, 0x9b, 0xc0, 0x46, 
 0x59, 0x72, 0x04, 0x9b, 0x1b, 0x7b, 0x2e, 0x1c, 0x04, 0x9d, 0xc0, 0x46, 
 0x6b, 0x73, 0x33, 0x8e, 0xc0, 0x46, 0x73, 0x86, 0x00, 0x9d, 0x2b, 0x78, 
-0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x59, 0x18, 0x04, 0x25, 0x3d, 0x40, 
-0x0e, 0xd0, 0x34, 0x87, 0x03, 0x8b, 0x01, 0x3b, 0xb3, 0x83, 0x13, 0x1c, 
-0x1b, 0x18, 0x20, 0x33, 0x19, 0x71, 0x01, 0x9b, 0x5b, 0x18, 0x5b, 0x78, 
-0x9b, 0x00, 0x59, 0x18, 0x08, 0x31, 0x01, 0x32, 0x3b, 0x09, 0x37, 0xd3, 
-0x00, 0x2d, 0x01, 0xd0, 0x43, 0x8b, 0x00, 0xe0, 0x03, 0x8b, 0x55, 0x00, 
-0x2d, 0x18, 0x01, 0x3b, 0xab, 0x83, 0x83, 0x18, 0x03, 0x93, 0x20, 0x33, 
-0x19, 0x71, 0x20, 0x4b, 0x9d, 0x6a, 0x53, 0x00, 0x1b, 0x18, 0x02, 0x93, 
-0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18, 0xdd, 0x1d, 0x01, 0x35, 
-0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 0x2b, 0x0e, 0x5b, 0x06, 
-0x02, 0xd1, 0x08, 0x31, 0x01, 0xe0, 0x15, 0xe0, 0x10, 0x31, 0x81, 0x23, 
-0x5b, 0x02, 0x1d, 0x40, 0x9d, 0x42, 0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 
-0x1c, 0x04, 0x24, 0x0c, 0x02, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 
-0x1b, 0x68, 0x1b, 0x19, 0x10, 0x3b, 0x9b, 0x7b, 0x03, 0x9c, 0x40, 0x34, 
-0x23, 0x70, 0x01, 0x32, 0x07, 0x9b, 0xc0, 0x46, 0xd9, 0x80, 0x51, 0x1e, 
-0xc3, 0x1d, 0x49, 0x33, 0x19, 0x70, 0x07, 0x61, 0x04, 0x2a, 0x06, 0xd2, 
-0x06, 0x49, 0x53, 0x00, 0x1b, 0x18, 0x99, 0x83, 0x01, 0x32, 0x04, 0x2a, 
-0xf9, 0xd3, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xc8, 0x29, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
-0x70, 0x47, 0x80, 0xb5, 0x8c, 0xb0, 0x07, 0x1c, 0x12, 0x48, 0x01, 0x68, 
-0x01, 0x31, 0x01, 0x60, 0x38, 0x68, 0xc0, 0x46, 0x00, 0x90, 0x78, 0x68, 
-0xc0, 0x46, 0x01, 0x90, 0xb8, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x0d, 0x48, 
-0x41, 0x68, 0xc9, 0x68, 0xc0, 0x46, 0x41, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
-0x4f, 0xf8, 0xb8, 0x68, 0x40, 0x09, 0x06, 0xd3, 0x10, 0x23, 0x02, 0x98, 
-0x18, 0x43, 0x02, 0x90, 0x68, 0x46, 0x02, 0xf0, 0xcd, 0xff, 0x68, 0x46, 
-0x02, 0xf0, 0x82, 0xfe, 0x0c, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x78, 0x2a, 0x00, 0x80, 0xec, 0x05, 0x00, 0x80, 0x00, 0xb5, 0x8c, 0xb0, 
-0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 0x05, 0x4b, 0x19, 0x43, 
-0x01, 0x91, 0x00, 0xf0, 0x2f, 0xf8, 0x68, 0x46, 0x02, 0xf0, 0x6c, 0xfe, 
-0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 
-0x02, 0x6a, 0x03, 0x68, 0xc0, 0x46, 0x13, 0x60, 0x40, 0x68, 0xc0, 0x46, 
-0x50, 0x60, 0x40, 0x32, 0x48, 0x68, 0xc0, 0x46, 0x90, 0x80, 0xc8, 0x68, 
-0xc0, 0x46, 0xd0, 0x80, 0x48, 0x69, 0xc0, 0x46, 0x10, 0x81, 0x88, 0x68, 
-0xc0, 0x46, 0x50, 0x81, 0x08, 0x7e, 0xc0, 0x46, 0x90, 0x73, 0x08, 0x69, 
-0xc0, 0x46, 0x90, 0x81, 0x70, 0x47, 0x04, 0x49, 0x08, 0x68, 0x00, 0x28, 
-0x00, 0xd1, 0x70, 0x47, 0xc2, 0x68, 0xc0, 0x46, 0x0a, 0x60, 0xfa, 0xe7, 
-0xec, 0x05, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 0xc0, 0x46, 0xc2, 0x60, 
-0x08, 0x60, 0x70, 0x47, 0xec, 0x05, 0x00, 0x80, 0xb0, 0xb4, 0x00, 0x22, 
-0x12, 0x4f, 0x3b, 0x7f, 0x01, 0x33, 0x3b, 0x77, 0x03, 0x23, 0xfc, 0x1d, 
-0x19, 0x34, 0x38, 0x62, 0x79, 0x62, 0x23, 0x72, 0x0e, 0x4c, 0x25, 0x68, 
-0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c, 0x10, 0xd1, 0x24, 0x68, 
-0xa3, 0x0a, 0x0d, 0xd3, 0x01, 0x23, 0x0a, 0x4f, 0xc0, 0x46, 0xfb, 0x62, 
-0x09, 0x4f, 0x0a, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 0x99, 0x60, 0x58, 0x60, 
-0x10, 0x1c, 0x18, 0x60, 0x01, 0x32, 0xfb, 0xe7, 0x10, 0x1c, 0x38, 0x64, 
-0x01, 0x32, 0xfb, 0xe7, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
-0xc0, 0x00, 0x18, 0x00, 0x02, 0x81, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00, 
-0xf0, 0xb5, 0x47, 0x4f, 0x38, 0x68, 0x47, 0x4e, 0x47, 0x4d, 0x07, 0x23, 
-0x5b, 0x02, 0xec, 0x18, 0x00, 0x28, 0x1d, 0xd1, 0xe0, 0x6a, 0x01, 0x30, 
-0xe0, 0x62, 0x44, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x43, 0x48, 0x41, 0x69, 
-0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 0x00, 0x29, 
-0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 0x09, 0x68, 
-0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 0xf1, 0x6c, 
-0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x3a, 0xfe, 0x38, 0x68, 0x01, 0x28, 
-0x17, 0xd1, 0x37, 0x48, 0x41, 0x69, 0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 
-0x69, 0x31, 0x09, 0x7b, 0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 
-0x01, 0x6d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 
-0x91, 0x42, 0x04, 0xd0, 0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 
-0x1f, 0xfe, 0x38, 0x68, 0x02, 0x28, 0x2f, 0xd1, 0xbb, 0x23, 0x1b, 0x01, 
-0xee, 0x18, 0x70, 0x7a, 0x00, 0x28, 0x03, 0xd0, 0x00, 0x20, 0x70, 0x72, 
-0x00, 0xf0, 0x30, 0xfd, 0x30, 0x7a, 0x00, 0x28, 0x02, 0xd0, 0x78, 0x68, 
-0x02, 0xf0, 0x96, 0xff, 0x1b, 0x23, 0xdb, 0x01, 0xe8, 0x18, 0x40, 0x8b, 
-0x04, 0x26, 0x06, 0x40, 0xa0, 0x6a, 0xb0, 0x42, 
-0x14, 0xd0, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 0x19, 0x28, 0x11, 0xd3, 
-0x1b, 0x48, 0x01, 0x7b, 0x00, 0x29, 0x0d, 0xd1, 0xff, 0x30, 0x41, 0x30, 
-0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0xb8, 0x68, 0x02, 0xf0, 0x7c, 0xff, 
-0x00, 0x20, 0xf8, 0x60, 0xa6, 0x62, 0x01, 0xe0, 0x00, 0x20, 0xf8, 0x60, 
-0x38, 0x68, 0x03, 0x28, 0x0b, 0xd1, 0xec, 0x1d, 0x79, 0x34, 0xa0, 0x6b, 
-0x80, 0x08, 0x02, 0xd3, 0x02, 0x20, 0x02, 0xf0, 0xef, 0xfb, 0x02, 0x23, 
-0xa0, 0x6b, 0x98, 0x43, 0xa0, 0x63, 0x38, 0x68, 0x01, 0x30, 0x38, 0x60, 
-0x03, 0x28, 0x01, 0xd9, 0x00, 0x20, 0x38, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xbc, 0x03, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 0xd0, 0x2c, 0x00, 0x80, 
-0x50, 0x2c, 0x00, 0x80, 0xa8, 0x04, 0x00, 0x80, 0x90, 0xb4, 0x1c, 0x48, 
-0x02, 0x8a, 0x1c, 0x49, 0x0f, 0x8a, 0x01, 0x23, 0xba, 0x42, 0x03, 0xd1, 
-0xc2, 0x89, 0x4f, 0x8a, 0xba, 0x42, 0x10, 0xd0, 0x02, 0x7b, 0x00, 0x2a, 
-0x0d, 0xd0, 0x42, 0x7b, 0x00, 0x2a, 0x0a, 0xd0, 0xc7, 0x8a, 0x8a, 0x8a, 
-0x97, 0x42, 0x04, 0xdc, 0x13, 0x4a, 0xc0, 0x46, 0x53, 0x60, 0x8b, 0x82, 
-0x01, 0xe0, 0x01, 0x32, 0x8a, 0x82, 0x42, 0x8b, 0x57, 0x1c, 0x47, 0x83, 
-0x07, 0x8b, 0xba, 0x42, 0x0e, 0xdb, 0x07, 0x8a, 0x84, 0x8a, 0x00, 0x22, 
-0xa7, 0x42, 0x05, 0xda, 0xc7, 0x89, 0x44, 0x8a, 0xa7, 0x42, 0x01, 0xda, 
-0x42, 0x73, 0x00, 0xe0, 0x43, 0x73, 0xc2, 0x81, 0x02, 0x82, 0x42, 0x83, 
-0xc2, 0x89, 0xc0, 0x46, 0x4a, 0x82, 0x00, 0x8a, 0xc0, 0x46, 0x08, 0x82, 
-0x90, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xbc, 0x03, 0x00, 0x80, 
-0x40, 0x01, 0x18, 0x00, 0xf7, 0xb5, 0x91, 0xb0, 0x6b, 0x46, 0x84, 0x1e, 
-0x12, 0x99, 0x14, 0x29, 0x1a, 0xd9, 0x00, 0x20, 0x81, 0x00, 0x67, 0x58, 
-0xc0, 0x46, 0x57, 0x50, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28, 
-0xf6, 0xd3, 0x00, 0x21, 0x05, 0x20, 0x87, 0x00, 0xd6, 0x59, 0x4f, 0x1c, 
-0x3d, 0x06, 0x2d, 0x0e, 0x0f, 0x1c, 0xbf, 0x00, 0xde, 0x51, 0x29, 0x1c, 
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28, 0xf1, 0xd3, 0x09, 0xe0, 
-0x00, 0x20, 0x81, 0x00, 0x63, 0x58, 0xc0, 0x46, 0x53, 0x50, 0x01, 0x30, 
-0x00, 0x06, 0x00, 0x0e, 0x06, 0x28, 0xf6, 0xd3, 0x00, 0x20, 0xe0, 0x70, 
-0x20, 0x72, 0x60, 0x72, 0xa0, 0x72, 0x20, 0x73, 0x60, 0x73, 0x12, 0x99, 
-0x14, 0x29, 0x37, 0xd9, 0x69, 0x46, 0x8e, 0x1c, 0x91, 0x78, 0x09, 0x07, 
-0x09, 0x0f, 0x89, 0x00, 0x14, 0x39, 0x0d, 0x06, 0x2d, 0x16, 0x00, 0x27, 
-0x00, 0x2d, 0x1b, 0xdd, 0xf0, 0x19, 0x10, 0xa9, 0x00, 0xf0, 0x3d, 0xf8, 
-0x00, 0x28, 0x0e, 0xd0, 0x00, 0x20, 0x10, 0xa9, 0x09, 0x78, 0x00, 0x29, 
-0x09, 0xdd, 0x00, 0x22, 0x39, 0x18, 0x72, 0x54, 0x01, 0x30, 0x00, 0x06, 
+0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c, 0x59, 0x18, 
+0x04, 0x25, 0x3d, 0x40, 0x0e, 0xd0, 0x34, 0x87, 0x03, 0x8b, 0x01, 0x3b, 
+0xb3, 0x83, 0x13, 0x1c, 0x1b, 0x18, 0x20, 0x33, 0x19, 0x71, 0x01, 0x9b, 
+0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 0x59, 0x18, 0x08, 0x31, 0x01, 0x32, 
+0x3b, 0x09, 0x37, 0xd3, 0x00, 0x2d, 0x01, 0xd0, 0x43, 0x8b, 0x00, 0xe0, 
+0x03, 0x8b, 0x55, 0x00, 0x2d, 0x18, 0x01, 0x3b, 0xab, 0x83, 0x83, 0x18, 
+0x03, 0x93, 0x20, 0x33, 0x19, 0x71, 0x20, 0x4b, 0x9d, 0x6a, 0x53, 0x00, 
+0x1b, 0x18, 0x02, 0x93, 0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18, 
+0xdd, 0x1d, 0x01, 0x35, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 
+0x2b, 0x0e, 0x5b, 0x06, 0x02, 0xd1, 0x08, 0x31, 0x01, 0xe0, 0x15, 0xe0, 
+0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40, 
+0x9d, 0x42, 0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c, 
+0x02, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19, 
+0x10, 0x3b, 0x9b, 0x7b, 0x03, 0x9c, 0x40, 0x34, 0x23, 0x70, 0x01, 0x32, 
+0x07, 0x9b, 0xc0, 0x46, 0xd9, 0x80, 0x51, 0x1e, 0xc3, 0x1d, 0x49, 0x33, 
+0x19, 0x70, 0x07, 0x61, 0x04, 0x2a, 0x06, 0xd2, 0x06, 0x49, 0x53, 0x00, 
+0x1b, 0x18, 0x99, 0x83, 0x01, 0x32, 0x04, 0x2a, 0xf9, 0xd3, 0x09, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 
+0xff, 0xff, 0x00, 0x00, 0x70, 0x47, 0x80, 0xb5, 0x8c, 0xb0, 0x07, 0x1c, 
+0x12, 0x48, 0x01, 0x68, 0x01, 0x31, 0x01, 0x60, 0x38, 0x68, 0xc0, 0x46, 
+0x00, 0x90, 0x78, 0x68, 0xc0, 0x46, 0x01, 0x90, 0xb8, 0x68, 0xc0, 0x46, 
+0x02, 0x90, 0x0d, 0x48, 0x41, 0x68, 0xc9, 0x68, 0xc0, 0x46, 0x41, 0x60, 
+0x38, 0x1c, 0x00, 0xf0, 0x4f, 0xf8, 0xb8, 0x68, 0x40, 0x09, 0x06, 0xd3, 
+0x10, 0x23, 0x02, 0x98, 0x18, 0x43, 0x02, 0x90, 0x68, 0x46, 0x02, 0xf0, 
+0xe1, 0xff, 0x68, 0x46, 0x02, 0xf0, 0x9a, 0xfe, 0x0c, 0xb0, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0x00, 0xb5, 0x8c, 0xb0, 0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 
+0x05, 0x4b, 0x19, 0x43, 0x01, 0x91, 0x00, 0xf0, 0x2f, 0xf8, 0x68, 0x46, 
+0x02, 0xf0, 0x84, 0xfe, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xa0, 0x02, 0x6a, 0x03, 0x68, 0xc0, 0x46, 0x13, 0x60, 
+0x40, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x40, 0x32, 0x48, 0x68, 0xc0, 0x46, 
+0x90, 0x80, 0xc8, 0x68, 0xc0, 0x46, 0xd0, 0x80, 0x48, 0x69, 0xc0, 0x46, 
+0x10, 0x81, 0x88, 0x68, 0xc0, 0x46, 0x50, 0x81, 0x08, 0x7e, 0xc0, 0x46, 
+0x90, 0x73, 0x08, 0x69, 0xc0, 0x46, 0x90, 0x81, 0x70, 0x47, 0x04, 0x49, 
+0x08, 0x68, 0x00, 0x28, 0x00, 0xd1, 0x70, 0x47, 0xc2, 0x68, 0xc0, 0x46, 
+0x0a, 0x60, 0xfa, 0xe7, 0x6c, 0x06, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 
+0xc0, 0x46, 0xc2, 0x60, 0x08, 0x60, 0x70, 0x47, 0x6c, 0x06, 0x00, 0x80, 
+0xb0, 0xb4, 0x00, 0x22, 0x12, 0x4f, 0x7c, 0x7f, 0x01, 0x34, 0x7c, 0x77, 
+0x03, 0x23, 0xfc, 0x1d, 0x19, 0x34, 0x38, 0x62, 0x79, 0x62, 0x23, 0x72, 
+0x0e, 0x4c, 0x25, 0x68, 0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c, 
+0x10, 0xd1, 0x24, 0x68, 0xa3, 0x0a, 0x0d, 0xd3, 0x01, 0x23, 0x0a, 0x4f, 
+0xc0, 0x46, 0xfb, 0x62, 0x09, 0x4f, 0x0a, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 
+0x99, 0x60, 0x58, 0x60, 0x10, 0x1c, 0x18, 0x60, 0x01, 0x32, 0xfb, 0xe7, 
+0x10, 0x1c, 0x38, 0x64, 0x01, 0x32, 0xfb, 0xe7, 0x00, 0x00, 0x00, 0x80, 
+0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x02, 0x81, 0x00, 0x00, 
+0x40, 0x01, 0x18, 0x00, 0xf0, 0xb5, 0x47, 0x4f, 0x38, 0x68, 0x47, 0x4e, 
+0x47, 0x4d, 0x07, 0x23, 0x5b, 0x02, 0xec, 0x18, 0x00, 0x28, 0x1d, 0xd1, 
+0x20, 0x6b, 0x01, 0x30, 0x20, 0x63, 0x44, 0x49, 0xc0, 0x46, 0x08, 0x60, 
+0x43, 0x48, 0x41, 0x69, 0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 
+0x09, 0x7b, 0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 
+0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 
+0x04, 0xd0, 0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x50, 0xfe, 
+0x38, 0x68, 0x01, 0x28, 0x17, 0xd1, 0x37, 0x48, 0x41, 0x69, 0x00, 0x29, 
+0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 
+0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 
+0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x35, 0xfe, 0x38, 0x68, 
+0x02, 0x28, 0x2f, 0xd1, 0xbb, 0x23, 0x1b, 0x01, 0xee, 0x18, 0x70, 0x7b, 
+0x00, 0x28, 0x03, 0xd0, 0x00, 0x20, 0x70, 0x73, 0x00, 0xf0, 0x4a, 0xfd, 
+0x30, 0x7b, 0x00, 0x28, 0x02, 0xd0, 0x78, 0x68, 0x02, 0xf0, 0xaa, 0xff, 
+0x1b, 0x23, 0xdb, 0x01, 0xe8, 0x18, 0xc0, 0x8b, 0x04, 0x26, 0x06, 0x40, 
+0xe0, 0x6a, 0xb0, 0x42, 0x14, 0xd0, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 
+0x19, 0x28, 0x11, 0xd3, 0x1b, 0x48, 0x01, 0x7b, 0x00, 0x29, 0x0d, 0xd1, 
+0xff, 0x30, 0x41, 0x30, 0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0xb8, 0x68, 
+0x02, 0xf0, 0x90, 0xff, 0x00, 0x20, 0xf8, 0x60, 0xe6, 0x62, 0x01, 0xe0, 
+0x00, 0x20, 0xf8, 0x60, 0x38, 0x68, 0x03, 0x28, 0x0b, 0xd1, 0xec, 0x1d, 
+0x79, 0x34, 0xe0, 0x6b, 0x80, 0x08, 0x02, 0xd3, 0x02, 0x20, 0x02, 0xf0, 
+0x07, 0xfc, 0x02, 0x23, 0xe0, 0x6b, 0x98, 0x43, 0xe0, 0x63, 0x38, 0x68, 
+0x01, 0x30, 0x38, 0x60, 0x03, 0x28, 0x01, 0xd9, 0x00, 0x20, 0x38, 0x60, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 
+0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 
+0xb0, 0xb4, 0x1d, 0x48, 0x84, 0x8a, 0x1d, 0x4a, 0x13, 0x8a, 0xc1, 0x1d, 
+0x09, 0x31, 0x01, 0x27, 0x9c, 0x42, 0x03, 0xd1, 0x43, 0x8a, 0x54, 0x8a, 
+0xa3, 0x42, 0x10, 0xd0, 0x0b, 0x78, 0x00, 0x2b, 0x0d, 0xd0, 0x4b, 0x78, 
+0x00, 0x2b, 0x0a, 0xd0, 0x44, 0x8b, 0x93, 0x8a, 0x9c, 0x42, 0x04, 0xdc, 
+0x13, 0x4b, 0xc0, 0x46, 0x5f, 0x60, 0x97, 0x82, 0x01, 0xe0, 0x01, 0x33, 
+0x93, 0x82, 0xc3, 0x8b, 0x5c, 0x1c, 0xc4, 0x83, 0x84, 0x8b, 0xa3, 0x42, 
+0x0e, 0xdb, 0x84, 0x8a, 0x05, 0x8b, 0x00, 0x23, 0xac, 0x42, 0x05, 0xda, 
+0x44, 0x8a, 0xc5, 0x8a, 0xac, 0x42, 0x01, 0xda, 0x4b, 0x70, 0x00, 0xe0, 
+0x4f, 0x70, 0x43, 0x82, 0x83, 0x82, 0xc3, 0x83, 0x41, 0x8a, 0xc0, 0x46, 
+0x51, 0x82, 0x80, 0x8a, 0xc0, 0x46, 0x10, 0x82, 0xb0, 0xbc, 0x70, 0x47, 
+0xe8, 0x0e, 0x00, 0x80, 0x3c, 0x04, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 
+0xf7, 0xb5, 0x91, 0xb0, 0x6b, 0x46, 0x84, 0x1e, 0x12, 0x99, 0x14, 0x29, 
+0x1a, 0xd9, 0x00, 0x20, 0x81, 0x00, 0x67, 0x58, 0xc0, 0x46, 0x57, 0x50, 
+0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x21, 
+0x05, 0x20, 0x87, 0x00, 0xd6, 0x59, 0x4f, 0x1c, 0x3d, 0x06, 0x2d, 0x0e, 
+0x0f, 0x1c, 0xbf, 0x00, 0xde, 0x51, 0x29, 0x1c, 0x01, 0x30, 0x00, 0x06, 
+0x00, 0x0e, 0x10, 0x28, 0xf1, 0xd3, 0x09, 0xe0, 0x00, 0x20, 0x81, 0x00, 
+0x63, 0x58, 0xc0, 0x46, 0x53, 0x50, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 
+0x06, 0x28, 0xf6, 0xd3, 0x00, 0x20, 0xe0, 0x70, 0x20, 0x72, 0x60, 0x72, 
+0xa0, 0x72, 0x20, 0x73, 0x60, 0x73, 0x12, 0x99, 0x14, 0x29, 0x37, 0xd9, 
+0x69, 0x46, 0x8e, 0x1c, 0x91, 0x78, 0x09, 0x07, 0x09, 0x0f, 0x89, 0x00, 
+0x14, 0x39, 0x0d, 0x06, 0x2d, 0x16, 0x00, 0x27, 0x00, 0x2d, 0x1b, 0xdd, 
+0xf0, 0x19, 0x10, 0xa9, 0x00, 0xf0, 0x3d, 0xf8, 0x00, 0x28, 0x0e, 0xd0, 
+0x00, 0x20, 0x10, 0xa9, 0x09, 0x78, 0x00, 0x29, 0x09, 0xdd, 0x00, 0x22, 
+0x39, 0x18, 0x72, 0x54, 0x01, 0x30, 0x00, 0x06, 
 0x00, 0x0e, 0x10, 0xa9, 0x09, 0x78, 0x88, 0x42, 0xf6, 0xdb, 0x10, 0xa8, 
 0x00, 0x78, 0x38, 0x18, 0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 0xe3, 0xdb, 
 0x68, 0x46, 0xe2, 0x1d, 0x0d, 0x32, 0x00, 0x21, 0xab, 0x08, 0x5f, 0x1c, 
@@ -804,257 +813,261 @@ const u8 typhoon_firmware_image[] = {
 0x09, 0x06, 0x09, 0x0e, 0x8f, 0x42, 0xf6, 0xd8, 0x14, 0xb0, 0xf0, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb4, 0x87, 0x1e, 0x00, 0x20, 0x89, 0x08, 
 0x4b, 0x1c, 0x08, 0xd0, 0x81, 0x00, 0x54, 0x58, 0xc0, 0x46, 0x7c, 0x50, 
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x83, 0x42, 
-0xf6, 0xd8, 0x90, 0xbc, 0x70, 0x47, 0x80, 0xb4, 0x02, 0x78, 0xd2, 0x06, 
-0xd2, 0x0e, 0x00, 0x23, 0x01, 0x27, 0x01, 0x2a, 0x01, 0xdc, 0x0f, 0x70, 
-0x11, 0xe0, 0x40, 0x78, 0xc0, 0x46, 0x08, 0x70, 0x14, 0x2a, 0x04, 0xd1, 
-0x08, 0x48, 0x01, 0x7a, 0x01, 0x31, 0x01, 0x72, 0x07, 0xe0, 0x02, 0x2a, 
-0x05, 0xd0, 0x05, 0x2a, 0x03, 0xd0, 0x06, 0x2a, 0x01, 0xd0, 0x15, 0x2a, 
-0x02, 0xd1, 0x18, 0x1c, 0x80, 0xbc, 0x70, 0x47, 0x38, 0x1c, 0xfb, 0xe7, 
-0xe0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x0f, 0x48, 0x01, 0x23, 0x1b, 0x06, 
-0x41, 0x69, 0x99, 0x43, 0x1a, 0x09, 0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 
-0xa1, 0x22, 0x52, 0x03, 0x91, 0x61, 0x19, 0x1c, 0x09, 0x4a, 0xc0, 0x46, 
-0x11, 0x60, 0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x40, 0x69, 0x00, 0x28, 
-0x03, 0xd0, 0x02, 0xf0, 0x4f, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x04, 0x48, 
-0x41, 0x88, 0x01, 0x31, 0x41, 0x80, 0xf8, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0xb0, 0xe0, 0x82, 0x20, 0x40, 0x70, 0x47, 0x00, 0x00, 
-0xf0, 0xb5, 0x85, 0xb0, 0x94, 0x49, 0xc8, 0x68, 0xcf, 0x1d, 0x79, 0x37, 
-0x01, 0x28, 0x0b, 0xd1, 0xb8, 0x88, 0x00, 0x28, 0x08, 0xd1, 0xc3, 0x1e, 
-0xca, 0x6f, 0x1a, 0x40, 0xca, 0x67, 0x8f, 0x48, 0xc0, 0x46, 0x02, 0x60, 
-0x14, 0x20, 0xb8, 0x80, 0x8d, 0x4c, 0x62, 0x6a, 0x8d, 0x48, 0xc3, 0x6b, 
-0x9a, 0x18, 0xc2, 0x63, 0xa0, 0x6a, 0x19, 0x23, 0xdb, 0x01, 0xcc, 0x18, 
-0x60, 0x62, 0xe2, 0x69, 0x12, 0x03, 0x12, 0x0b, 0x82, 0x42, 0x05, 0xd1, 
-0x01, 0x20, 0x40, 0x04, 0x86, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xef, 0xe0, 
-0x3b, 0x8a, 0x58, 0x1c, 0x38, 0x82, 0xbd, 0x8a, 0x01, 0x20, 0x00, 0x22, 
-0xab, 0x42, 0x02, 0xdb, 0x78, 0x73, 0x3a, 0x82, 0x7a, 0x83, 0x33, 0x23, 
-0x9b, 0x01, 0xcb, 0x18, 0x04, 0x93, 0x1b, 0x69, 0x0f, 0x2b, 0x73, 0xd2, 
-0x00, 0x22, 0x2f, 0x23, 0x9b, 0x01, 0xcf, 0x18, 0xfa, 0x60, 0xe1, 0x69, 
-0x8a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x4b, 0x68, 0x1e, 0x0c, 0x36, 0x04, 
-0x76, 0x4d, 0x05, 0xd1, 0x3b, 0x2a, 0x03, 0xd3, 0x01, 0x23, 0xdb, 0x02, 
-0x9a, 0x42, 0x01, 0xd9, 0xa8, 0x72, 0xc7, 0xe0, 0x01, 0x23, 0x9b, 0x07, 
-0x08, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x03, 0x91, 0x03, 0xa9, 
-0x09, 0x88, 0x01, 0x31, 0x09, 0x04, 0x09, 0x0c, 0xf9, 0x81, 0x49, 0x09, 
-0x05, 0x31, 0x09, 0x06, 0x09, 0x0e, 0x6a, 0x4a, 0xc0, 0x46, 0x02, 0x92, 
-0x06, 0x1c, 0x69, 0x48, 0x43, 0x6a, 0xc0, 0x46, 0x01, 0x93, 0x83, 0x6a, 
-0xc0, 0x46, 0x00, 0x93, 0xc2, 0x1d, 0x11, 0x32, 0x80, 0x69, 0x00, 0x03, 
-0x00, 0x0b, 0x92, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x1a, 0x43, 0x12, 0x68, 
-0x90, 0x42, 0x01, 0xd1, 0x30, 0x1c, 0x0d, 0xe0, 0x90, 0x42, 0x05, 0xd9, 
-0x00, 0x9b, 0x18, 0x1a, 0x01, 0x9b, 0xd2, 0x1a, 0x82, 0x18, 0x00, 0xe0, 
-0x12, 0x1a, 0x01, 0x20, 0x09, 0x01, 0x91, 0x42, 0x00, 0xd3, 0x00, 0x20, 
-0x01, 0x28, 0x62, 0xd1, 0xe0, 0x68, 0x00, 0x28, 0x60, 0xd0, 0x04, 0x99, 
-0x08, 0x69, 0x01, 0x30, 0x08, 0x61, 0x02, 0x20, 0xe1, 0x69, 0xc0, 0x46, 
-0x08, 0x60, 0x00, 0xf0, 0x8f, 0xfc, 0x38, 0x63, 0x4e, 0x49, 0xc0, 0x46, 
-0x79, 0x60, 0xe1, 0x69, 0x62, 0x6b, 0x8a, 0x18, 0x23, 0x6b, 0x9a, 0x42, 
-0x00, 0xd9, 0xe1, 0x6a, 0xc0, 0x46, 0x79, 0x62, 0x79, 0x6a, 0x0c, 0x31, 
-0xb9, 0x62, 0x00, 0x21, 0xb9, 0x61, 0x03, 0xa9, 0x49, 0x88, 0xc9, 0x09, 
-0x03, 0xd3, 0x00, 0xe0, 0x78, 0xe0, 0x31, 0x1c, 
-0x00, 0xe0, 0x00, 0x21, 0x39, 0x60, 0x39, 0x68, 0xc0, 0x46, 0x01, 0x60, 
-0xf8, 0x89, 0x41, 0x4e, 0x60, 0x28, 0x04, 0xdc, 0x30, 0x83, 0xf8, 0x89, 
-0xc0, 0x46, 0x70, 0x83, 0x08, 0xe0, 0x60, 0x20, 0x30, 0x83, 0xf9, 0x89, 
-0xb8, 0x6a, 0x42, 0x18, 0x23, 0x6b, 0x9a, 0x42, 0x03, 0xd8, 0x71, 0x83, 
-0x00, 0x21, 0xf9, 0x62, 0x05, 0xe0, 0xe1, 0x6a, 0xc0, 0x46, 0xf9, 0x62, 
-0x21, 0x6b, 0x08, 0x1a, 0x70, 0x83, 0x38, 0x6b, 0x41, 0x68, 0xc0, 0x46, 
-0x79, 0x60, 0x81, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0x01, 0x69, 0xc0, 0x46, 
-0x39, 0x61, 0x40, 0x69, 0xc0, 0x46, 0x78, 0x61, 0x38, 0x1c, 0x00, 0xf0, 
-0x23, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x88, 0xf8, 0x00, 0xf0, 0xe0, 0xfa, 
-0xf8, 0x89, 0x71, 0x8b, 0x88, 0x42, 0x04, 0xd1, 0xb9, 0x6a, 0x08, 0x18, 
-0x04, 0xe0, 0x38, 0xe0, 0x32, 0xe0, 0xfa, 0x6a, 0x10, 0x18, 0x40, 0x1a, 
-0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x21, 0x6b, 
-0x09, 0x1a, 0x62, 0x6b, 0x91, 0x42, 0x00, 0xd2, 0xe0, 0x6a, 0xc0, 0x46, 
-0xe0, 0x61, 0xe8, 0x7a, 0x00, 0x28, 0x08, 0xd0, 0x00, 0x21, 0xe9, 0x72, 
-0x04, 0x99, 0x08, 0x69, 0x01, 0x38, 0x08, 0x61, 0x38, 0x6b, 0x00, 0xf0, 
-0x5d, 0xfa, 0x18, 0x48, 0x80, 0x6a, 0x80, 0x06, 0x80, 0x0e, 0x01, 0x28, 
-0x0a, 0xd1, 0xe0, 0x69, 0x00, 0x03, 0x00, 0x0b, 0x0c, 0x4c, 0xa1, 0x6a, 
-0x88, 0x42, 0x03, 0xd0, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x01, 0x20, 0x40, 0x04, 0x09, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x05, 0xe0, 
-0xa0, 0x68, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x9f, 0xfa, 0xae, 0x72, 
-0xee, 0xe7, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x01, 0x11, 0x00, 
-0x00, 0x40, 0x14, 0x40, 0x10, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 
-0x98, 0x19, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 0x28, 0x03, 0x00, 0x80, 
-0xe8, 0x19, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0x80, 0xb5, 0x07, 0x1c, 
+0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x83, 0x42, 0xf6, 0xd8, 0x90, 0xbc, 
+0x70, 0x47, 0x80, 0xb4, 0x02, 0x78, 0xd2, 0x06, 0xd2, 0x0e, 0x00, 0x23, 
+0x01, 0x27, 0x01, 0x2a, 0x01, 0xdc, 0x0f, 0x70, 0x11, 0xe0, 0x40, 0x78, 
+0xc0, 0x46, 0x08, 0x70, 0x14, 0x2a, 0x04, 0xd1, 0x08, 0x48, 0x01, 0x7a, 
+0x01, 0x31, 0x01, 0x72, 0x07, 0xe0, 0x02, 0x2a, 0x05, 0xd0, 0x05, 0x2a, 
+0x03, 0xd0, 0x06, 0x2a, 0x01, 0xd0, 0x15, 0x2a, 0x02, 0xd1, 0x18, 0x1c, 
+0x80, 0xbc, 0x70, 0x47, 0x38, 0x1c, 0xfb, 0xe7, 0xe0, 0x82, 0x20, 0x40, 
+0x00, 0xb5, 0x0f, 0x48, 0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 
+0x1a, 0x09, 0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 
+0x91, 0x61, 0x19, 0x1c, 0x09, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x1b, 0x23, 
+0xdb, 0x01, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 0x03, 0xd0, 0x02, 0xf0, 
+0x61, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x04, 0x48, 0x41, 0x88, 0x01, 0x31, 
+0x41, 0x80, 0xf8, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 
+0xe0, 0x82, 0x20, 0x40, 0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x86, 0xb0, 
+0x95, 0x4a, 0xd0, 0x68, 0xd7, 0x1d, 0x79, 0x37, 0x01, 0x28, 0x09, 0xd1, 
+0x38, 0x89, 0x00, 0x28, 0x06, 0xd1, 0xd0, 0x6f, 0x02, 0x23, 0x01, 0x68, 
+0x99, 0x43, 0x01, 0x60, 0x14, 0x20, 0x38, 0x81, 0x8e, 0x4c, 0x61, 0x6a, 
+0x8e, 0x48, 0xc3, 0x6b, 0x59, 0x18, 0xc1, 0x63, 0xa0, 0x6a, 0x19, 0x23, 
+0xdb, 0x01, 0xd4, 0x18, 0xa0, 0x62, 0x21, 0x6a, 0x09, 0x03, 0x09, 0x0b, 
+0x81, 0x42, 0x05, 0xd1, 0x01, 0x20, 0x40, 0x04, 0x87, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0xf3, 0xe0, 0xbb, 0x8a, 0x58, 0x1c, 0xb8, 0x82, 0x3d, 0x8b, 
+0x01, 0x20, 0x00, 0x21, 0xab, 0x42, 0x04, 0xdb, 0xd3, 0x1d, 0x89, 0x33, 
+0x58, 0x70, 0xb9, 0x82, 0xf9, 0x83, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 
+0x05, 0x93, 0x5b, 0x69, 0x0f, 0x2b, 0x73, 0xd2, 0x00, 0x21, 0x7c, 0x4f, 
+0xc0, 0x46, 0x39, 0x61, 0x21, 0x6a, 0x8a, 0x68, 0x12, 0x04, 0x12, 0x0c, 
+0x4b, 0x68, 0x1e, 0x0c, 0x36, 0x04, 0xfd, 0x1f, 0x09, 0x3d, 0x00, 0x2e, 
+0x05, 0xd1, 0x3b, 0x2a, 0x03, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x9a, 0x42, 
+0x01, 0xd9, 0xa8, 0x73, 0xc8, 0xe0, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x31, 
+0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x03, 0x91, 0x03, 0xa9, 0x09, 0x88, 
+0x01, 0x31, 0x09, 0x04, 0x09, 0x0c, 0x79, 0x82, 0x49, 0x09, 0x05, 0x31, 
+0x09, 0x06, 0x09, 0x0e, 0x69, 0x4e, 0xc0, 0x46, 0x02, 0x96, 0x69, 0x48, 
+0x43, 0x6a, 0xc0, 0x46, 0x01, 0x93, 0x83, 0x6a, 0xc0, 0x46, 0x00, 0x93, 
+0xc2, 0x1d, 0x11, 0x32, 0x80, 0x69, 0x00, 0x03, 0x00, 0x0b, 0x92, 0x68, 
+0xb3, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x90, 0x42, 0x01, 0xd1, 0x01, 0x20, 
+0x0d, 0xe0, 0x90, 0x42, 0x05, 0xd9, 0x00, 0x9b, 0x18, 0x1a, 0x01, 0x9b, 
+0xd2, 0x1a, 0x82, 0x18, 0x00, 0xe0, 0x12, 0x1a, 
+0x01, 0x20, 0x09, 0x01, 0x91, 0x42, 0x00, 0xd3, 0x00, 0x20, 0x01, 0x28, 
+0x65, 0xd1, 0x51, 0x49, 0x20, 0x69, 0x00, 0x28, 0x62, 0xd0, 0x05, 0x99, 
+0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x02, 0x20, 0x21, 0x6a, 0xc0, 0x46, 
+0x08, 0x60, 0x00, 0xf0, 0xa7, 0xfc, 0x78, 0x63, 0xbe, 0x60, 0x49, 0x49, 
+0x22, 0x6a, 0xa3, 0x6b, 0xd3, 0x18, 0x66, 0x6b, 0xb3, 0x42, 0x00, 0xd9, 
+0x22, 0x6b, 0xc0, 0x46, 0xba, 0x62, 0xba, 0x6a, 0x0c, 0x32, 0xfa, 0x62, 
+0x00, 0x22, 0xfa, 0x61, 0x03, 0xaa, 0x52, 0x88, 0xd2, 0x09, 0x03, 0xd3, 
+0x01, 0x22, 0x00, 0xe0, 0x7b, 0xe0, 0x00, 0xe0, 0x00, 0x22, 0x7a, 0x60, 
+0x7a, 0x68, 0xc0, 0x46, 0x02, 0x60, 0x78, 0x8a, 0x41, 0x4e, 0x60, 0x28, 
+0x04, 0xdc, 0xb0, 0x83, 0x78, 0x8a, 0xc0, 0x46, 0xf0, 0x83, 0x08, 0xe0, 
+0x60, 0x20, 0xb0, 0x83, 0x79, 0x8a, 0xf8, 0x6a, 0x42, 0x18, 0x63, 0x6b, 
+0x9a, 0x42, 0x03, 0xd8, 0xf1, 0x83, 0x00, 0x22, 0x3a, 0x63, 0x05, 0xe0, 
+0x21, 0x6b, 0xc0, 0x46, 0x39, 0x63, 0x61, 0x6b, 0x08, 0x1a, 0xf0, 0x83, 
+0x2d, 0x49, 0x78, 0x6b, 0x42, 0x68, 0xc0, 0x46, 0xba, 0x60, 0x82, 0x68, 
+0xc0, 0x46, 0xfa, 0x60, 0x02, 0x69, 0xc0, 0x46, 0x7a, 0x61, 0x40, 0x69, 
+0xc0, 0x46, 0xb8, 0x61, 0x2e, 0x4b, 0xc8, 0x18, 0x04, 0x90, 0x00, 0xf0, 
+0x37, 0xf9, 0x04, 0x98, 0x00, 0xf0, 0x88, 0xf8, 0x00, 0xf0, 0xf6, 0xfa, 
+0x78, 0x8a, 0xf1, 0x8b, 0x88, 0x42, 0x04, 0xd1, 0xf9, 0x6a, 0x08, 0x18, 
+0x04, 0xe0, 0x38, 0xe0, 0x32, 0xe0, 0x3a, 0x6b, 0x10, 0x18, 0x40, 0x1a, 
+0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x61, 0x6b, 
+0x09, 0x1a, 0xa2, 0x6b, 0x91, 0x42, 0x00, 0xd2, 0x20, 0x6b, 0xc0, 0x46, 
+0x20, 0x62, 0xe8, 0x7b, 0x00, 0x28, 0x08, 0xd0, 0x00, 0x22, 0xea, 0x73, 
+0x05, 0x99, 0x48, 0x69, 0x01, 0x38, 0x48, 0x61, 0x78, 0x6b, 0x00, 0xf0, 
+0x73, 0xfa, 0x18, 0x48, 0x80, 0x6a, 0x80, 0x06, 0x80, 0x0e, 0x01, 0x28, 
+0x0a, 0xd1, 0x20, 0x6a, 0x00, 0x03, 0x00, 0x0b, 0x0b, 0x4c, 0xa1, 0x6a, 
+0x88, 0x42, 0x03, 0xd0, 0x06, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x01, 0x20, 0x40, 0x04, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x06, 0xe0, 
+0xe0, 0x68, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0xb5, 0xfa, 0x01, 0x20, 
+0xa8, 0x73, 0xed, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x40, 0x14, 0x40, 
+0xa4, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x1a, 0x00, 0x80, 
+0x55, 0x55, 0x55, 0x55, 0xa8, 0x03, 0x00, 0x80, 0x68, 0x1a, 0x00, 0x80, 
+0xc4, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x80, 0xb5, 0x07, 0x1c, 
 0x78, 0x6a, 0x40, 0x89, 0xff, 0x21, 0x01, 0x31, 0x01, 0x40, 0x10, 0x48, 
 0x02, 0xd1, 0x81, 0x6c, 0x01, 0x31, 0x81, 0x64, 0x79, 0x6a, 0x49, 0x89, 
 0x49, 0x0b, 0x02, 0xd2, 0x41, 0x6c, 0x01, 0x31, 0x41, 0x64, 0x0b, 0x48, 
 0x41, 0x6a, 0x01, 0x31, 0x41, 0x62, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 
-0x48, 0x62, 0x38, 0x6b, 0x00, 0xf0, 0xe2, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 
-0x9f, 0xf8, 0x01, 0x20, 0x04, 0x49, 0xc0, 0x46, 0xc8, 0x72, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x10, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x98, 0x19, 0x00, 0x80, 0xf8, 0xb5, 0x07, 0x1c, 0x00, 0x22, 0xf9, 0x1d, 
+0x48, 0x62, 0x38, 0x6b, 0x00, 0xf0, 0xf8, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 
+0xb3, 0xf8, 0x01, 0x20, 0x04, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
+0x18, 0x1a, 0x00, 0x80, 0xf8, 0xb5, 0x07, 0x1c, 0x00, 0x22, 0xf9, 0x1d, 
 0x61, 0x31, 0x0d, 0x1c, 0x78, 0x6a, 0xc0, 0x46, 0x00, 0x90, 0x40, 0x89, 
 0x03, 0x0c, 0x01, 0xd2, 0x40, 0x0a, 0x03, 0xd2, 0x38, 0x1c, 0xff, 0xf7, 
-0xc1, 0xff, 0x54, 0xe0, 0x2b, 0x48, 0x80, 0x6b, 0x00, 0x09, 0x1f, 0xd3, 
-0x08, 0x78, 0x40, 0x08, 0x1c, 0xd2, 0x00, 0x20, 0x43, 0x00, 0xcc, 0x5a, 
-0x27, 0x4e, 0x9e, 0x19, 0x65, 0x23, 0x5b, 0x01, 0xf3, 0x18, 0x9b, 0x8b, 
-0x9c, 0x42, 0x0e, 0xd0, 0xb8, 0x69, 0x39, 0x6b, 0xc0, 0x46, 0x88, 0x61, 
-0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
-0x13, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x60, 0xf8, 0x33, 0xe0, 0x01, 0x30, 
-0x03, 0x28, 0xe3, 0xd3, 0x1a, 0x48, 0x0b, 0x23, 0x1b, 0x02, 0xc1, 0x18, 
-0x09, 0x69, 0x00, 0x29, 0x24, 0xd0, 0x7d, 0x63, 0x00, 0x99, 0x49, 0x89, 
-0x09, 0x0c, 0x1f, 0xd2, 0x00, 0x24, 0x2d, 0x23, 
-0x9b, 0x01, 0xc1, 0x18, 0x89, 0x6b, 0x00, 0x29, 0x18, 0xd0, 0x05, 0x1c, 
-0xfe, 0x1d, 0x2d, 0x36, 0xa2, 0x00, 0x52, 0x19, 0x2d, 0x23, 0x9b, 0x01, 
-0xd2, 0x18, 0x92, 0x6b, 0x38, 0x1c, 0x31, 0x1c, 0x02, 0xf0, 0x7e, 0xfc, 
-0x01, 0x28, 0x0e, 0xd0, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 0x2d, 0x23, 
-0x9b, 0x01, 0xc0, 0x18, 0x80, 0x6b, 0x00, 0x28, 0xea, 0xd1, 0x01, 0xe0, 
-0x01, 0x2a, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0xf8, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x1a, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 
-0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x69, 0x39, 0x6b, 0xc0, 0x46, 0x88, 0x61, 
-0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 0x78, 0x6a, 0x40, 0x89, 
-0x01, 0x0c, 0x0e, 0xd2, 0x40, 0x0a, 0x0c, 0xd3, 0x38, 0x68, 0x40, 0x08, 
-0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x10, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 
-0xbb, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 0x02, 0xe0, 0x38, 0x1c, 
-0xff, 0xf7, 0x44, 0xff, 0x01, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x01, 0x21, 0x00, 0x6b, 0x40, 0x6a, 0xc0, 0x46, 0x01, 0x60, 0x70, 0x47, 
-0xb0, 0xb4, 0xc1, 0x1d, 0x39, 0x31, 0x09, 0x8b, 0x89, 0x08, 0x09, 0x04, 
-0x09, 0x0c, 0x84, 0x6a, 0xc2, 0x1d, 0x61, 0x32, 0x00, 0x20, 0x00, 0x29, 
-0x0c, 0xdd, 0x87, 0x00, 0x3d, 0x19, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 
-0x1b, 0x68, 0xc0, 0x46, 0xd3, 0x51, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 
-0x88, 0x42, 0xf2, 0xdb, 0xb0, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0xa0, 0xb0, 
-0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x21, 0x31, 0x19, 0x43, 0x09, 0x68, 
-0xc0, 0x46, 0x0b, 0x91, 0xc1, 0x1d, 0x53, 0x31, 0x19, 0x43, 0x1f, 0x91, 
-0x09, 0x68, 0x01, 0xaf, 0xfa, 0x1d, 0x39, 0x32, 0x1e, 0x92, 0x17, 0xab, 
-0x59, 0x80, 0x3a, 0x49, 0x01, 0x23, 0x9b, 0x07, 0x0a, 0x6a, 0x13, 0x43, 
-0xcc, 0x1d, 0x11, 0x34, 0x89, 0x69, 0x09, 0x03, 0x09, 0x0b, 0x22, 0x69, 
-0xe5, 0x68, 0xc0, 0x46, 0x1d, 0x95, 0xfc, 0x1d, 0x39, 0x34, 0x64, 0x8b, 
-0x64, 0x09, 0x05, 0x34, 0x24, 0x06, 0x24, 0x0e, 0x1c, 0x94, 0x56, 0x1a, 
-0x1b, 0x96, 0x1c, 0x9c, 0x2e, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x26, 
-0x1d, 0x9d, 0x1a, 0x68, 0x91, 0x42, 0x01, 0xd1, 0x32, 0x1c, 0x0b, 0xe0, 
-0x91, 0x42, 0x03, 0xd9, 0x52, 0x1b, 0x1b, 0x9e, 0xb5, 0x18, 0x00, 0xe0, 
-0x55, 0x1a, 0x01, 0x22, 0x24, 0x01, 0xac, 0x42, 0x00, 0xd3, 0x00, 0x22, 
-0x01, 0x2a, 0xe6, 0xd1, 0x91, 0x07, 0x01, 0x43, 0x09, 0x68, 0xc0, 0x46, 
-0x39, 0x60, 0x93, 0x07, 0x01, 0x1d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 
-0x79, 0x60, 0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 
-0xb9, 0x60, 0x1f, 0x99, 0x09, 0x68, 0x1e, 0x9a, 0xc0, 0x46, 0x51, 0x83, 
-0xc1, 0x1d, 0x1d, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x38, 0x63, 
-0x79, 0x62, 0xc1, 0x1d, 0x11, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 
-0xb9, 0x61, 0xc1, 0x1d, 0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 
-0xf9, 0x60, 0xc1, 0x1d, 0x17, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 
-0xf9, 0x83, 0x0e, 0x30, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x81, 
-0x38, 0x68, 0x40, 0x08, 0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x60, 0xfb, 
-0x38, 0x1c, 0x00, 0xf0, 0x0b, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0x58, 0xff, 
-0x20, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x28, 0x03, 0x00, 0x80, 
-0x55, 0x55, 0x55, 0x55, 0xf8, 0xb5, 0x07, 0x1c, 
-0xf8, 0x1d, 0x39, 0x30, 0x41, 0x8b, 0x38, 0x4a, 0x91, 0x42, 0x00, 0xdd, 
-0x42, 0x83, 0x42, 0x8b, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x20, 0x3a, 0x1d, 
-0x06, 0xca, 0xbb, 0x6a, 0x02, 0xf0, 0x12, 0xff, 0x32, 0x4a, 0xc0, 0x46, 
-0x00, 0x92, 0x32, 0x4e, 0x30, 0x6a, 0x32, 0x4c, 0xe1, 0x6d, 0x41, 0x18, 
-0x38, 0x6b, 0xc3, 0x1d, 0x05, 0x33, 0x01, 0x20, 0x72, 0x6a, 0x02, 0xf0, 
-0xff, 0xfe, 0xe0, 0x6d, 0x18, 0x30, 0xb1, 0x6a, 0x81, 0x42, 0x00, 0xd8, 
-0x00, 0x20, 0xe0, 0x65, 0x17, 0x23, 0xdb, 0x01, 0x20, 0x1c, 0xe1, 0x6d, 
-0xe4, 0x18, 0xe2, 0x6b, 0x92, 0x00, 0x27, 0x4b, 0xc0, 0x46, 0x99, 0x50, 
-0x26, 0x4d, 0xa8, 0x6b, 0x41, 0x08, 0x05, 0xd3, 0x40, 0x08, 0x40, 0x00, 
-0xa8, 0x63, 0x01, 0x20, 0x01, 0xf0, 0xd8, 0xff, 0x22, 0x4a, 0x1f, 0x48, 
-0x29, 0x7b, 0x00, 0x29, 0x02, 0xd0, 0x69, 0x7b, 0x00, 0x29, 0x00, 0xd1, 
-0x1f, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x05, 0x1c, 0xe0, 0x6b, 0x80, 0x00, 
-0x19, 0x4b, 0xc3, 0x18, 0x05, 0xce, 0xc1, 0x1d, 0x11, 0x31, 0x01, 0x20, 
-0x02, 0xf0, 0xce, 0xfe, 0xe0, 0x6b, 0x01, 0x30, 0xe0, 0x63, 0x17, 0x28, 
-0x01, 0xd3, 0x00, 0x20, 0xe0, 0x63, 0x00, 0x20, 0x39, 0x6b, 0xc0, 0x46, 
-0x08, 0x65, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62, 0x33, 0x23, 
-0x9b, 0x01, 0xe8, 0x18, 0x41, 0x68, 0x00, 0x29, 0x03, 0xd1, 0x39, 0x6b, 
-0xc0, 0x46, 0x41, 0x60, 0x04, 0xe0, 0x39, 0x6b, 0x82, 0x68, 0xc0, 0x46, 
-0x11, 0x65, 0x39, 0x6b, 0xc0, 0x46, 0x81, 0x60, 0xf8, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xea, 0x05, 0x00, 0x00, 0x18, 0x00, 0x14, 0x02, 
-0xf8, 0x28, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 0x44, 0x82, 0x20, 0x40, 
-0x68, 0x0e, 0x00, 0x80, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 
-0xf0, 0xb5, 0x11, 0x4e, 0xff, 0x25, 0x01, 0x35, 0x10, 0x4f, 0xc0, 0x46, 
-0x35, 0x60, 0x38, 0x69, 0x01, 0x38, 0x38, 0x61, 0x7c, 0x68, 0x00, 0x2c, 
-0x10, 0xd0, 0x20, 0x6d, 0xc0, 0x46, 0x78, 0x60, 0x20, 0x1c, 0x00, 0xf0, 
-0x21, 0xf8, 0x20, 0x1c, 0x00, 0xf0, 0x04, 0xfa, 0x08, 0x48, 0x80, 0x6a, 
-0x00, 0x0c, 0x00, 0x07, 0xe9, 0xd1, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x05, 0x48, 0xc1, 0x79, 0x01, 0x31, 0xc1, 0x71, 0xf7, 0xe7, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0xa8, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
-0xa0, 0x82, 0x20, 0x40, 0x01, 0x20, 0x80, 0x03, 0x01, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x70, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x90, 0xb5, 0x07, 0x1c, 
+0xc1, 0xff, 0x67, 0xe0, 0x35, 0x48, 0xc0, 0x6b, 
+0x00, 0x09, 0x1f, 0xd3, 0x08, 0x78, 0x40, 0x08, 0x1c, 0xd2, 0x00, 0x20, 
+0x43, 0x00, 0xcc, 0x5a, 0x31, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 
+0xf3, 0x18, 0x1b, 0x88, 0x9c, 0x42, 0x0e, 0xd0, 0xb8, 0x69, 0x39, 0x6b, 
+0xc0, 0x46, 0x88, 0x61, 0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 
+0x38, 0x1c, 0x00, 0xf0, 0x27, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x74, 0xf8, 
+0x46, 0xe0, 0x01, 0x30, 0x03, 0x28, 0xe3, 0xdb, 0x02, 0x20, 0x43, 0x00, 
+0x5c, 0x18, 0xe4, 0x88, 0x22, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 
+0xf3, 0x18, 0x1b, 0x88, 0x9c, 0x42, 0x03, 0xd1, 0x01, 0x23, 0x01, 0x38, 
+0xd8, 0x42, 0xf0, 0xdc, 0x01, 0x23, 0xd8, 0x42, 0xc4, 0xd0, 0x1b, 0x4e, 
+0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 0x40, 0x69, 0x00, 0x28, 0x24, 0xd0, 
+0x7d, 0x63, 0x00, 0x98, 0x40, 0x89, 0x00, 0x0c, 0x1f, 0xd2, 0x00, 0x24, 
+0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x6b, 0x35, 0x1c, 0x00, 0x28, 
+0x17, 0xd0, 0xfe, 0x1d, 0x2d, 0x36, 0xa2, 0x00, 0x52, 0x19, 0x2d, 0x23, 
+0x9b, 0x01, 0xd2, 0x18, 0xd2, 0x6b, 0x38, 0x1c, 0x31, 0x1c, 0x02, 0xf0, 
+0x7b, 0xfc, 0x01, 0x28, 0x0e, 0xd0, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 
+0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0xc0, 0x6b, 0x00, 0x28, 0xea, 0xd1, 
+0x01, 0xe0, 0x01, 0x2a, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 
+0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x69, 0x39, 0x6b, 
+0xc0, 0x46, 0x88, 0x61, 0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 
+0x78, 0x6a, 0x40, 0x89, 0x01, 0x0c, 0x0e, 0xd2, 0x40, 0x0a, 0x0c, 0xd3, 
+0x38, 0x68, 0x40, 0x08, 0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x0c, 0xfc, 
+0x38, 0x1c, 0x00, 0xf0, 0xbb, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 
+0x02, 0xe0, 0x38, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x01, 0x20, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x01, 0x21, 0x00, 0x6b, 0x40, 0x6a, 0xc0, 0x46, 
+0x01, 0x60, 0x70, 0x47, 0xb0, 0xb4, 0xc1, 0x1d, 0x39, 0x31, 0x09, 0x8b, 
+0x89, 0x08, 0x09, 0x04, 0x09, 0x0c, 0x84, 0x6a, 0xc2, 0x1d, 0x61, 0x32, 
+0x00, 0x20, 0x00, 0x29, 0x0c, 0xdd, 0x87, 0x00, 0x3d, 0x19, 0x01, 0x23, 
+0x9b, 0x07, 0x2b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xd3, 0x51, 0x01, 0x30, 
+0x00, 0x04, 0x00, 0x0c, 0x88, 0x42, 0xf2, 0xdb, 0xb0, 0xbc, 0x70, 0x47, 
+0xf0, 0xb5, 0xa0, 0xb0, 0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x21, 0x31, 
+0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x0b, 0x91, 0xc1, 0x1d, 0x53, 0x31, 
+0x19, 0x43, 0x1f, 0x91, 0x09, 0x68, 0x01, 0xaf, 0xfa, 0x1d, 0x39, 0x32, 
+0x1e, 0x92, 0x17, 0xab, 0x59, 0x80, 0x3a, 0x49, 0x01, 0x23, 0x9b, 0x07, 
+0x0a, 0x6a, 0x13, 0x43, 0xcc, 0x1d, 0x11, 0x34, 0x89, 0x69, 0x09, 0x03, 
+0x09, 0x0b, 0x22, 0x69, 0xe5, 0x68, 0xc0, 0x46, 0x1d, 0x95, 0xfc, 0x1d, 
+0x39, 0x34, 0x64, 0x8b, 0x64, 0x09, 0x05, 0x34, 0x24, 0x06, 0x24, 0x0e, 
+0x1c, 0x94, 0x56, 0x1a, 0x1b, 0x96, 0x1c, 0x9c, 0x2e, 0x4a, 0xc0, 0x46, 
+0x00, 0x92, 0x01, 0x26, 0x1d, 0x9d, 0x1a, 0x68, 0x91, 0x42, 0x01, 0xd1, 
+0x32, 0x1c, 0x0b, 0xe0, 0x91, 0x42, 0x03, 0xd9, 0x52, 0x1b, 0x1b, 0x9e, 
+0xb5, 0x18, 0x00, 0xe0, 0x55, 0x1a, 0x01, 0x22, 0x24, 0x01, 0xac, 0x42, 
+0x00, 0xd3, 0x00, 0x22, 0x01, 0x2a, 0xe6, 0xd1, 0x91, 0x07, 0x01, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x93, 0x07, 
+0x01, 0x1d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x79, 0x60, 0xc1, 0x1d, 
+0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0x1f, 0x99, 
+0x09, 0x68, 0x1e, 0x9a, 0xc0, 0x46, 0x51, 0x83, 0xc1, 0x1d, 0x1d, 0x31, 
+0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x38, 0x63, 0x79, 0x62, 0xc1, 0x1d, 
+0x11, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xb9, 0x61, 0xc1, 0x1d, 
+0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0xc1, 0x1d, 
+0x17, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xf9, 0x83, 0x0e, 0x30, 
+0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x81, 0x38, 0x68, 0x40, 0x08, 
+0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x5c, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 
+0x0b, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0x58, 0xff, 0x20, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xa8, 0x03, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 
+0xf8, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x39, 0x30, 0x41, 0x8b, 0x39, 0x4a, 
+0x91, 0x42, 0x00, 0xdd, 0x42, 0x83, 0x42, 0x8b, 0xc0, 0x46, 0x00, 0x92, 
+0x01, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0xbb, 0x6a, 0x02, 0xf0, 0x0e, 0xff, 
+0x33, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x33, 0x4e, 0x30, 0x6a, 0x33, 0x4c, 
+0xe1, 0x6d, 0x41, 0x18, 0x38, 0x6b, 0xc3, 0x1d, 0x05, 0x33, 0x01, 0x20, 
+0x72, 0x6a, 0x02, 0xf0, 0xfb, 0xfe, 0xe0, 0x6d, 0x18, 0x30, 0x00, 0x25, 
+0xb1, 0x6a, 0x81, 0x42, 0x01, 0xd8, 0xe5, 0x65, 0x00, 0xe0, 0xe0, 0x65, 
+0x2f, 0x23, 0x9b, 0x01, 0x20, 0x1c, 0xe1, 0x6d, 0xe4, 0x18, 0x22, 0x68, 
+0x92, 0x00, 0x27, 0x4b, 0xc0, 0x46, 0x99, 0x50, 0x26, 0x48, 0xc1, 0x6b, 
+0x4a, 0x08, 0x05, 0xd3, 0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 
+0x01, 0xf0, 0xd6, 0xff, 0x22, 0x4a, 0x1f, 0x48, 0xc1, 0x1d, 0x89, 0x31, 
+0x0b, 0x78, 0x00, 0x2b, 0x02, 0xd0, 0x49, 0x78, 0x00, 0x29, 0x00, 0xd1, 
+0x1e, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x20, 0x68, 0x80, 0x00, 0x19, 0x4b, 
+0xc3, 0x18, 0x05, 0xce, 0xc1, 0x1d, 0x11, 0x31, 0x01, 0x20, 0x02, 0xf0, 
+0xc7, 0xfe, 0x14, 0x48, 0x21, 0x68, 0x01, 0x31, 0x21, 0x60, 0x17, 0x29, 
+0x00, 0xd3, 0x25, 0x60, 0x39, 0x6b, 0xc0, 0x46, 0x0d, 0x65, 0x79, 0x6a, 
+0x3a, 0x6b, 0xc0, 0x46, 0x51, 0x62, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 
+0x81, 0x68, 0x00, 0x29, 0x03, 0xd1, 0x39, 0x6b, 0xc0, 0x46, 0x81, 0x60, 
+0x04, 0xe0, 0x39, 0x6b, 0xc2, 0x68, 0xc0, 0x46, 0x11, 0x65, 0x39, 0x6b, 
+0xc0, 0x46, 0xc1, 0x60, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xea, 0x05, 0x00, 0x00, 0x18, 0x00, 0x14, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0x44, 0x82, 0x20, 0x40, 0xe8, 0x0e, 0x00, 0x80, 
+0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0xf0, 0xb5, 0x11, 0x4e, 
+0xff, 0x25, 0x01, 0x35, 0x10, 0x4f, 0xc0, 0x46, 0x35, 0x60, 0x78, 0x69, 
+0x01, 0x38, 0x78, 0x61, 0xbc, 0x68, 0x00, 0x2c, 0x10, 0xd0, 0x20, 0x6d, 
+0xc0, 0x46, 0xb8, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x20, 0x1c, 
+0x00, 0xf0, 0x04, 0xfa, 0x08, 0x48, 0x80, 0x6a, 0x00, 0x0c, 0x00, 0x07, 
+0xe9, 0xd1, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x05, 0x48, 0xc1, 0x79, 
+0x01, 0x31, 0xc1, 0x71, 0xf7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x28, 0x1b, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0xa0, 0x82, 0x20, 0x40, 
+0x01, 0x20, 0x80, 0x03, 0x01, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x70, 0x47, 
+0x00, 0x00, 0x00, 0xb0, 0x90, 0xb5, 0x07, 0x1c, 
 0x38, 0x68, 0xc0, 0x08, 0x09, 0xd3, 0x1d, 0x48, 0x01, 0x6a, 0x01, 0x39, 
 0x01, 0x62, 0x20, 0x30, 0x00, 0x79, 0x00, 0x28, 0x01, 0xd0, 0xfe, 0xf7, 
-0x09, 0xfe, 0x01, 0x23, 0x9b, 0x07, 0xf8, 0x1d, 0x1d, 0x30, 0x18, 0x43, 
-0x00, 0x68, 0x16, 0x4c, 0x21, 0x6a, 0x81, 0x42, 0x21, 0xd1, 0x01, 0x1c, 
+0xf3, 0xfd, 0x01, 0x23, 0x9b, 0x07, 0xf8, 0x1d, 0x1d, 0x30, 0x18, 0x43, 
+0x00, 0x68, 0x16, 0x4c, 0x61, 0x6a, 0x81, 0x42, 0x21, 0xd1, 0x01, 0x1c, 
 0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x01, 0x29, 0x1a, 0xd1, 
-0x00, 0xf0, 0x22, 0xf8, 0x20, 0x62, 0x20, 0x6a, 0xe1, 0x69, 0x88, 0x42, 
+0x00, 0xf0, 0x22, 0xf8, 0x60, 0x62, 0x60, 0x6a, 0x21, 0x6a, 0x88, 0x42, 
 0x05, 0xd0, 0x01, 0x21, 0x89, 0x07, 0x01, 0x43, 0x09, 0x68, 0x09, 0x04, 
-0xf2, 0xd0, 0x51, 0x21, 0x89, 0x03, 0x22, 0x6a, 0xe3, 0x6a, 0x9a, 0x42, 
-0x02, 0xd1, 0x20, 0x6b, 0x62, 0x6b, 0x80, 0x1a, 0x04, 0x38, 0xc8, 0x60, 
+0xf2, 0xd0, 0x51, 0x21, 0x89, 0x03, 0x62, 0x6a, 0x23, 0x6b, 0x9a, 0x42, 
+0x02, 0xd1, 0x60, 0x6b, 0xa2, 0x6b, 0x80, 0x1a, 0x04, 0x38, 0xc8, 0x60, 
 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x79, 0x6a, 0xc0, 0x46, 
-0x08, 0x60, 0xf7, 0xe7, 0xec, 0x05, 0x00, 0x80, 0x68, 0x1a, 0x00, 0x80, 
-0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x01, 0x31, 
-0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x08, 0x18, 0x0d, 0x30, 
-0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x04, 0x49, 
-0x4a, 0x6b, 0x12, 0x18, 0x0b, 0x6b, 0x9a, 0x42, 0x00, 0xd9, 0xc8, 0x6a, 
-0x70, 0x47, 0x00, 0x00, 0x68, 0x1a, 0x00, 0x80, 0x00, 0xb5, 0x04, 0x48, 
-0x80, 0x68, 0x10, 0x28, 0x01, 0xd3, 0x00, 0xf0, 0x05, 0xf8, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x68, 0x1a, 0x00, 0x80, 0x88, 0xb5, 0x0c, 0x4f, 
-0x38, 0x78, 0x00, 0x28, 0x11, 0xd1, 0x0b, 0x49, 0x10, 0x20, 0x02, 0xf0, 
-0xfb, 0xfd, 0x00, 0x28, 0x0b, 0xd0, 0x01, 0x20, 0x38, 0x70, 0x08, 0x4a, 
-0xc0, 0x46, 0x00, 0x92, 0x07, 0x48, 0x42, 0x68, 0x07, 0x4b, 0x01, 0x68, 
-0x00, 0x20, 0x02, 0xf0, 0xe5, 0xfd, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x78, 0x1a, 0x00, 0x80, 0x69, 0x2c, 0xff, 0xff, 0x10, 0x00, 0x35, 0x02, 
-0xf8, 0x28, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x90, 0xb5, 0x01, 0x20, 
-0x40, 0x02, 0x10, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4f, 0x10, 0x21, 
-0xf8, 0x1d, 0x3d, 0x30, 0x02, 0xf0, 0x52, 0xfc, 0x19, 0x23, 0xdb, 0x01, 
-0xfc, 0x18, 0xa0, 0x68, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x14, 0xf8, 
-0x00, 0x20, 0xc9, 0x23, 0x1b, 0x01, 0xf9, 0x18, 0x08, 0x70, 0xa0, 0x68, 
-0x10, 0x28, 0x04, 0xd3, 0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xf9, 0x18, 
-0x48, 0x72, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
-0xe8, 0x0d, 0x00, 0x80, 0xf8, 0xb5, 0x37, 0x48, 0x19, 0x23, 0xdb, 0x01, 
-0xc1, 0x18, 0x89, 0x68, 0x35, 0x4d, 0x10, 0x29, 0x00, 0xd9, 0x10, 0x21, 
-0x29, 0x62, 0x32, 0x48, 0xc1, 0x6c, 0x00, 0x6e, 0x81, 0x42, 0x07, 0xd9, 
-0x08, 0x1a, 0x07, 0x09, 0x00, 0x24, 0x28, 0x6a, 0xb8, 0x42, 0x12, 0xd2, 
-0x07, 0x1c, 0x10, 0xe0, 0x81, 0x42, 0x2a, 0xd2, 0x2c, 0x4a, 0x52, 0x6b, 
-0x10, 0x1a, 0x07, 0x09, 0x28, 0x6a, 0xb8, 0x42, 0x05, 0xd9, 0x0c, 0x09, 
-0x39, 0x19, 0x88, 0x42, 0x03, 0xd2, 0xc4, 0x1b, 0x01, 0xe0, 0x00, 0x24, 
-0x07, 0x1c, 0x3e, 0x19, 0x30, 0x01, 0x25, 0x49, 0x02, 0xf0, 0x8a, 0xfd, 
-0x00, 0x28, 0x3d, 0xd0, 0x23, 0x48, 0x00, 0x2c, 0x1a, 0xd1, 0x1e, 0x49, 
-0x3a, 0x01, 0x2f, 0x62, 0x09, 0x6e, 0x8c, 0x18, 0x1d, 0x4d, 0x6b, 0x6b, 
-0xa3, 0x42, 0x00, 0xd8, 0xe4, 0x1a, 0x1e, 0x4b, 0x1a, 0x43, 0x00, 0x92, 
-0xea, 0x6a, 0x51, 0x18, 0x2a, 0x6b, 0x03, 0x1c, 0x20, 0xe0, 0x1b, 0x48, 
-0x01, 0x6b, 0x01, 0x31, 0x01, 0x63, 0x00, 0x20, 0x28, 0x62, 0xf8, 0xbc, 
+0x08, 0x60, 0xf7, 0xe7, 0x6c, 0x06, 0x00, 0x80, 0xe8, 0x1a, 0x00, 0x80, 
+0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 
+0x09, 0x04, 0x09, 0x0c, 0x08, 0x18, 0x0d, 0x30, 0x81, 0x07, 0x02, 0xd0, 
+0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x04, 0x49, 0x8a, 0x6b, 0x12, 0x18, 
+0x4b, 0x6b, 0x9a, 0x42, 0x00, 0xd9, 0x08, 0x6b, 0x70, 0x47, 0x00, 0x00, 
+0xe8, 0x1a, 0x00, 0x80, 0x00, 0xb5, 0x04, 0x48, 0xc0, 0x68, 0x10, 0x28, 
+0x01, 0xd3, 0x00, 0xf0, 0x05, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xe8, 0x1a, 0x00, 0x80, 0x88, 0xb5, 0x0c, 0x4f, 0x38, 0x79, 0x00, 0x28, 
+0x11, 0xd1, 0x0b, 0x49, 0x10, 0x20, 0x02, 0xf0, 0xf5, 0xfd, 0x00, 0x28, 
+0x0b, 0xd0, 0x01, 0x20, 0x38, 0x71, 0x08, 0x4a, 0xc0, 0x46, 0x00, 0x92, 
+0x07, 0x48, 0x42, 0x68, 0x07, 0x4b, 0x01, 0x68, 0x00, 0x20, 0x02, 0xf0, 
+0xdf, 0xfd, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf8, 0x1a, 0x00, 0x80, 
+0xe1, 0x2c, 0xff, 0xff, 0x10, 0x00, 0x35, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0x44, 0x80, 0x20, 0x40, 0x90, 0xb5, 0x01, 0x20, 0x40, 0x02, 0x10, 0x49, 
+0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4f, 0x10, 0x21, 0xf8, 0x1d, 0x3d, 0x30, 
+0x02, 0xf0, 0x4c, 0xfc, 0x19, 0x23, 0xdb, 0x01, 0xfc, 0x18, 0xe0, 0x68, 
+0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x14, 0xf8, 0x00, 0x20, 0xc9, 0x23, 
+0x1b, 0x01, 0xf9, 0x18, 0x08, 0x71, 0xe0, 0x68, 0x10, 0x28, 0x04, 0xd3, 
+0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xf9, 0x18, 0x48, 0x73, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
+0xf8, 0xb5, 0x37, 0x48, 0x19, 0x23, 0xdb, 0x01, 0xc1, 0x18, 0xc9, 0x68, 
+0x35, 0x4d, 0x10, 0x29, 0x00, 0xd9, 0x10, 0x21, 0x69, 0x62, 0x32, 0x48, 
+0xc1, 0x6c, 0x00, 0x6e, 0x81, 0x42, 0x07, 0xd9, 0x08, 0x1a, 0x07, 0x09, 
+0x00, 0x24, 0x68, 0x6a, 0xb8, 0x42, 0x12, 0xd2, 0x07, 0x1c, 0x10, 0xe0, 
+0x81, 0x42, 0x2a, 0xd2, 0x2c, 0x4a, 0x52, 0x6b, 0x10, 0x1a, 0x07, 0x09, 
+0x68, 0x6a, 0xb8, 0x42, 0x05, 0xd9, 0x0c, 0x09, 0x39, 0x19, 0x88, 0x42, 
+0x03, 0xd2, 0xc4, 0x1b, 0x01, 0xe0, 0x00, 0x24, 0x07, 0x1c, 0x3e, 0x19, 
+0x30, 0x01, 0x25, 0x49, 0x02, 0xf0, 0x84, 0xfd, 0x00, 0x28, 0x3d, 0xd0, 
+0x23, 0x48, 0x00, 0x2c, 0x1a, 0xd1, 0x1e, 0x49, 0x3a, 0x01, 0x6f, 0x62, 
+0x09, 0x6e, 0x8c, 0x18, 0x1d, 0x4d, 0x6b, 0x6b, 0xa3, 0x42, 0x00, 0xd8, 
+0xe4, 0x1a, 0x1e, 0x4b, 0x1a, 0x43, 0x00, 0x92, 0xea, 0x6a, 0x51, 0x18, 
+0x2a, 0x6b, 0x03, 0x1c, 0x20, 0xe0, 0x1b, 0x48, 0x01, 0x6b, 0x01, 0x31, 
+0x01, 0x63, 0x00, 0x20, 0x68, 0x62, 0xf8, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x10, 0x49, 0x24, 0x01, 0x3f, 0x01, 0x11, 0x22, 
-0x52, 0x05, 0x3a, 0x43, 0x2e, 0x62, 0x00, 0x92, 0x0e, 0x4d, 0xea, 0x6a, 
+0x52, 0x05, 0x3a, 0x43, 0x6e, 0x62, 0x00, 0x92, 0x0e, 0x4d, 0xea, 0x6a, 
 0x09, 0x6e, 0x51, 0x18, 0x03, 0x1c, 0x06, 0x1c, 0x00, 0x20, 0x2a, 0x6b, 
-0x02, 0xf0, 0x50, 0xfd, 0x0c, 0x4a, 0x22, 0x43, 0x00, 0x92, 0xbb, 0x19, 
-0xe9, 0x6a, 0x2a, 0x6b, 0x00, 0x20, 0x02, 0xf0, 0x47, 0xfd, 0x03, 0x48, 
+0x02, 0xf0, 0x4a, 0xfd, 0x0c, 0x4a, 0x22, 0x43, 0x00, 0x92, 0xbb, 0x19, 
+0xe9, 0x6a, 0x2a, 0x6b, 0x00, 0x20, 0x02, 0xf0, 0x41, 0xfd, 0x03, 0x48, 
 0xc0, 0x46, 0x04, 0x66, 0x00, 0xf0, 0x10, 0xf8, 0x01, 0x20, 0xda, 0xe7, 
-0xe8, 0x0d, 0x00, 0x80, 0xa8, 0x1a, 0x00, 0x80, 0xf8, 0x28, 0x00, 0x80, 
-0xd1, 0x2d, 0xff, 0xff, 0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x36, 0x02, 
+0x68, 0x0e, 0x00, 0x80, 0x28, 0x1b, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 
+0x49, 0x2e, 0xff, 0xff, 0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x36, 0x02, 
 0xa0, 0x82, 0x20, 0x40, 0x04, 0x48, 0x01, 0x6e, 0x04, 0x4a, 0x80, 0x30, 
-0xd1, 0x60, 0x02, 0x23, 0x81, 0x6b, 0x19, 0x43, 0x81, 0x63, 0x70, 0x47, 
-0xe8, 0x0d, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 
-0x01, 0x20, 0x80, 0x02, 0x1c, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x00, 0x27, 0x1b, 0x4e, 0x33, 0x23, 0x9b, 0x01, 0xf5, 0x18, 
-0x28, 0x6a, 0x00, 0x28, 0x1d, 0xd9, 0x19, 0x4c, 0x68, 0x46, 0x10, 0x21, 
-0x02, 0xf0, 0x96, 0xfb, 0x68, 0x46, 0x00, 0xf0, 0x33, 0xf8, 0x00, 0x28, 
-0x04, 0xd0, 0x15, 0x49, 0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x0a, 0xe0, 
-0x13, 0x49, 0x60, 0x7b, 0x01, 0x30, 0x60, 0x73, 0x88, 0x79, 0x01, 0x30, 
-0x88, 0x71, 0x11, 0x48, 0x00, 0x68, 0x02, 0xf0, 0x6b, 0xf9, 0x28, 0x6a, 
-0x01, 0x37, 0xb8, 0x42, 0xe2, 0xd8, 0xbb, 0x23, 0x1b, 0x01, 0xf0, 0x18, 
-0x81, 0x7a, 0x00, 0x29, 0x03, 0xd0, 0x00, 0x21, 0x81, 0x72, 0xff, 0xf7, 
-0x1d, 0xfb, 0xff, 0xf7, 0xe3, 0xfe, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xe8, 0x0d, 0x00, 0x80, 
-0xb0, 0x82, 0x20, 0x40, 0x08, 0x83, 0x20, 0x40, 0xa0, 0x82, 0x20, 0x40, 
-0xd8, 0x03, 0x00, 0x80, 0x90, 0xb4, 0x17, 0x4f, 0x19, 0x23, 0xdb, 0x01, 
-0xf9, 0x18, 0x00, 0x22, 0x8b, 0x68, 0x00, 0x2b, 0x23, 0xd0, 0x01, 0x3b, 
-0x8b, 0x60, 0x33, 0x23, 0x9b, 0x01, 0xff, 0x18, 0x7b, 0x69, 0x1c, 0x6d, 
-0xc0, 0x46, 0x7c, 0x61, 0x04, 0x68, 0xc0, 0x46, 0x5c, 0x60, 0x44, 0x68, 
-0xc0, 0x46, 0x9c, 0x60, 0x84, 0x68, 0xc0, 0x46, 0x1c, 0x61, 0xc0, 0x68, 
-0xc0, 0x46, 0x58, 0x61, 0x1a, 0x65, 0xc8, 0x68, 0x42, 0x1c, 0xca, 0x60, 
-0x00, 0x28, 0x03, 0xd0, 0xf8, 0x69, 0xc0, 0x46, 0x03, 0x65, 0x00, 0xe0, 
-0xbb, 0x61, 0xfb, 0x61, 0x18, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0x10, 0x1c, 
-0xfb, 0xe7, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0x0a, 0x4a, 0x33, 0x23, 
-0x9b, 0x01, 0xd1, 0x18, 0x88, 0x69, 0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 
-0xd3, 0x68, 0x00, 0x2b, 0x06, 0xd0, 0x01, 0x3b, 0xd3, 0x60, 0x8a, 0x69, 
-0x12, 0x6d, 0xc0, 0x46, 0x8a, 0x61, 0x70, 0x47, 0x00, 0x21, 0xd1, 0x60, 
-0xfb, 0xe7, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0x06, 0x4a, 0xd1, 0x68, 
-0x4b, 0x1c, 0xd3, 0x60, 0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0x91, 0x69, 
-0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0x90, 0x61, 0x70, 0x47, 0x00, 0x00, 
-0x68, 0x1a, 0x00, 0x80, 0x06, 0x4a, 0x91, 0x68, 0x4b, 0x1c, 0x93, 0x60, 
-0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0x51, 0x69, 0x00, 0xe0, 0x00, 0x21, 
-0x01, 0x65, 0x50, 0x61, 0x70, 0x47, 0x00, 0x00, 0x68, 0x1a, 0x00, 0x80, 
-0x90, 0xb4, 0x00, 0x21, 0x0f, 0x4a, 0x97, 0x89, 0x92, 0x6a, 0x4b, 0x00, 
-0x1b, 0x18, 0x9b, 0x8a, 0x00, 0x2b, 0x12, 0xd0, 0xbb, 0x42, 0x10, 0xdc, 
+0xd1, 0x60, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x70, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 
+0x01, 0x20, 0x80, 0x02, 0x1c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0x27, 
+0x1b, 0x4e, 0x33, 0x23, 0x9b, 0x01, 0xf5, 0x18, 0x68, 0x6a, 0x00, 0x28, 
+0x1d, 0xd9, 0x19, 0x4c, 0x68, 0x46, 0x10, 0x21, 0x02, 0xf0, 0x90, 0xfb, 
+0x68, 0x46, 0x00, 0xf0, 0x33, 0xf8, 0x00, 0x28, 0x04, 0xd0, 0x15, 0x49, 
+0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x0a, 0xe0, 0x13, 0x49, 0x60, 0x7b, 
+0x01, 0x30, 0x60, 0x73, 0x88, 0x79, 0x01, 0x30, 0x88, 0x71, 0x11, 0x48, 
+0x00, 0x68, 0x02, 0xf0, 0x65, 0xf9, 0x68, 0x6a, 0x01, 0x37, 0xb8, 0x42, 
+0xe2, 0xd8, 0xbb, 0x23, 0x1b, 0x01, 0xf0, 0x18, 0x81, 0x7b, 0x00, 0x29, 
+0x03, 0xd0, 0x00, 0x21, 0x81, 0x73, 0xff, 0xf7, 0x05, 0xfb, 0xff, 0xf7, 
+0xe3, 0xfe, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0xb0, 0x82, 0x20, 0x40, 
+0x08, 0x83, 0x20, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x58, 0x04, 0x00, 0x80, 
+0x90, 0xb4, 0x17, 0x4f, 0x19, 0x23, 0xdb, 0x01, 0xf9, 0x18, 0x00, 0x22, 
+0xcb, 0x68, 0x00, 0x2b, 0x23, 0xd0, 0x01, 0x3b, 0xcb, 0x60, 0x33, 0x23, 
+0x9b, 0x01, 0xff, 0x18, 0xbb, 0x69, 0x1c, 0x6d, 0xc0, 0x46, 0xbc, 0x61, 
+0x04, 0x68, 0xc0, 0x46, 0x5c, 0x60, 0x44, 0x68, 0xc0, 0x46, 0x9c, 0x60, 
+0x84, 0x68, 0xc0, 0x46, 0x1c, 0x61, 0xc0, 0x68, 0xc0, 0x46, 0x58, 0x61, 
+0x1a, 0x65, 0x08, 0x69, 0x42, 0x1c, 0x0a, 0x61, 0x00, 0x28, 0x03, 0xd0, 
+0x38, 0x6a, 0xc0, 0x46, 0x03, 0x65, 0x00, 0xe0, 0xfb, 0x61, 0x3b, 0x62, 
+0x18, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0x10, 0x1c, 0xfb, 0xe7, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x0a, 0x4a, 0x33, 0x23, 0x9b, 0x01, 0xd1, 0x18, 
+0xc8, 0x69, 0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 0x13, 0x69, 0x00, 0x2b, 
+0x06, 0xd0, 0x01, 0x3b, 0x13, 0x61, 0xca, 0x69, 0x12, 0x6d, 0xc0, 0x46, 
+0xca, 0x61, 0x70, 0x47, 0x00, 0x21, 0x11, 0x61, 0xfb, 0xe7, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x06, 0x4a, 0x11, 0x69, 0x4b, 0x1c, 0x13, 0x61, 
+0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0xd1, 0x69, 0x00, 0xe0, 0x00, 0x21, 
+0x01, 0x65, 0xd0, 0x61, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 
+0x06, 0x4a, 0xd1, 0x68, 0x4b, 0x1c, 0xd3, 0x60, 0x40, 0x32, 0x00, 0x29, 
+0x01, 0xd0, 0x91, 0x69, 0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0x90, 0x61, 
+0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21, 
+0x0f, 0x4a, 0x97, 0x89, 0x92, 0x6a, 0x4b, 0x00, 0x1b, 0x18, 0x9b, 0x8a, 
+0x00, 0x2b, 0x12, 0xd0, 0xbb, 0x42, 0x10, 0xdc, 
 0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 0xd3, 0x18, 0xdc, 0x1f, 0x49, 0x3c, 
 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 
 0x03, 0x2b, 0x02, 0xd0, 0x00, 0x20, 0x90, 0xbc, 0x70, 0x47, 0x01, 0x31, 
-0x04, 0x29, 0xe4, 0xd3, 0x01, 0x20, 0xf8, 0xe7, 0xc8, 0x29, 0x00, 0x80, 
+0x04, 0x29, 0xe4, 0xd3, 0x01, 0x20, 0xf8, 0xe7, 0x4c, 0x2a, 0x00, 0x80, 
 0xf7, 0xb5, 0x86, 0xb0, 0x3d, 0x4a, 0x07, 0x1c, 0xd1, 0x69, 0x8f, 0x40, 
 0x03, 0x1c, 0x14, 0x6a, 0xe3, 0x40, 0x5f, 0x40, 0x07, 0x9e, 0x8e, 0x40, 
 0x77, 0x40, 0xcf, 0x40, 0x94, 0x69, 0xc0, 0x46, 0x05, 0x94, 0x03, 0x1c, 
@@ -1062,85 +1075,85 @@ const u8 typhoon_firmware_image[] = {
 0x5d, 0xd9, 0x1c, 0x1c, 0x32, 0x4e, 0x26, 0x43, 0x94, 0x69, 0xe6, 0x40, 
 0x33, 0x1c, 0x03, 0x96, 0x53, 0x6a, 0xc0, 0x46, 0x02, 0x93, 0xd2, 0x6a, 
 0xc0, 0x46, 0x01, 0x92, 0xbb, 0x00, 0x02, 0x9a, 0xd2, 0x58, 0x13, 0x1c, 
-0x05, 0x9c, 0xe3, 0x40, 0x03, 0x9c, 0xa3, 0x42, 
-0x3e, 0xd1, 0x8a, 0x40, 0xca, 0x40, 0x14, 0x1c, 0x63, 0x00, 0x1b, 0x19, 
-0x5b, 0x01, 0x01, 0x9a, 0xd2, 0x18, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 
-0x01, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 0x03, 0x2b, 
-0x2c, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x51, 0x36, 0x33, 0x43, 
-0x1b, 0x68, 0x07, 0x9e, 0x1e, 0x40, 0x00, 0x96, 0x01, 0x23, 0x9b, 0x07, 
-0xd6, 0x1d, 0x49, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x83, 0x42, 0x1b, 0xd1, 
-0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x4d, 0x36, 0x33, 0x43, 0x1b, 0x68, 
-0x00, 0x9e, 0xb3, 0x42, 0x12, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0x1a, 0x43, 
-0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x08, 0x9b, 0x32, 0x2b, 0x04, 0xd1, 
-0x02, 0x2a, 0x07, 0xd1, 0x20, 0x04, 0x00, 0x14, 0x0f, 0xe0, 0x08, 0x9b, 
-0x33, 0x2b, 0x01, 0xd1, 0x01, 0x2a, 0xf7, 0xd0, 0x04, 0x9a, 0x01, 0x37, 
-0x97, 0x42, 0x00, 0xd3, 0x00, 0x27, 0x04, 0x9a, 0x01, 0x35, 0xaa, 0x42, 
-0xae, 0xd8, 0x00, 0x20, 0xc0, 0x43, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xc8, 0x29, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
-0xf0, 0xb5, 0x27, 0x4d, 0x68, 0x69, 0x00, 0x28, 0x06, 0xd0, 0x26, 0x48, 
-0x00, 0x68, 0x02, 0xf0, 0x31, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x23, 0x4c, 0x00, 0x26, 0xa0, 0x68, 0x23, 0x4f, 0x00, 0x28, 0x16, 0xd0, 
-0x0f, 0xe0, 0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 
-0x0f, 0xe0, 0xa6, 0x60, 0xfd, 0xf7, 0x08, 0xff, 0x00, 0x28, 0xea, 0xd1, 
-0x28, 0x6a, 0x02, 0x28, 0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 
-0x00, 0x28, 0x02, 0xd0, 0x38, 0x79, 0x00, 0x28, 0xe9, 0xd0, 0x68, 0x68, 
-0x00, 0x28, 0x1b, 0xd0, 0x01, 0x20, 0xa0, 0x60, 0xfe, 0xf7, 0xd2, 0xfb, 
-0x00, 0x28, 0xd6, 0xd1, 0x68, 0x68, 0x00, 0x28, 0xf6, 0xd1, 0x11, 0xe0, 
-0x00, 0x28, 0xd0, 0xd1, 0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 
-0x38, 0x71, 0xca, 0xe7, 0xa6, 0x60, 0xfd, 0xf7, 0xe3, 0xfe, 0x00, 0x28, 
-0xc5, 0xd1, 0x28, 0x6a, 0x02, 0x28, 0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 
-0xe8, 0x68, 0x00, 0x28, 0xbd, 0xd0, 0x38, 0x79, 0x00, 0x28, 0xe7, 0xd0, 
-0xb9, 0xe7, 0x00, 0x00, 0xec, 0x05, 0x00, 0x80, 0xdc, 0x03, 0x00, 0x80, 
-0xc8, 0x29, 0x00, 0x80, 0x0c, 0x06, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 
-0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x40, 0x20, 
-0x1d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x01, 0xf0, 0x9f, 0xfc, 0x03, 0x23, 
+0x05, 0x9c, 0xe3, 0x40, 0x03, 0x9c, 0xa3, 0x42, 0x3e, 0xd1, 0x8a, 0x40, 
+0xca, 0x40, 0x14, 0x1c, 0x63, 0x00, 0x1b, 0x19, 0x5b, 0x01, 0x01, 0x9a, 
+0xd2, 0x18, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x01, 0x36, 0x33, 0x43, 
+0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 0x03, 0x2b, 0x2c, 0xd1, 0x01, 0x23, 
+0x9b, 0x07, 0xd6, 0x1d, 0x51, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x07, 0x9e, 
+0x1e, 0x40, 0x00, 0x96, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x49, 0x36, 
+0x33, 0x43, 0x1b, 0x68, 0x83, 0x42, 0x1b, 0xd1, 0x01, 0x23, 0x9b, 0x07, 
+0xd6, 0x1d, 0x4d, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0xb3, 0x42, 
+0x12, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 
+0x12, 0x0c, 0x08, 0x9b, 0x32, 0x2b, 0x04, 0xd1, 0x02, 0x2a, 0x07, 0xd1, 
+0x20, 0x04, 0x00, 0x14, 0x0f, 0xe0, 0x08, 0x9b, 0x33, 0x2b, 0x01, 0xd1, 
+0x01, 0x2a, 0xf7, 0xd0, 0x04, 0x9a, 0x01, 0x37, 0x97, 0x42, 0x00, 0xd3, 
+0x00, 0x27, 0x04, 0x9a, 0x01, 0x35, 0xaa, 0x42, 0xae, 0xd8, 0x00, 0x20, 
+0xc0, 0x43, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x27, 0x4d, 
+0x68, 0x69, 0x00, 0x28, 0x06, 0xd0, 0x26, 0x48, 0x00, 0x68, 0x02, 0xf0, 
+0x2b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x23, 0x4c, 0x00, 0x26, 
+0xa0, 0x68, 0x23, 0x4f, 0x00, 0x28, 0x16, 0xd0, 0x0f, 0xe0, 0x28, 0x6a, 
+0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0x0f, 0xe0, 0xa6, 0x60, 
+0xfd, 0xf7, 0xe8, 0xfe, 0x00, 0x28, 0xea, 0xd1, 0x28, 0x6a, 0x02, 0x28, 
+0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0x02, 0xd0, 
+0x38, 0x79, 0x00, 0x28, 0xe9, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x1b, 0xd0, 
+0x01, 0x20, 0xa0, 0x60, 0xfe, 0xf7, 0xbc, 0xfb, 0x00, 0x28, 0xd6, 0xd1, 
+0x68, 0x68, 0x00, 0x28, 0xf6, 0xd1, 0x11, 0xe0, 0x00, 0x28, 0xd0, 0xd1, 
+0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xca, 0xe7, 
+0xa6, 0x60, 0xfd, 0xf7, 0xc3, 0xfe, 0x00, 0x28, 0xc5, 0xd1, 0x28, 0x6a, 
+0x02, 0x28, 0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 
+0xbd, 0xd0, 0x38, 0x79, 0x00, 0x28, 0xe7, 0xd0, 0xb9, 0xe7, 0x00, 0x00, 
+0x6c, 0x06, 0x00, 0x80, 0x5c, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 
+0x8c, 0x06, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
+0x70, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x40, 0x20, 0x1d, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0x01, 0xf0, 0x9d, 0xfc, 0x03, 0x23, 
 0x1b, 0x07, 0x41, 0x68, 0x19, 0x40, 0x0c, 0x0f, 0x61, 0x01, 0x09, 0x1b, 
 0x89, 0x00, 0x18, 0x4a, 0x8f, 0x18, 0x01, 0x21, 0x39, 0x80, 0x81, 0x6a, 
 0xc0, 0x46, 0x79, 0x65, 0x41, 0x6a, 0xc0, 0x46, 0x79, 0x67, 0xb9, 0x6c, 
 0xfa, 0x6c, 0x89, 0x18, 0xb9, 0x64, 0x00, 0x21, 0xf9, 0x64, 0xba, 0x6b, 
 0x3b, 0x6d, 0xd2, 0x18, 0xba, 0x63, 0x39, 0x65, 0x42, 0x6a, 0x20, 0x32, 
 0x51, 0x71, 0x79, 0x6d, 0x7a, 0x6f, 0xd2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 
-0xfd, 0xf7, 0x10, 0xf8, 0x20, 0x01, 0x09, 0x49, 0x40, 0x18, 0x19, 0x23, 
+0xfc, 0xf7, 0xd4, 0xff, 0x20, 0x01, 0x09, 0x49, 0x40, 0x18, 0x19, 0x23, 
 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0x78, 0x6f, 
-0x01, 0xf0, 0xc8, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0xc8, 0x2a, 0x00, 0x80, 0x1c, 0x1c, 0x00, 0x80, 
+0x01, 0xf0, 0xc6, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 
 0xf0, 0xb5, 0x40, 0x20, 0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x01, 0xf0, 
-0x5b, 0xfc, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 
-0x1b, 0x07, 0x18, 0x40, 0x06, 0x0f, 0x70, 0x01, 0x80, 0x1b, 0x80, 0x00, 
-0x0c, 0x49, 0x44, 0x18, 0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65, 0x78, 0x6a, 
-0xc0, 0x46, 0x60, 0x67, 0x80, 0x6f, 0x05, 0x1d, 0xe5, 0x63, 0xb9, 0x69, 
-0x28, 0x1c, 0x02, 0xf0, 0x8f, 0xf9, 0x38, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 
-0x2b, 0x1c, 0x00, 0xf0, 0x20, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x00, 0x00, 0xb0, 0xc8, 0x2a, 0x00, 0x80, 0xf0, 0xb5, 0x4b, 0x6f, 
-0x9b, 0x6f, 0x1f, 0x1d, 0xcf, 0x63, 0x05, 0x68, 0x00, 0x23, 0x84, 0x69, 
-0xa4, 0x08, 0x08, 0xd0, 0x9c, 0x00, 0x2e, 0x59, 0xc0, 0x46, 0x3e, 0x51, 
-0x84, 0x69, 0xa4, 0x08, 0x01, 0x33, 0x9c, 0x42, 0xf6, 0xd8, 0x3b, 0x1c, 
-0x00, 0xf0, 0x03, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0xb5, 
-0x81, 0xb0, 0x04, 0x1c, 0x1d, 0x1c, 0x0f, 0x1c, 0x46, 0x48, 0x01, 0x69, 
-0x01, 0x31, 0x01, 0x61, 0xf9, 0x1d, 0x51, 0x31, 0xbd, 0x65, 0x00, 0x91, 
-0x20, 0x1c, 0xfd, 0xf7, 0xa3, 0xfc, 0xf8, 0x6d, 0x40, 0x09, 0x36, 0xd2, 
-0xb8, 0x6d, 0x06, 0x7b, 0x43, 0x7b, 0x1b, 0x02, 0x1e, 0x43, 0x17, 0x21, 
-0x49, 0x02, 0x01, 0x73, 0x0b, 0x0a, 0x43, 0x73, 0x00, 0x99, 0x20, 0x1c, 
-0xfd, 0xf7, 0x92, 0xfc, 0xb8, 0x6d, 0xc0, 0x46, 0x06, 0x73, 0x33, 0x0a, 
-0x43, 0x73, 0xf8, 0x6d, 0x40, 0x09, 0x20, 0xd2, 0x60, 0x68, 0x01, 0x04, 
-0x09, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0xce, 0xfc, 0x60, 0x68, 0x32, 0x4b, 
-0x18, 0x43, 0x60, 0x60, 0x20, 0x1c, 0x01, 0xf0, 0x37, 0xfd, 0x00, 0x25, 
-0x7d, 0x60, 0xbd, 0x60, 0x3d, 0x64, 0x7d, 0x64, 0x20, 0x1c, 0xfc, 0xf7, 
-0x77, 0xff, 0x38, 0x88, 0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0x7d, 0x62, 
-0x29, 0x48, 0xc0, 0x46, 0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0xa0, 0xfb, 
-0x44, 0xe0, 0x20, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 
-0x00, 0x68, 0xc0, 0x46, 0x78, 0x64, 0x60, 0x68, 0x02, 0x04, 0x12, 0x0c, 
-0x78, 0x6e, 0x01, 0x26, 0xc1, 0x1d, 0x0d, 0x31, 0x8a, 0x42, 0x02, 0xd2, 
-0x3a, 0x64, 0x08, 0x1c, 0x0e, 0xe0, 0x41, 0x19, 0x89, 0x89, 0xf0, 0x23, 
-0x19, 0x40, 0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 0xf9, 0x61, 
-0x61, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x81, 0x42, 0x16, 0xd2, 0x39, 0x64, 
-0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08, 
-0x82, 0x00, 0xa0, 0x61, 0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 
-0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x7e, 0x80, 
+0x59, 0xfc, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 
+0x06, 0x0f, 0x70, 0x01, 0x80, 0x1b, 0x80, 0x00, 0x0c, 0x49, 0x44, 0x18, 
+0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65, 0x78, 0x6a, 0xc0, 0x46, 0x60, 0x67, 
+0x80, 0x6f, 0x05, 0x1d, 0xe5, 0x63, 0xb9, 0x69, 0x28, 0x1c, 0x02, 0xf0, 
+0x89, 0xf9, 0x38, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 0x2b, 0x1c, 0x00, 0xf0, 
+0x20, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
+0x5c, 0x2b, 0x00, 0x80, 0xf0, 0xb5, 0x4b, 0x6f, 0x9b, 0x6f, 0x1f, 0x1d, 
+0xcf, 0x63, 0x05, 0x68, 0x00, 0x23, 0x84, 0x69, 0xa4, 0x08, 0x08, 0xd0, 
+0x9c, 0x00, 0x2e, 0x59, 0xc0, 0x46, 0x3e, 0x51, 0x84, 0x69, 0xa4, 0x08, 
+0x01, 0x33, 0x9c, 0x42, 0xf6, 0xd8, 0x3b, 0x1c, 0x00, 0xf0, 0x03, 0xf8, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0xb5, 0x81, 0xb0, 0x04, 0x1c, 
+0x1d, 0x1c, 0x0f, 0x1c, 0x46, 0x48, 0x01, 0x69, 0x01, 0x31, 0x01, 0x61, 
+0xf9, 0x1d, 0x51, 0x31, 0xbd, 0x65, 0x00, 0x91, 0x20, 0x1c, 0xfd, 0xf7, 
+0x67, 0xfc, 0xf8, 0x6d, 0x40, 0x09, 0x36, 0xd2, 0xb8, 0x6d, 0x06, 0x7b, 
+0x43, 0x7b, 0x1b, 0x02, 0x1e, 0x43, 0x17, 0x21, 0x49, 0x02, 0x01, 0x73, 
+0x0b, 0x0a, 0x43, 0x73, 0x00, 0x99, 0x20, 0x1c, 0xfd, 0xf7, 0x56, 0xfc, 
+0xb8, 0x6d, 0xc0, 0x46, 0x06, 0x73, 0x33, 0x0a, 0x43, 0x73, 0xf8, 0x6d, 
+0x40, 0x09, 0x20, 0xd2, 0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 0x03, 0x98, 
+0x01, 0xf0, 0xcc, 0xfc, 0x60, 0x68, 0x32, 0x4b, 0x18, 0x43, 0x60, 0x60, 
+0x20, 0x1c, 0x01, 0xf0, 0x35, 0xfd, 0x00, 0x25, 0x7d, 0x60, 0xbd, 0x60, 
+0x3d, 0x64, 0x7d, 0x64, 0x20, 0x1c, 0xfc, 0xf7, 0x3b, 0xff, 0x38, 0x88, 
+0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0x7d, 0x62, 0x29, 0x48, 0xc0, 0x46, 
+0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0xa0, 0xfb, 0x44, 0xe0, 0x20, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 
+0x78, 0x64, 0x60, 0x68, 0x02, 0x04, 0x12, 0x0c, 0x78, 0x6e, 0x01, 0x26, 
+0xc1, 0x1d, 0x0d, 0x31, 0x8a, 0x42, 0x02, 0xd2, 0x3a, 0x64, 0x08, 0x1c, 
+0x0e, 0xe0, 0x41, 0x19, 0x89, 0x89, 0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 
+0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 0xf9, 0x61, 0x61, 0x68, 0x09, 0x04, 
+0x09, 0x0c, 0x81, 0x42, 0x16, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04, 
+0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08, 0x82, 0x00, 0xa0, 0x61, 
+0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 0xc3, 0x1f, 0x05, 0x3b, 
+0x38, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x7e, 0x80, 
 0x20, 0x1c, 0x00, 0xf0, 0xbf, 0xfb, 0x0b, 0xe0, 0xb9, 0x68, 0x08, 0x1a, 
 0x00, 0x25, 0x78, 0x62, 0xbd, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x3c, 0xfc, 
 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x64, 0xf8, 0x05, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x78, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
+0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
 0x01, 0x00, 0x00, 0xc0, 0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x6c, 
 0xf9, 0x6b, 0x0d, 0x18, 0x21, 0x68, 0x41, 0x18, 0x00, 0x20, 0xa2, 0x69, 
 0x00, 0x2a, 0x0b, 0xd9, 0x82, 0x00, 0x56, 0x18, 0x01, 0x23, 0x9b, 0x07, 
@@ -1148,127 +1161,127 @@ const u8 typhoon_firmware_image[] = {
 0x82, 0x42, 0xf3, 0xd8, 0x78, 0x6e, 0xf9, 0x6b, 0x09, 0x18, 0x89, 0x89, 
 0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 
 0xf9, 0x61, 0x20, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 
-0x01, 0x68, 0x78, 0x6c, 0xfc, 0xf7, 0xdb, 0xff, 
-0x78, 0x64, 0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 0xf8, 0x68, 0x81, 0x42, 
-0x19, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a, 
-0x03, 0x30, 0x80, 0x08, 0x82, 0x00, 0xa0, 0x61, 0x20, 0x68, 0x09, 0x18, 
-0x9b, 0x18, 0x63, 0x60, 0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 0x00, 0xf0, 
-0x56, 0xfa, 0x01, 0x20, 0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x5e, 0xfb, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb9, 0x68, 0x08, 0x1a, 0x78, 0x62, 
-0x00, 0x20, 0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0xd9, 0xfb, 0x20, 0x1c, 
-0x39, 0x1c, 0x00, 0xf0, 0x01, 0xf8, 0xef, 0xe7, 0xf0, 0xb5, 0x84, 0xb0, 
-0x04, 0x1c, 0x0f, 0x1c, 0x8e, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 
-0x03, 0x20, 0x00, 0x07, 0x61, 0x68, 0x08, 0x40, 0x06, 0x0f, 0x0a, 0x04, 
-0x12, 0x0c, 0x20, 0x68, 0x11, 0x18, 0xfb, 0x68, 0xd2, 0x1a, 0x7b, 0x68, 
-0x9d, 0x1a, 0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 
-0x26, 0xfa, 0x00, 0x20, 0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x2e, 0xfb, 
-0x60, 0x68, 0x40, 0x19, 0x01, 0x04, 0x09, 0x0c, 0x60, 0x60, 0x30, 0x1c, 
-0x01, 0xf0, 0xe2, 0xfb, 0x7d, 0x4e, 0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 
-0xc0, 0x68, 0x00, 0x28, 0x19, 0xd0, 0x00, 0x25, 0x2d, 0x23, 0x9b, 0x01, 
-0xf0, 0x18, 0x80, 0x68, 0x00, 0x28, 0x12, 0xd0, 0xaa, 0x00, 0x92, 0x19, 
-0x2d, 0x23, 0x9b, 0x01, 0xd2, 0x18, 0x92, 0x68, 0x20, 0x1c, 0x39, 0x1c, 
-0x01, 0xf0, 0x22, 0xfe, 0x01, 0x35, 0xa8, 0x00, 0x80, 0x19, 0x2d, 0x23, 
-0x9b, 0x01, 0xc0, 0x18, 0x80, 0x68, 0x00, 0x28, 0xec, 0xd1, 0xf8, 0x6b, 
-0x01, 0x1f, 0x8a, 0x1c, 0xfa, 0x63, 0xfa, 0x68, 0x7d, 0x6c, 0x00, 0xf0, 
-0xbb, 0xf9, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x28, 0x1c, 0xfc, 0xf7, 
-0x56, 0xff, 0x03, 0x90, 0xf9, 0x6b, 0x3a, 0x6e, 0x8e, 0x18, 0x20, 0x68, 
-0x12, 0x18, 0x01, 0x92, 0x7a, 0x6e, 0x8d, 0x18, 0x11, 0x18, 0x02, 0x91, 
-0xc8, 0x1d, 0x09, 0x30, 0xe0, 0x60, 0xb1, 0x88, 0x08, 0x02, 0x09, 0x0a, 
-0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x78, 0x61, 
-0x68, 0x68, 0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 
-0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 
-0x00, 0x06, 0x08, 0x43, 0x38, 0x61, 0xa8, 0x89, 0x09, 0x23, 0x1b, 0x02, 
-0x18, 0x40, 0xb8, 0x61, 0xa8, 0x89, 0x98, 0x43, 0xa8, 0x81, 0xa8, 0x89, 
-0x02, 0x99, 0xc0, 0x46, 0x88, 0x81, 0x00, 0x20, 0x70, 0x80, 0xb0, 0x80, 
+0x01, 0x68, 0x78, 0x6c, 0xfc, 0xf7, 0x9f, 0xff, 0x78, 0x64, 0x60, 0x68, 
+0x01, 0x04, 0x09, 0x0c, 0xf8, 0x68, 0x81, 0x42, 0x19, 0xd2, 0x39, 0x64, 
+0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08, 
+0x82, 0x00, 0xa0, 0x61, 0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 
+0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 0x00, 0xf0, 0x56, 0xfa, 0x01, 0x20, 
+0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x5e, 0xfb, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0xb9, 0x68, 0x08, 0x1a, 0x78, 0x62, 0x00, 0x20, 0xb8, 0x62, 
+0x38, 0x1c, 0x00, 0xf0, 0xd9, 0xfb, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 
+0x01, 0xf8, 0xef, 0xe7, 0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 
+0x8e, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x03, 0x20, 0x00, 0x07, 
+0x61, 0x68, 0x08, 0x40, 0x06, 0x0f, 0x0a, 0x04, 0x12, 0x0c, 0x20, 0x68, 
+0x11, 0x18, 0xfb, 0x68, 0xd2, 0x1a, 0x7b, 0x68, 0x9d, 0x1a, 0xc3, 0x1f, 
+0x05, 0x3b, 0x38, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 0x26, 0xfa, 0x00, 0x20, 
+0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x2e, 0xfb, 0x60, 0x68, 0x40, 0x19, 
+0x01, 0x04, 0x09, 0x0c, 0x60, 0x60, 0x30, 0x1c, 0x01, 0xf0, 0xe0, 0xfb, 
+0x7d, 0x4e, 0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 0x00, 0x69, 0x00, 0x28, 
+0x19, 0xd0, 0x00, 0x25, 0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x68, 
+0x00, 0x28, 0x12, 0xd0, 0xaa, 0x00, 0x92, 0x19, 0x2d, 0x23, 0x9b, 0x01, 
+0xd2, 0x18, 0xd2, 0x68, 0x20, 0x1c, 0x39, 0x1c, 0x01, 0xf0, 0x1c, 0xfe, 
+0x01, 0x35, 0xa8, 0x00, 0x80, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 
+0xc0, 0x68, 0x00, 0x28, 0xec, 0xd1, 0xf8, 0x6b, 0x01, 0x1f, 0x8a, 0x1c, 
+0xfa, 0x63, 0xfa, 0x68, 0x7d, 0x6c, 0x00, 0xf0, 0xbb, 0xf9, 0xc0, 0x43, 
+0x01, 0x04, 0x09, 0x0c, 0x28, 0x1c, 0xfc, 0xf7, 0x1a, 0xff, 0x03, 0x90, 
+0xf9, 0x6b, 0x3a, 0x6e, 0x8e, 0x18, 0x20, 0x68, 0x12, 0x18, 0x01, 0x92, 
+0x7a, 0x6e, 0x8d, 0x18, 0x11, 0x18, 0x02, 0x91, 0xc8, 0x1d, 0x09, 0x30, 
+0xe0, 0x60, 0xb1, 0x88, 0x08, 0x02, 0x09, 0x0a, 0x09, 0x06, 0x09, 0x0e, 
+0x08, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x78, 0x61, 0x68, 0x68, 0x01, 0x0e, 
+0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 
+0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 
+0x38, 0x61, 0xa8, 0x89, 0x09, 0x23, 0x1b, 0x02, 0x18, 0x40, 0xb8, 0x61, 
+0xa8, 0x89, 0x98, 0x43, 0xa8, 0x81, 0xa8, 0x89, 0x02, 0x99, 0xc0, 0x46, 
+0x88, 0x81, 0x00, 0x20, 0x70, 0x80, 0xb0, 0x80, 
 0x70, 0x81, 0x68, 0x60, 0x28, 0x82, 0xb9, 0x6e, 0x30, 0x1c, 0xfc, 0xf7, 
-0x2e, 0xff, 0x38, 0x86, 0xfa, 0x69, 0x30, 0x1c, 0x29, 0x1c, 0xfc, 0xf7, 
-0x49, 0xff, 0x78, 0x86, 0x3d, 0x8e, 0x78, 0x8e, 0x03, 0x99, 0xfc, 0xf7, 
-0x0e, 0xff, 0x00, 0x90, 0x60, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x39, 0x6e, 
+0xf2, 0xfe, 0x38, 0x86, 0xfa, 0x69, 0x30, 0x1c, 0x29, 0x1c, 0xfc, 0xf7, 
+0x0d, 0xff, 0x78, 0x86, 0x3d, 0x8e, 0x78, 0x8e, 0x03, 0x99, 0xfc, 0xf7, 
+0xd2, 0xfe, 0x00, 0x90, 0x60, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x39, 0x6e, 
 0x41, 0x1a, 0x09, 0x04, 0x09, 0x0c, 0x7a, 0x6e, 0x82, 0x1a, 0x13, 0x04, 
 0x1b, 0x0c, 0x1a, 0x02, 0x1b, 0x0a, 0x1a, 0x43, 0x16, 0x04, 0x36, 0x0c, 
 0xba, 0x68, 0x82, 0x42, 0x01, 0xd2, 0x00, 0x20, 0x00, 0xe0, 0x10, 0x1a, 
 0xb8, 0x60, 0x08, 0x02, 0x09, 0x12, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 
 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x28, 0x1c, 
-0xfc, 0xf7, 0xe9, 0xfe, 0x05, 0x1c, 0x00, 0x98, 0x31, 0x1c, 0xfc, 0xf7, 
-0xe4, 0xfe, 0x06, 0x1c, 0x78, 0x69, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x02, 
-0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 
-0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x28, 0x1c, 0xfc, 0xf7, 0xd5, 0xfe, 
-0x79, 0x69, 0x01, 0x31, 0xc0, 0x43, 0x79, 0x61, 0x01, 0x9a, 0xc0, 0x46, 
-0x50, 0x81, 0x38, 0x69, 0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 
-0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 
-0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 0x30, 0x1c, 0xfc, 0xf7, 0xbd, 0xfe, 
-0x39, 0x69, 0x7a, 0x68, 0x89, 0x18, 0x39, 0x61, 0xb9, 0x68, 0x00, 0x29, 
-0x09, 0xd1, 0x02, 0x99, 0x89, 0x89, 0xba, 0x69, 0x11, 0x43, 0x02, 0x9a, 
-0xc0, 0x46, 0x91, 0x81, 0xb9, 0x69, 0xfc, 0xf7, 0xac, 0xfe, 0x20, 0x82, 
-0x00, 0x20, 0x60, 0x82, 0xf8, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 
-0x0a, 0xd3, 0x60, 0x68, 0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 
-0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 0xc0, 0x46, 0x08, 0x82, 0x09, 0xe0, 
-0x60, 0x68, 0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 
-0x08, 0x43, 0x21, 0x68, 0xc0, 0x46, 0x88, 0x81, 0x04, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x78, 0x2a, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 
-0xf1, 0xb5, 0x84, 0xb0, 0x6e, 0x4d, 0x28, 0x69, 0x01, 0x22, 0x04, 0x99, 
-0x8a, 0x40, 0x90, 0x43, 0x28, 0x61, 0x04, 0x98, 0x43, 0x01, 0x18, 0x1a, 
-0x80, 0x00, 0x16, 0x1c, 0x69, 0x49, 0x44, 0x18, 0xe0, 0x6b, 0xc0, 0x46, 
-0x00, 0x90, 0xa0, 0x68, 0x00, 0x28, 0x01, 0xd1, 0x00, 0x26, 0x26, 0xe0, 
-0x65, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x04, 0x98, 0xfc, 0xf7, 
-0x4f, 0xfd, 0x07, 0x1c, 0x03, 0xd1, 0x28, 0x69, 0x30, 0x43, 0x28, 0x61, 
-0xb5, 0xe0, 0xa0, 0x68, 0x65, 0x68, 0xa8, 0x42, 0x00, 0xd2, 0x05, 0x1c, 
-0xa1, 0x6c, 0xa9, 0x42, 0x16, 0xd2, 0x40, 0x1a, 0x62, 0x6a, 0x10, 0x1a, 
-0x00, 0x26, 0x60, 0x62, 0xa6, 0x60, 0xa6, 0x62, 0x20, 0x88, 0x48, 0x23, 
-0x18, 0x43, 0x20, 0x80, 0x0d, 0x1c, 0x09, 0xd1, 0x38, 0x1c, 0xfc, 0xf7, 
-0x5f, 0xfd, 0x03, 0x20, 0x60, 0x80, 0x66, 0x60, 0x20, 0x1c, 0x00, 0xf0, 
-0x8d, 0xf9, 0x96, 0xe0, 0xe1, 0x68, 0x38, 0x68, 0x09, 0x18, 0xc3, 0x1f, 
-0x05, 0x3b, 0x20, 0x1c, 0x02, 0x39, 0x2a, 0x1c, 0x00, 0xf0, 0xcd, 0xf8, 
-0x38, 0x1c, 0x00, 0xf0, 0xd7, 0xf9, 0xe0, 0x68, 0x46, 0x19, 0x78, 0x68, 
-0x30, 0x43, 0x78, 0x60, 0x04, 0x98, 0x31, 0x1c, 0x01, 0xf0, 0x8a, 0xfa, 
-0x21, 0x6e, 0x00, 0x98, 0x08, 0x18, 0x01, 0x90, 0x70, 0x1a, 0x00, 0x04, 
-0x00, 0x0c, 0x61, 0x6e, 0x71, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 
+0xfc, 0xf7, 0xad, 0xfe, 0x05, 0x1c, 0x00, 0x98, 0x31, 0x1c, 0xfc, 0xf7, 
+0xa8, 0xfe, 0x06, 0x1c, 0x78, 0x69, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x02, 
+0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 
+0x81, 0x80, 0x28, 0x1c, 0xfc, 0xf7, 0x99, 0xfe, 0x79, 0x69, 0x01, 0x31, 
+0xc0, 0x43, 0x79, 0x61, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x81, 0x38, 0x69, 
+0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 
+0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 
+0x01, 0x43, 0x30, 0x1c, 0xfc, 0xf7, 0x81, 0xfe, 0x39, 0x69, 0x7a, 0x68, 
+0x89, 0x18, 0x39, 0x61, 0xb9, 0x68, 0x00, 0x29, 0x09, 0xd1, 0x02, 0x99, 
+0x89, 0x89, 0xba, 0x69, 0x11, 0x43, 0x02, 0x9a, 0xc0, 0x46, 0x91, 0x81, 
+0xb9, 0x69, 0xfc, 0xf7, 0x70, 0xfe, 0x20, 0x82, 0x00, 0x20, 0x60, 0x82, 
+0xf8, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x60, 0x68, 
+0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 
+0x21, 0x68, 0xc0, 0x46, 0x08, 0x82, 0x09, 0xe0, 0x60, 0x68, 0x0c, 0x38, 
+0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 
+0xc0, 0x46, 0x88, 0x81, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x0c, 0x2b, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0xf1, 0xb5, 0x84, 0xb0, 
+0x6e, 0x4d, 0x28, 0x69, 0x01, 0x22, 0x04, 0x99, 0x8a, 0x40, 0x90, 0x43, 
+0x28, 0x61, 0x04, 0x98, 0x43, 0x01, 0x18, 0x1a, 0x80, 0x00, 0x16, 0x1c, 
+0x69, 0x49, 0x44, 0x18, 0xe0, 0x6b, 0xc0, 0x46, 0x00, 0x90, 0xa0, 0x68, 
+0x00, 0x28, 0x01, 0xd1, 0x00, 0x26, 0x26, 0xe0, 0x65, 0x48, 0x41, 0x69, 
+0x01, 0x31, 0x41, 0x61, 0x04, 0x98, 0xfc, 0xf7, 0x13, 0xfd, 0x07, 0x1c, 
+0x03, 0xd1, 0x28, 0x69, 0x30, 0x43, 0x28, 0x61, 0xb5, 0xe0, 0xa0, 0x68, 
+0x65, 0x68, 0xa8, 0x42, 0x00, 0xd2, 0x05, 0x1c, 0xa1, 0x6c, 0xa9, 0x42, 
+0x16, 0xd2, 0x40, 0x1a, 0x62, 0x6a, 0x10, 0x1a, 0x00, 0x26, 0x60, 0x62, 
+0xa6, 0x60, 0xa6, 0x62, 0x20, 0x88, 0x48, 0x23, 0x18, 0x43, 0x20, 0x80, 
+0x0d, 0x1c, 0x09, 0xd1, 0x38, 0x1c, 0xfc, 0xf7, 0x23, 0xfd, 0x03, 0x20, 
+0x60, 0x80, 0x66, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x8d, 0xf9, 0x96, 0xe0, 
+0xe1, 0x68, 0x38, 0x68, 0x09, 0x18, 0xc3, 0x1f, 0x05, 0x3b, 0x20, 0x1c, 
+0x02, 0x39, 0x2a, 0x1c, 0x00, 0xf0, 0xcd, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 
+0xd7, 0xf9, 0xe0, 0x68, 0x46, 0x19, 0x78, 0x68, 0x30, 0x43, 0x78, 0x60, 
+0x04, 0x98, 0x31, 0x1c, 0x01, 0xf0, 0x88, 0xfa, 0x21, 0x6e, 0x00, 0x98, 
+0x08, 0x18, 0x01, 0x90, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x61, 0x6e, 
+0x71, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 
 0x12, 0x0a, 0x11, 0x43, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x91, 0x01, 0x02, 
 0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 
-0x41, 0x80, 0x20, 0x8e, 0xfc, 0xf7, 0x11, 0xfe, 0x06, 0x1c, 0x60, 0x8e, 
-0x02, 0x99, 0xfc, 0xf7, 0x0c, 0xfe, 0x03, 0x90, 0x60, 0x69, 0x01, 0x04, 
+0x41, 0x80, 0x20, 0x8e, 0xfc, 0xf7, 0xd5, 0xfd, 0x06, 0x1c, 0x60, 0x8e, 
+0x02, 0x99, 0xfc, 0xf7, 0xd0, 0xfd, 0x03, 0x90, 0x60, 0x69, 0x01, 0x04, 
 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 
-0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x30, 0x1c, 0xfc, 0xf7, 0xfd, 0xfd, 
+0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x30, 0x1c, 0xfc, 0xf7, 0xc1, 0xfd, 
 0x61, 0x69, 0x01, 0x31, 0xc0, 0x43, 0x61, 0x61, 0x01, 0x99, 0xc0, 0x46, 
 0x48, 0x81, 0x60, 0x6e, 0x00, 0x99, 0x46, 0x18, 0x20, 0x69, 0x01, 0x0e, 
 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 
 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 
-0x71, 0x60, 0x03, 0x98, 0xfc, 0xf7, 0xe1, 0xfd, 0x21, 0x69, 0x49, 0x19, 
-0x21, 0x61, 0xa1, 0x68, 0x49, 0x1b, 0xa1, 0x60, 
-0x06, 0xd1, 0xb1, 0x89, 0xa2, 0x69, 0x11, 0x43, 0xb1, 0x81, 0xa1, 0x69, 
-0xfc, 0xf7, 0xd3, 0xfd, 0x38, 0x82, 0x61, 0x6e, 0x38, 0x68, 0x09, 0x18, 
-0x0e, 0x31, 0xf9, 0x60, 0xe2, 0x68, 0x00, 0x99, 0x04, 0x38, 0x00, 0xf0, 
-0x4c, 0xf8, 0x02, 0x20, 0x78, 0x82, 0xe0, 0x6d, 0x41, 0x08, 0x16, 0xd3, 
-0x80, 0x0a, 0x0a, 0xd3, 0x78, 0x68, 0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 
-0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x39, 0x68, 0xc0, 0x46, 0xc8, 0x81, 
-0x09, 0xe0, 0x78, 0x68, 0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 
-0x09, 0x0a, 0x08, 0x43, 0x39, 0x68, 0xc0, 0x46, 0x48, 0x81, 0x05, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x3c, 0x2c, 0x00, 0x80, 
-0xc8, 0x2a, 0x00, 0x80, 0x78, 0x2a, 0x00, 0x80, 0xf7, 0xb5, 0x03, 0x1c, 
-0x0f, 0x1c, 0x00, 0x20, 0x1c, 0x68, 0x26, 0x04, 0x31, 0x1c, 0x1d, 0x1d, 
-0xfc, 0xf7, 0x97, 0xfd, 0x40, 0xc7, 0x02, 0x9a, 0xd1, 0x1c, 0x89, 0x08, 
-0x01, 0x39, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29, 0x0d, 0xd0, 0x21, 0x0c, 
-0x10, 0xcd, 0x22, 0x04, 0x0a, 0x43, 0x11, 0x1c, 0x16, 0x1c, 0xfc, 0xf7, 
-0x86, 0xfd, 0x40, 0xc7, 0x02, 0x99, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29, 
-0xf1, 0xd1, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x08, 
-0x80, 0x00, 0x89, 0x08, 0x89, 0x00, 0x03, 0x32, 0x93, 0x08, 0x5a, 0x1e, 
-0x00, 0x2b, 0x05, 0xd0, 0x08, 0xc9, 0x08, 0xc0, 0x13, 0x1c, 0x01, 0x3a, 
-0x00, 0x2b, 0xf9, 0xd1, 0x70, 0x47, 0xff, 0xb5, 0x86, 0xb0, 0x17, 0x1c, 
-0x00, 0x26, 0x06, 0x98, 0x80, 0x6c, 0xc0, 0x1b, 0x06, 0x99, 0xc0, 0x46, 
-0x88, 0x64, 0x01, 0x20, 0xc0, 0x05, 0x06, 0x99, 0x89, 0x6b, 0xc0, 0x46, 
-0x01, 0x91, 0x06, 0x99, 0x4c, 0x6b, 0x67, 0xe0, 0x21, 0x68, 0xc0, 0x46, 
-0x02, 0x91, 0x61, 0x68, 0xc0, 0x46, 0x03, 0x91, 0xa1, 0x68, 0xc0, 0x46, 
-0x04, 0x91, 0x02, 0xa9, 0x49, 0x88, 0xb9, 0x42, 0x08, 0xd2, 0x02, 0xad, 
-0x6d, 0x88, 0x02, 0xa9, 0x49, 0x88, 0x7f, 0x1a, 0x00, 0x21, 0x02, 0xab, 
-0x59, 0x80, 0x19, 0xe0, 0x02, 0xa9, 0x49, 0x88, 0xc9, 0x1b, 0x02, 0xab, 
-0x59, 0x80, 0x3d, 0x1c, 0x00, 0x27, 0x01, 0x21, 0x49, 0x06, 0x07, 0x9b, 
-0x9a, 0x07, 0x92, 0x0f, 0x0d, 0xd0, 0xeb, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 
-0x1e, 0x2b, 0x08, 0xd3, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x2a, 0x04, 0xd1, 
-0x01, 0xe0, 0x02, 0x2a, 0x01, 0xd3, 0x01, 0x26, 0x00, 0x21, 0x29, 0x43, 
-0x01, 0x43, 0x0a, 0x1c, 0x00, 0x91, 0x00, 0x20, 0x03, 0x99, 0x04, 0x9a, 
-0x07, 0x9b, 0x01, 0xf0, 0x61, 0xff, 0x07, 0x99, 0x49, 0x19, 0x07, 0x91, 
+0x71, 0x60, 0x03, 0x98, 0xfc, 0xf7, 0xa5, 0xfd, 0x21, 0x69, 0x49, 0x19, 
+0x21, 0x61, 0xa1, 0x68, 0x49, 0x1b, 0xa1, 0x60, 0x06, 0xd1, 0xb1, 0x89, 
+0xa2, 0x69, 0x11, 0x43, 0xb1, 0x81, 0xa1, 0x69, 0xfc, 0xf7, 0x97, 0xfd, 
+0x38, 0x82, 0x61, 0x6e, 0x38, 0x68, 0x09, 0x18, 0x0e, 0x31, 0xf9, 0x60, 
+0xe2, 0x68, 0x00, 0x99, 0x04, 0x38, 0x00, 0xf0, 0x4c, 0xf8, 0x02, 0x20, 
+0x78, 0x82, 0xe0, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 
+0x78, 0x68, 0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 
+0x08, 0x43, 0x39, 0x68, 0xc0, 0x46, 0xc8, 0x81, 0x09, 0xe0, 0x78, 0x68, 
+0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 
+0x39, 0x68, 0xc0, 0x46, 0x48, 0x81, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 
+0x0c, 0x2b, 0x00, 0x80, 0xf7, 0xb5, 0x03, 0x1c, 0x0f, 0x1c, 0x00, 0x20, 
+0x1c, 0x68, 0x26, 0x04, 0x31, 0x1c, 0x1d, 0x1d, 0xfc, 0xf7, 0x5b, 0xfd, 
+0x40, 0xc7, 0x02, 0x9a, 0xd1, 0x1c, 0x89, 0x08, 0x01, 0x39, 0x4a, 0x1e, 
+0x02, 0x92, 0x00, 0x29, 0x0d, 0xd0, 0x21, 0x0c, 0x10, 0xcd, 0x22, 0x04, 
+0x0a, 0x43, 0x11, 0x1c, 0x16, 0x1c, 0xfc, 0xf7, 0x4a, 0xfd, 0x40, 0xc7, 
+0x02, 0x99, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29, 0xf1, 0xd1, 0x03, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x08, 0x80, 0x00, 0x89, 0x08, 
+0x89, 0x00, 0x03, 0x32, 0x93, 0x08, 0x5a, 0x1e, 0x00, 0x2b, 0x05, 0xd0, 
+0x08, 0xc9, 0x08, 0xc0, 0x13, 0x1c, 0x01, 0x3a, 0x00, 0x2b, 0xf9, 0xd1, 
+0x70, 0x47, 0xff, 0xb5, 0x86, 0xb0, 0x17, 0x1c, 0x00, 0x26, 0x06, 0x98, 
+0x80, 0x6c, 0xc0, 0x1b, 0x06, 0x99, 0xc0, 0x46, 0x88, 0x64, 0x01, 0x20, 
+0xc0, 0x05, 0x06, 0x99, 0x89, 0x6b, 0xc0, 0x46, 0x01, 0x91, 0x06, 0x99, 
+0x4c, 0x6b, 0x67, 0xe0, 0x21, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x61, 0x68, 
+0xc0, 0x46, 0x03, 0x91, 0xa1, 0x68, 0xc0, 0x46, 0x04, 0x91, 0x02, 0xa9, 
+0x49, 0x88, 0xb9, 0x42, 0x08, 0xd2, 0x02, 0xad, 0x6d, 0x88, 0x02, 0xa9, 
+0x49, 0x88, 0x7f, 0x1a, 0x00, 0x21, 0x02, 0xab, 0x59, 0x80, 0x19, 0xe0, 
+0x02, 0xa9, 0x49, 0x88, 0xc9, 0x1b, 0x02, 0xab, 0x59, 0x80, 0x3d, 0x1c, 
+0x00, 0x27, 0x01, 0x21, 0x49, 0x06, 0x07, 0x9b, 0x9a, 0x07, 0x92, 0x0f, 
+0x0d, 0xd0, 0xeb, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 0x08, 0xd3, 
+0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x2a, 0x04, 0xd1, 0x01, 0xe0, 0x02, 0x2a, 
+0x01, 0xd3, 0x01, 0x26, 0x00, 0x21, 0x29, 0x43, 0x01, 0x43, 0x0a, 0x1c, 
+0x00, 0x91, 0x00, 0x20, 0x03, 0x99, 0x04, 0x9a, 
+0x07, 0x9b, 0x01, 0xf0, 0x5b, 0xff, 0x07, 0x99, 0x49, 0x19, 0x07, 0x91, 
 0x00, 0x2e, 0x0a, 0xd0, 0x1d, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x1d, 0x48, 
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x07, 0x9b, 0x01, 0xf0, 0x52, 0xff, 
+0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x07, 0x9b, 0x01, 0xf0, 0x4c, 0xff, 
 0x00, 0x26, 0x02, 0xa8, 0x40, 0x88, 0x00, 0x28, 0x0c, 0xd0, 0x03, 0x98, 
 0x40, 0x19, 0x03, 0x90, 0x02, 0x98, 0xc0, 0x46, 0x20, 0x60, 0x03, 0x98, 
 0xc0, 0x46, 0x60, 0x60, 0x04, 0x98, 0xc0, 0x46, 0xa0, 0x60, 0x03, 0xe0, 
@@ -1276,513 +1289,512 @@ const u8 typhoon_firmware_image[] = {
 0x44, 0x63, 0x01, 0x98, 0x06, 0x99, 0xc0, 0x46, 0x88, 0x63, 0x00, 0x20, 
 0x00, 0x2f, 0x02, 0xd0, 0x01, 0x99, 0x00, 0x29, 0x92, 0xd1, 0x09, 0x4a, 
 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 
-0x09, 0x9b, 0x01, 0xf0, 0x25, 0xff, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 
-0xf8, 0x28, 0x00, 0x80, 0x04, 0x00, 0x53, 0x02, 0x90, 0xb5, 0x0c, 0x1c, 
-0x07, 0x1c, 0x38, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 
-0x01, 0x68, 0x38, 0x8a, 0xfc, 0xf7, 0xcb, 0xfc, 0xc0, 0x43, 0xf9, 0x68, 
-0xc0, 0x46, 0x08, 0x80, 0x78, 0x8a, 0x39, 0x68, 0x08, 0x1a, 0x38, 0x60, 
-0x38, 0x1c, 0x01, 0xf0, 0x8d, 0xf9, 0x38, 0x1c, 0xfc, 0xf7, 0xd2, 0xfb, 
-0x20, 0x1c, 0xff, 0xf7, 0x33, 0xfe, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x80, 0xb5, 0x01, 0x88, 0x8a, 0x09, 0x21, 0xd3, 0xca, 0x09, 0x1f, 0xd2, 
-0x8a, 0x08, 0x1d, 0xd3, 0x00, 0x21, 0x01, 0x80, 0x41, 0x80, 0x47, 0x6f, 
-0x40, 0x6d, 0xfa, 0x1d, 0x19, 0x32, 0x51, 0x71, 0xfa, 0x6d, 0xc0, 0x46, 
-0x10, 0x60, 0x3a, 0x6e, 0xc0, 0x46, 0x10, 0x60, 0x0c, 0x48, 0xc0, 0x46, 
-0x41, 0x63, 0x81, 0x6b, 0x49, 0x08, 0x49, 0x00, 0x81, 0x63, 0x01, 0x20, 
-0x00, 0xf0, 0xce, 0xff, 0x38, 0x1c, 0x00, 0xf0, 0x6d, 0xff, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x80, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 
-0x49, 0x09, 0xf6, 0xd2, 0x00, 0xf0, 0xb0, 0xf8, 0xf3, 0xe7, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 0x10, 0x1c, 0x0d, 0x1c, 
-0x00, 0x24, 0x5e, 0x1e, 0x00, 0x2b, 0x19, 0xd0, 0x01, 0x68, 0xc0, 0x46, 
-0x39, 0x60, 0x41, 0x88, 0x0c, 0x19, 0x41, 0x68, 0xc0, 0x46, 0x79, 0x60, 
-0x81, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0xc1, 0x68, 0xc0, 0x46, 0xf9, 0x60, 
-0x10, 0x30, 0x10, 0x37, 0xe9, 0x6a, 0x81, 0x42, 0x02, 0xd8, 0x28, 0x1c, 
-0x00, 0xf0, 0xee, 0xff, 0x31, 0x1c, 0x01, 0x3e, 0x00, 0x29, 0xe5, 0xd1, 
-0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0xc1, 0x61, 
-0x05, 0x49, 0x0a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 0x08, 0x60, 0x02, 0xe0, 
-0x4a, 0x68, 0xc0, 0x46, 0xd0, 0x61, 0x48, 0x60, 0x70, 0x47, 0x00, 0x00, 
-0x3c, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x08, 0x68, 0x00, 0x28, 0x02, 0xd0, 
-0xc2, 0x69, 0xc0, 0x46, 0x0a, 0x60, 0x70, 0x47, 0x3c, 0x2c, 0x00, 0x80, 
-0x00, 0x21, 0x81, 0x67, 0x05, 0x49, 0x8a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 
-0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46, 0x90, 0x67, 0xc8, 0x60, 
-0x70, 0x47, 0x00, 0x00, 0x3c, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x88, 0x68, 
-0x00, 0x28, 0x02, 0xd0, 0x82, 0x6f, 0xc0, 0x46, 0x8a, 0x60, 0x70, 0x47, 
-0x3c, 0x2c, 0x00, 0x80, 0x00, 0xb5, 0x80, 0x20, 0x13, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0xff, 0xf7, 0xd5, 0xff, 0x00, 0x28, 0x1b, 0xd0, 0x03, 0x23, 
+0x09, 0x9b, 0x01, 0xf0, 0x1f, 0xff, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0x04, 0x00, 0x53, 0x02, 0x90, 0xb5, 0x0c, 0x1c, 0x07, 0x1c, 0x38, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x38, 0x8a, 
+0xfc, 0xf7, 0x8f, 0xfc, 0xc0, 0x43, 0xf9, 0x68, 0xc0, 0x46, 0x08, 0x80, 
+0x78, 0x8a, 0x39, 0x68, 0x08, 0x1a, 0x38, 0x60, 0x38, 0x1c, 0x01, 0xf0, 
+0x8b, 0xf9, 0x38, 0x1c, 0xfc, 0xf7, 0x96, 0xfb, 0x20, 0x1c, 0xff, 0xf7, 
+0x33, 0xfe, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x01, 0x88, 
+0x8a, 0x09, 0x21, 0xd3, 0xca, 0x09, 0x1f, 0xd2, 0x8a, 0x08, 0x1d, 0xd3, 
+0x00, 0x21, 0x01, 0x80, 0x41, 0x80, 0x47, 0x6f, 0x40, 0x6d, 0xfa, 0x1d, 
+0x19, 0x32, 0x51, 0x71, 0xfa, 0x6d, 0xc0, 0x46, 0x10, 0x60, 0x3a, 0x6e, 
+0xc0, 0x46, 0x10, 0x60, 0x0c, 0x48, 0xc0, 0x46, 0x81, 0x63, 0xc1, 0x6b, 
+0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 0x00, 0xf0, 0xcc, 0xff, 
+0x38, 0x1c, 0x00, 0xf0, 0x6b, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 0x49, 0x09, 0xf6, 0xd2, 
+0x00, 0xf0, 0xb0, 0xf8, 0xf3, 0xe7, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 
+0xf0, 0xb5, 0x07, 0x1c, 0x10, 0x1c, 0x0d, 0x1c, 0x00, 0x24, 0x5e, 0x1e, 
+0x00, 0x2b, 0x19, 0xd0, 0x01, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x41, 0x88, 
+0x0c, 0x19, 0x41, 0x68, 0xc0, 0x46, 0x79, 0x60, 0x81, 0x68, 0xc0, 0x46, 
+0xb9, 0x60, 0xc1, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x10, 0x30, 0x10, 0x37, 
+0xe9, 0x6a, 0x81, 0x42, 0x02, 0xd8, 0x28, 0x1c, 0x00, 0xf0, 0xec, 0xff, 
+0x31, 0x1c, 0x01, 0x3e, 0x00, 0x29, 0xe5, 0xd1, 0x20, 0x1c, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x0a, 0x68, 
+0x00, 0x2a, 0x01, 0xd1, 0x08, 0x60, 0x02, 0xe0, 0x4a, 0x68, 0xc0, 0x46, 
+0xd0, 0x61, 0x48, 0x60, 0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 
+0x03, 0x49, 0x08, 0x68, 0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 
+0x0a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80, 0x00, 0x21, 0x81, 0x67, 
+0x05, 0x49, 0x8a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 
+0xca, 0x68, 0xc0, 0x46, 0x90, 0x67, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 
+0xd0, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 
+0x82, 0x6f, 0xc0, 0x46, 0x8a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80, 
+0x00, 0xb5, 0x80, 0x20, 0x13, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xff, 0xf7, 
+0xd5, 0xff, 0x00, 0x28, 0x1b, 0xd0, 0x03, 0x23, 
 0x1b, 0x07, 0x41, 0x68, 0x19, 0x40, 0x0a, 0x0f, 0x51, 0x01, 0x89, 0x1a, 
 0x89, 0x00, 0x0d, 0x4b, 0xc9, 0x18, 0x4b, 0x88, 0x00, 0x2b, 0x04, 0xd1, 
 0x11, 0x1c, 0xff, 0xf7, 0x3b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x2b, 
 0x02, 0xd1, 0xff, 0xf7, 0x05, 0xfc, 0xf8, 0xe7, 0x02, 0x2b, 0xf6, 0xd1, 
 0xff, 0xf7, 0x4e, 0xfb, 0xf3, 0xe7, 0x04, 0x48, 0x01, 0x6d, 0x01, 0x31, 
-0x01, 0x65, 0xee, 0xe7, 0x00, 0x00, 0x00, 0xb0, 0xc8, 0x2a, 0x00, 0x80, 
+0x01, 0x65, 0xee, 0xe7, 0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 
 0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x20, 0x20, 0x0d, 0x49, 0xc0, 0x46, 
 0x08, 0x60, 0xff, 0xf7, 0xbf, 0xff, 0x00, 0x28, 0x0e, 0xd0, 0x01, 0x88, 
 0x20, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 0x10, 0x23, 0x99, 0x43, 
 0x01, 0x80, 0x01, 0x88, 0x09, 0x0a, 0x01, 0xd3, 0xff, 0xf7, 0x2e, 0xff, 
 0x08, 0xbc, 0x18, 0x47, 0x03, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 
-0xf8, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
-0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x07, 0x1c, 0x22, 0x48, 0xc0, 0x46, 
-0x00, 0x90, 0x22, 0x48, 0xc3, 0x1d, 0x41, 0x33, 0x41, 0x6d, 0x82, 0x6d, 
-0x80, 0x6c, 0x00, 0x03, 0x00, 0x0b, 0x9c, 0x68, 0x01, 0x23, 0x9b, 0x07, 
-0x23, 0x43, 0x1b, 0x68, 0x98, 0x42, 0x00, 0xd1, 0x0c, 0xe0, 0x98, 0x42, 
-0x03, 0xd9, 0x10, 0x1a, 0x59, 0x1a, 0x41, 0x18, 0x00, 0xe0, 0x19, 0x1a, 
-0x01, 0x20, 0x10, 0x29, 0x00, 0xd8, 0x00, 0x20, 0x00, 0x28, 0x1f, 0xd0, 
-0x78, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x08, 0x60, 0xb8, 0x6a, 0xf9, 0x6a, 
-0xc0, 0x46, 0x48, 0x60, 0x10, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xfb, 0x6a, 
-0x0f, 0x48, 0x42, 0x6d, 0x03, 0x20, 0x39, 0x6a, 0x01, 0xf0, 0xe8, 0xfd, 
-0x38, 0x88, 0x10, 0x23, 0x18, 0x43, 0x38, 0x80, 0x38, 0x88, 0x40, 0x23, 
-0x98, 0x43, 0x38, 0x80, 0x38, 0x1c, 0xff, 0xf7, 0x55, 0xff, 0x98, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x88, 0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 
-0xf7, 0xe7, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x28, 0x03, 0x00, 0x80, 
-0x08, 0x00, 0x11, 0x02, 0xf8, 0x28, 0x00, 0x80, 0xb0, 0xb5, 0x40, 0x20, 
-0x2c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0, 0xff, 0xfe, 0x07, 0x1c, 
-0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x05, 0x0f, 0x68, 0x01, 
-0x40, 0x1b, 0x80, 0x00, 0x26, 0x49, 0x44, 0x18, 0x20, 0x88, 0x02, 0x23, 
-0x18, 0x43, 0x20, 0x80, 0x20, 0x88, 0x41, 0x08, 0x34, 0xd3, 0x40, 0x08, 
-0x40, 0x00, 0x20, 0x80, 0xa0, 0x6c, 0xe1, 0x6c, 0x40, 0x18, 0xa0, 0x64, 
-0x00, 0x20, 0xe0, 0x64, 0xa1, 0x6b, 0x22, 0x6d, 0x89, 0x18, 0xa1, 0x63, 
-0x20, 0x65, 0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65, 0x03, 0x23, 0x1b, 0x07, 
-0x78, 0x68, 0x18, 0x40, 0x78, 0x60, 0x61, 0x68, 0x36, 0x31, 0x94, 0x29, 
-0x04, 0xd8, 0x38, 0x23, 0x18, 0x43, 0x78, 0x60, 0x38, 0x20, 0x03, 0xe0, 
-0x94, 0x23, 0x18, 0x43, 0x78, 0x60, 0x94, 0x20, 0xb8, 0x61, 0x39, 0x68, 
-0x78, 0x68, 0x02, 0x04, 0x12, 0x0c, 0x20, 0x1c, 0xcb, 0x1f, 0x05, 0x3b, 
-0xff, 0xf7, 0xd7, 0xfd, 0x02, 0x20, 0x60, 0x80, 0x38, 0x1c, 0xff, 0xf7, 
-0xdf, 0xfe, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xfc, 0xf7, 
-0x4d, 0xfa, 0x28, 0x01, 0x06, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 
-0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0xef, 0xe7, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0xc8, 0x2a, 0x00, 0x80, 0x1c, 0x1c, 0x00, 0x80, 
-0x90, 0xb5, 0x00, 0x27, 0x0f, 0x4c, 0x0d, 0xe0, 0x02, 0x6b, 0x01, 0x3a, 
-0x02, 0x63, 0x00, 0x2a, 0x05, 0xdc, 0xc2, 0x6a, 0xc0, 0x46, 0x02, 0x63, 
-0x80, 0x6a, 0x01, 0xf0, 0xcc, 0xf9, 0x01, 0x37, 0x0b, 0x2f, 0x07, 0xd2, 
-0x38, 0x01, 0x00, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x41, 0x6a, 
+0xf8, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa0, 0x82, 0x20, 0x40, 
+0x98, 0xb5, 0x07, 0x1c, 0x22, 0x48, 0xc0, 0x46, 0x00, 0x90, 0x22, 0x48, 
+0xc3, 0x1d, 0x41, 0x33, 0x41, 0x6d, 0x82, 0x6d, 0x80, 0x6c, 0x00, 0x03, 
+0x00, 0x0b, 0x9c, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 
+0x98, 0x42, 0x00, 0xd1, 0x0c, 0xe0, 0x98, 0x42, 0x03, 0xd9, 0x10, 0x1a, 
+0x59, 0x1a, 0x41, 0x18, 0x00, 0xe0, 0x19, 0x1a, 0x01, 0x20, 0x10, 0x29, 
+0x00, 0xd8, 0x00, 0x20, 0x00, 0x28, 0x1f, 0xd0, 0x78, 0x6a, 0xf9, 0x6a, 
+0xc0, 0x46, 0x08, 0x60, 0xb8, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x48, 0x60, 
+0x10, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xfb, 0x6a, 0x0f, 0x48, 0x42, 0x6d, 
+0x03, 0x20, 0x39, 0x6a, 0x01, 0xf0, 0xe2, 0xfd, 0x38, 0x88, 0x10, 0x23, 
+0x18, 0x43, 0x38, 0x80, 0x38, 0x88, 0x40, 0x23, 0x98, 0x43, 0x38, 0x80, 
+0x38, 0x1c, 0xff, 0xf7, 0x55, 0xff, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x38, 0x88, 0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0xf7, 0xe7, 0x00, 0x00, 
+0x55, 0x55, 0x55, 0x55, 0xa8, 0x03, 0x00, 0x80, 0x08, 0x00, 0x11, 0x02, 
+0x7c, 0x29, 0x00, 0x80, 0xb0, 0xb5, 0x40, 0x20, 0x2c, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0x00, 0xf0, 0xfd, 0xfe, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 
+0x1b, 0x07, 0x18, 0x40, 0x05, 0x0f, 0x68, 0x01, 0x40, 0x1b, 0x80, 0x00, 
+0x26, 0x49, 0x44, 0x18, 0x20, 0x88, 0x02, 0x23, 0x18, 0x43, 0x20, 0x80, 
+0x20, 0x88, 0x41, 0x08, 0x34, 0xd3, 0x40, 0x08, 0x40, 0x00, 0x20, 0x80, 
+0xa0, 0x6c, 0xe1, 0x6c, 0x40, 0x18, 0xa0, 0x64, 0x00, 0x20, 0xe0, 0x64, 
+0xa1, 0x6b, 0x22, 0x6d, 0x89, 0x18, 0xa1, 0x63, 0x20, 0x65, 0xb8, 0x6a, 
+0xc0, 0x46, 0x60, 0x65, 0x03, 0x23, 0x1b, 0x07, 0x78, 0x68, 0x18, 0x40, 
+0x78, 0x60, 0x61, 0x68, 0x36, 0x31, 0x94, 0x29, 0x04, 0xd8, 0x38, 0x23, 
+0x18, 0x43, 0x78, 0x60, 0x38, 0x20, 0x03, 0xe0, 0x94, 0x23, 0x18, 0x43, 
+0x78, 0x60, 0x94, 0x20, 0xb8, 0x61, 0x39, 0x68, 0x78, 0x68, 0x02, 0x04, 
+0x12, 0x0c, 0x20, 0x1c, 0xcb, 0x1f, 0x05, 0x3b, 0xff, 0xf7, 0xd7, 0xfd, 
+0x02, 0x20, 0x60, 0x80, 0x38, 0x1c, 0xff, 0xf7, 0xdf, 0xfe, 0xb0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xfc, 0xf7, 0x11, 0xfa, 0x28, 0x01, 
+0x06, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 
+0x01, 0x39, 0x41, 0x63, 0xef, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 0x90, 0xb5, 0x00, 0x27, 
+0x0f, 0x4c, 0x0d, 0xe0, 0x42, 0x6b, 0x01, 0x3a, 
+0x42, 0x63, 0x00, 0x2a, 0x05, 0xdc, 0x02, 0x6b, 0xc0, 0x46, 0x42, 0x63, 
+0xc0, 0x6a, 0x01, 0xf0, 0xc6, 0xf9, 0x01, 0x37, 0x0b, 0x2f, 0x07, 0xd2, 
+0x38, 0x01, 0x00, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x6a, 
 0x00, 0x29, 0xe9, 0xd1, 0x01, 0x20, 0x40, 0x06, 0x03, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0xb0, 0x11, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60, 
-0x10, 0x49, 0xc8, 0x68, 0x01, 0x28, 0x19, 0xd1, 0xc8, 0x1d, 0x79, 0x30, 
-0x82, 0x88, 0x00, 0x2a, 0x14, 0xd0, 0x01, 0x3a, 0x82, 0x80, 0x82, 0x88, 
-0x00, 0x2a, 0x0f, 0xd1, 0xc2, 0x88, 0x00, 0x2a, 0x0a, 0xd1, 0x02, 0x23, 
-0xca, 0x6f, 0x1a, 0x43, 0xca, 0x67, 0x07, 0x49, 0xc0, 0x46, 0x0a, 0x60, 
-0x04, 0x21, 0x81, 0x80, 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0xc1, 0x80, 
-0x70, 0x47, 0x00, 0x00, 0x08, 0x83, 0x20, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0x00, 0x01, 0x11, 0x00, 0xb0, 0xb5, 0x07, 0x1c, 
-0x01, 0x23, 0xf8, 0x1d, 0x69, 0x30, 0x03, 0x73, 0x1d, 0x49, 0xca, 0x1d, 
-0x79, 0x32, 0xd4, 0x89, 0x60, 0x1c, 0xd0, 0x81, 0x55, 0x8a, 0x00, 0x20, 
-0xac, 0x42, 0x02, 0xdb, 0x53, 0x73, 0xd0, 0x81, 0x50, 0x83, 0x01, 0x23, 
-0x9b, 0x07, 0x3a, 0x6d, 0x1a, 0x43, 0x12, 0x68, 0xc0, 0x46, 0xba, 0x61, 
-0xfb, 0x69, 0x9a, 0x42, 0x06, 0xd1, 0xf8, 0x6c, 0x12, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x78, 0x61, 0x48, 0x69, 
-0xfa, 0x6c, 0x90, 0x43, 0x48, 0x61, 0x01, 0x21, 0x09, 0x05, 0xc8, 0x60, 
-0x38, 0x69, 0x02, 0x28, 0xf1, 0xd0, 0xb8, 0x69, 0xf9, 0x69, 0x41, 0x1a, 
-0x01, 0xd5, 0x78, 0x6d, 0x41, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 
-0xf9, 0x69, 0x09, 0x18, 0xf9, 0x61, 0x78, 0x6d, 0x81, 0x42, 0xe2, 0xd3, 
-0x08, 0x1a, 0xf8, 0x61, 0xdf, 0xe7, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0xb0, 0xf8, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0xff, 0x23, 
-0x21, 0x33, 0x9f, 0x42, 0x01, 0xd9, 0xff, 0x27, 0x21, 0x37, 0xe1, 0x6e, 
-0x38, 0x1c, 0x01, 0xf0, 0xcf, 0xfc, 0x2d, 0x4d, 0x00, 0x28, 0x13, 0xd1, 
-0xe0, 0x1d, 0x49, 0x30, 0x01, 0x7a, 0x01, 0x23, 0x19, 0x43, 0x01, 0x72, 
-0x29, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x29, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
-0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0xb4, 0xfc, 0x00, 0x20, 0xf8, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x20, 0x69, 0x01, 0x30, 0x20, 0x61, 0x23, 0x49, 
-0xc8, 0x1d, 0xb9, 0x30, 0xc2, 0x6a, 0x92, 0x00, 0x51, 0x18, 0xc0, 0x31, 
-0xcf, 0x60, 0xc1, 0x6a, 0x01, 0x31, 0x89, 0x07, 0x89, 0x0f, 0xc1, 0x62, 
-0x20, 0x6b, 0xc2, 0x19, 0x61, 0x6d, 0x8a, 0x42, 0x03, 0xd8, 0x23, 0x22, 
-0x12, 0x05, 0x3a, 0x43, 0x05, 0xe0, 0x09, 0x1a, 0x7e, 0x1a, 0x07, 0xd1, 
-0x23, 0x22, 0x12, 0x05, 0x0a, 0x43, 0x00, 0x92, 0x61, 0x6e, 0x09, 0x18, 
-0xa2, 0x6e, 0x10, 0xe0, 0x11, 0x22, 0x52, 0x05, 0x0a, 0x43, 0x00, 0x92, 
-0x61, 0x6e, 0x09, 0x18, 0x00, 0x20, 0xa2, 0x6e, 0x2b, 0x1c, 0x01, 0xf0, 
-0x81, 0xfc, 0x23, 0x22, 0x12, 0x05, 0x32, 0x43, 0x00, 0x92, 0x61, 0x6e, 
-0xa2, 0x6e, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0x77, 0xfc, 0x20, 0x6b, 
-0xc0, 0x19, 0x00, 0x09, 0x00, 0x01, 0x61, 0x6d, 0x81, 0x42, 0x00, 0xd8, 
-0x40, 0x1a, 0x20, 0x63, 0x38, 0x1c, 0xb8, 0xe7, 0x44, 0x80, 0x20, 0x40, 
-0x04, 0x00, 0x1b, 0x02, 0xf8, 0x28, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 
-0x80, 0xb5, 0x01, 0x20, 0xc0, 0x03, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x60, 
-0x0c, 0x49, 0xc8, 0x1d, 0x49, 0x30, 0x02, 0x7a, 0x00, 0x27, 0x00, 0x2a, 
-0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7, 0x39, 0xff, 0x08, 0x49, 
-0xc8, 0x1d, 0x49, 0x30, 0x02, 0x7a, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 
-0x08, 0x1c, 0xff, 0xf7, 0x2f, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x00, 0x00, 0xb0, 0xd0, 0x2c, 0x00, 0x80, 0x50, 0x2c, 0x00, 0x80, 
-0x90, 0xb5, 0x07, 0x1c, 0x10, 0x20, 0x18, 0x49, 0xc0, 0x46, 0x08, 0x60, 
-0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 0x16, 0x48, 0xc4, 0x1d, 0xb9, 0x34, 
-0x21, 0x6b, 0x89, 0x00, 0x09, 0x18, 0xc0, 0x31, 0xc9, 0x68, 0x7a, 0x68, 
-0x92, 0x00, 0xd2, 0x19, 0x51, 0x64, 0x21, 0x6b, 0x89, 0x00, 0x08, 0x18, 
-0xc0, 0x30, 0xc1, 0x68, 0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 
-0x01, 0xf0, 0xa6, 0xfa, 0x01, 0x23, 0x78, 0x68, 
-0x58, 0x40, 0x78, 0x60, 0x20, 0x6b, 0x01, 0x30, 0x80, 0x07, 0x80, 0x0f, 
-0x20, 0x63, 0xf8, 0x1d, 0x19, 0x30, 0x40, 0x79, 0x00, 0x28, 0x02, 0xd1, 
-0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x00, 0x00, 0xb0, 0xe8, 0x0d, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 
-0x39, 0x48, 0x80, 0x68, 0x00, 0x28, 0x05, 0xd0, 0xb8, 0x6a, 0xc0, 0x68, 
-0x80, 0x09, 0x01, 0xd3, 0x02, 0x20, 0x00, 0xe0, 0x78, 0x6f, 0xfc, 0xf7, 
-0x9d, 0xf8, 0x04, 0x1c, 0x06, 0xd1, 0x01, 0x20, 0xf9, 0x1d, 0x19, 0x31, 
-0x08, 0x71, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf8, 0x6c, 0x2f, 0x49, 
-0xc0, 0x46, 0x08, 0x60, 0xba, 0x6a, 0x38, 0x1c, 0x21, 0x1c, 0x00, 0xf0, 
-0x59, 0xf8, 0x67, 0x62, 0x00, 0x28, 0x03, 0xd1, 0x20, 0x1c, 0x00, 0xf0, 
-0x0b, 0xfd, 0xec, 0xe7, 0xf9, 0x6d, 0x09, 0x68, 0x09, 0x18, 0x09, 0x09, 
-0x09, 0x01, 0x7a, 0x6d, 0x8a, 0x42, 0x00, 0xd8, 0x89, 0x1a, 0xa1, 0x62, 
-0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x4a, 0x6c, 0x00, 0x2a, 0x07, 0xd0, 
-0x4a, 0x6c, 0x12, 0x1a, 0x4a, 0x64, 0x80, 0x08, 0x80, 0x00, 0xb9, 0x6a, 
-0x08, 0x18, 0xb8, 0x62, 0x38, 0x68, 0xb9, 0x6a, 0x80, 0x00, 0xc0, 0x19, 
-0x42, 0x6b, 0x91, 0x42, 0x0e, 0xd3, 0x00, 0x21, 0x41, 0x64, 0xb8, 0x6a, 
-0x39, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x49, 0x6b, 0x40, 0x1a, 0xb8, 0x62, 
-0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0xc9, 0x6b, 0x40, 0x18, 0xb8, 0x62, 
-0xb8, 0x68, 0x81, 0x00, 0xc9, 0x19, 0x49, 0x6c, 0x00, 0x29, 0xb8, 0xd1, 
-0xb9, 0x6a, 0xfa, 0x6b, 0x91, 0x42, 0xb4, 0xd0, 0x3a, 0x6c, 0x91, 0x42, 
-0xb1, 0xd0, 0x01, 0x23, 0x58, 0x40, 0xb8, 0x60, 0x80, 0x00, 0xc0, 0x19, 
-0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf8, 0x68, 0x00, 0x28, 0x01, 0xd0, 
-0x01, 0x38, 0xf8, 0x60, 0x38, 0x69, 0x00, 0x28, 0xa1, 0xd0, 0x01, 0x38, 
-0x38, 0x61, 0x9e, 0xe7, 0xe8, 0x18, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 
-0xf7, 0xb5, 0x90, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 0x00, 0x20, 0x05, 0x90, 
-0x02, 0x90, 0x00, 0x22, 0x01, 0x92, 0xf9, 0x48, 0x80, 0x6a, 0xc0, 0x46, 
-0xa8, 0x61, 0xa0, 0x68, 0x81, 0x00, 0x09, 0x19, 0x49, 0x6b, 0xc0, 0x46, 
-0x20, 0x60, 0xe1, 0x62, 0x12, 0x9a, 0xd0, 0x68, 0xc0, 0x46, 0xa8, 0x60, 
-0x12, 0x9a, 0x51, 0x78, 0xc0, 0x46, 0x0c, 0x91, 0xf0, 0x48, 0xc0, 0x46, 
-0x03, 0x90, 0xd7, 0x1d, 0x09, 0x37, 0xe0, 0x6a, 0xc1, 0x1b, 0x09, 0x09, 
-0xe3, 0x1d, 0x19, 0x33, 0x0c, 0x9a, 0xc0, 0x46, 0x0f, 0x93, 0xeb, 0x4b, 
-0xc0, 0x46, 0x0e, 0x93, 0x91, 0x42, 0x01, 0xd3, 0xb8, 0x42, 0x21, 0xd8, 
-0xe1, 0x68, 0x02, 0x29, 0x1e, 0xd2, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 
-0x48, 0x71, 0x00, 0x20, 0x03, 0x99, 0x01, 0xf0, 0x5b, 0xfb, 0x00, 0x28, 
-0x03, 0xd1, 0x0e, 0x9b, 0x98, 0x6b, 0x01, 0x30, 0x98, 0x63, 0x01, 0x20, 
-0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 0xaf, 0x61, 0xdd, 0x4a, 0xc0, 0x46, 
-0x00, 0x92, 0xdd, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0xdc, 0x4b, 0x00, 0x20, 
-0x01, 0xf0, 0x3e, 0xfb, 0x38, 0x1c, 0x5c, 0xe3, 0xb8, 0x42, 0x03, 0xd8, 
-0x20, 0x1c, 0x00, 0xf0, 0x7b, 0xfc, 0x07, 0x1c, 0xd7, 0x48, 0x80, 0x68, 
-0x00, 0x28, 0x64, 0xd0, 0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 
-0x60, 0xd1, 0x05, 0x98, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x05, 0x90, 
-0x38, 0x78, 0xf0, 0x23, 0x18, 0x40, 0x58, 0xd1, 0xe0, 0x6a, 0xc0, 0x1b, 
-0x00, 0x09, 0x0c, 0x99, 0x88, 0x42, 0x02, 0xd2, 
-0xe0, 0x68, 0x02, 0x28, 0x05, 0xd3, 0xcb, 0x49, 0x88, 0x68, 0x00, 0xf0, 
-0x87, 0xff, 0x06, 0x1c, 0x06, 0xd1, 0x03, 0x9b, 0x28, 0x1c, 0x39, 0x1c, 
-0x22, 0x1c, 0x00, 0xf0, 0x8b, 0xfc, 0x16, 0xe1, 0x2e, 0x62, 0xf8, 0x68, 
-0x00, 0x28, 0x0d, 0xd0, 0xb8, 0x89, 0x00, 0x28, 0x03, 0xd0, 0xc1, 0x49, 
-0xc9, 0x68, 0x00, 0xf0, 0x74, 0xff, 0xf8, 0x89, 0x00, 0x28, 0x03, 0xd0, 
-0xbd, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x6d, 0xff, 0x7a, 0x68, 0xc0, 0x46, 
-0x72, 0x61, 0xb9, 0x68, 0xc0, 0x46, 0xb1, 0x61, 0x30, 0x1c, 0xb8, 0x49, 
-0x09, 0x68, 0x00, 0xf0, 0x62, 0xff, 0x00, 0x28, 0x17, 0xd1, 0x30, 0x1c, 
-0xb4, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x5b, 0xff, 0x10, 0x37, 0xe0, 0x6a, 
-0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x27, 0xfc, 0x07, 0x1c, 
-0x68, 0x68, 0xaf, 0x4b, 0x18, 0x43, 0x68, 0x60, 0x00, 0x20, 0xa8, 0x61, 
-0xac, 0x23, 0xa8, 0x68, 0x98, 0x43, 0xa8, 0x60, 0xb0, 0xe0, 0xa8, 0x69, 
-0xa8, 0x28, 0x01, 0xd2, 0xa8, 0x20, 0xa8, 0x61, 0x10, 0x37, 0xe0, 0x6a, 
-0xb8, 0x42, 0x6c, 0xd8, 0x9c, 0xe0, 0xa5, 0xe0, 0xa4, 0xe0, 0x10, 0x28, 
-0x68, 0xd1, 0x03, 0x23, 0x1b, 0x07, 0x68, 0x68, 0x18, 0x40, 0x01, 0x0f, 
-0x48, 0x01, 0x40, 0x1a, 0x80, 0x00, 0xa0, 0x4a, 0x82, 0x18, 0x01, 0x92, 
-0x78, 0x88, 0x42, 0x0b, 0x31, 0xd3, 0x82, 0x0b, 0x2f, 0xd3, 0x9d, 0x48, 
-0xc0, 0x46, 0x03, 0x90, 0x02, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x10, 0x80, 
-0x78, 0x88, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x60, 
-0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 0x01, 0x9a, 
-0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 
-0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x8f, 0x49, 0x40, 0x18, 
-0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x01, 0x9a, 0x50, 0x68, 0x36, 0x30, 
-0x94, 0x28, 0x01, 0xd8, 0x38, 0x20, 0x00, 0xe0, 0x94, 0x20, 0xa8, 0x61, 
-0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x28, 0xd8, 0x58, 0xe0, 0x7a, 0x88, 
-0x92, 0x0b, 0x03, 0xd3, 0x85, 0x48, 0xc0, 0x46, 0x03, 0x90, 0x23, 0xe0, 
-0x01, 0x22, 0x12, 0x03, 0x02, 0x40, 0x83, 0x4b, 0x1d, 0xd0, 0x03, 0x93, 
-0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x60, 0xb8, 0x68, 
-0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 0x01, 0x9a, 0xc0, 0x46, 
-0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 
-0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x75, 0x49, 0x40, 0x18, 0x01, 0x9a, 
-0xc0, 0x46, 0x50, 0x63, 0x02, 0xe0, 0x33, 0xe0, 0x2a, 0xe0, 0x03, 0x93, 
-0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x12, 0x9a, 0x50, 0x78, 
-0x05, 0x99, 0x43, 0x1a, 0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 
-0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x92, 0xfb, 0x07, 0x1c, 0x01, 0x9a, 
-0x50, 0x6b, 0x91, 0x6b, 0x09, 0x01, 0x40, 0x18, 0x0b, 0x9b, 0x21, 0x1c, 
-0x3a, 0x1c, 0xff, 0xf7, 0x7b, 0xfb, 0x01, 0x9a, 0xc0, 0x46, 0xd0, 0x64, 
-0x01, 0x9a, 0x0b, 0x9b, 0xc0, 0x46, 0x13, 0x65, 0x01, 0x23, 0x5b, 0x06, 
-0x68, 0x68, 0x18, 0x43, 0x68, 0x60, 0x00, 0x20, 0xa8, 0x61, 0x0d, 0xe0, 
+0x08, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0xb0, 0x10, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60, 
+0x0f, 0x49, 0xc8, 0x68, 0x01, 0x28, 0x17, 0xd1, 0xc8, 0x1d, 0x79, 0x30, 
+0x02, 0x89, 0x00, 0x2a, 0x12, 0xd0, 0x01, 0x3a, 0x02, 0x81, 0x02, 0x89, 
+0x00, 0x2a, 0x0d, 0xd1, 0x42, 0x89, 0x00, 0x2a, 0x08, 0xd1, 0xc9, 0x6f, 
+0x02, 0x23, 0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 0x04, 0x21, 0x01, 0x81, 
+0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x41, 0x81, 0x70, 0x47, 0x00, 0x00, 
+0x08, 0x83, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c, 
+0x01, 0x23, 0xf8, 0x1d, 0x69, 0x30, 0x03, 0x73, 0x1e, 0x48, 0xc2, 0x1d, 
+0x79, 0x32, 0x54, 0x8a, 0x61, 0x1c, 0x51, 0x82, 0xd5, 0x8a, 0x00, 0x21, 
+0xac, 0x42, 0x04, 0xdb, 0xc4, 0x1d, 0x89, 0x34, 0x63, 0x70, 0x51, 0x82, 
+0xd1, 0x83, 0x01, 0x23, 0x9b, 0x07, 0x3a, 0x6d, 0x1a, 0x43, 0x12, 0x68, 
+0xc0, 0x46, 0xba, 0x61, 0xfb, 0x69, 0x9a, 0x42, 0x06, 0xd1, 0xf8, 0x6c, 
+0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x79, 0x61, 0x41, 0x69, 0xfa, 0x6c, 0x91, 0x43, 0x41, 0x61, 0x01, 0x20, 
+0x00, 0x05, 0xc1, 0x60, 0x38, 0x69, 0x02, 0x28, 0xf1, 0xd0, 0xb8, 0x69, 
+0xf9, 0x69, 0x41, 0x1a, 0x01, 0xd5, 0x78, 0x6d, 0x41, 0x18, 0x38, 0x1c, 
+0x00, 0xf0, 0x0e, 0xf8, 0xf9, 0x69, 0x09, 0x18, 0xf9, 0x61, 0x78, 0x6d, 
+0x81, 0x42, 0xe2, 0xd3, 0x08, 0x1a, 0xf8, 0x61, 0xdf, 0xe7, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xf8, 0xb5, 0x04, 0x1c, 
+0x0f, 0x1c, 0xff, 0x23, 0x21, 0x33, 0x9f, 0x42, 0x01, 0xd9, 0xff, 0x27, 
+0x21, 0x37, 0xe1, 0x6e, 0x38, 0x1c, 0x01, 0xf0, 0xcb, 0xfc, 0x2d, 0x4d, 
+0x00, 0x28, 0x13, 0xd1, 0xe0, 0x1d, 0x49, 0x30, 0x01, 0x7a, 0x01, 0x23, 
+0x19, 0x43, 0x01, 0x72, 0x29, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x29, 0x48, 
+0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0xb0, 0xfc, 
+0x00, 0x20, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x20, 0x69, 0x01, 0x30, 
+0x20, 0x61, 0x23, 0x49, 0xc8, 0x1d, 0xb9, 0x30, 0x02, 0x6b, 0x92, 0x00, 
+0x51, 0x18, 0xc0, 0x31, 0x0f, 0x61, 0x01, 0x6b, 0x01, 0x31, 0x89, 0x07, 
+0x89, 0x0f, 0x01, 0x63, 0x20, 0x6b, 0xc2, 0x19, 0x61, 0x6d, 0x8a, 0x42, 
+0x03, 0xd8, 0x23, 0x22, 0x12, 0x05, 0x3a, 0x43, 0x05, 0xe0, 0x09, 0x1a, 
+0x7e, 0x1a, 0x07, 0xd1, 0x23, 0x22, 0x12, 0x05, 0x0a, 0x43, 0x00, 0x92, 
+0x61, 0x6e, 0x09, 0x18, 0xa2, 0x6e, 0x10, 0xe0, 0x11, 0x22, 0x52, 0x05, 
+0x0a, 0x43, 0x00, 0x92, 0x61, 0x6e, 0x09, 0x18, 0x00, 0x20, 0xa2, 0x6e, 
+0x2b, 0x1c, 0x01, 0xf0, 0x7d, 0xfc, 0x23, 0x22, 0x12, 0x05, 0x32, 0x43, 
+0x00, 0x92, 0x61, 0x6e, 0xa2, 0x6e, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 
+0x73, 0xfc, 0x20, 0x6b, 0xc0, 0x19, 0x00, 0x09, 0x00, 0x01, 0x61, 0x6d, 
+0x81, 0x42, 0x00, 0xd8, 0x40, 0x1a, 0x20, 0x63, 0x38, 0x1c, 0xb8, 0xe7, 
+0x44, 0x80, 0x20, 0x40, 0x04, 0x00, 0x1b, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x01, 0x20, 
+0xc0, 0x03, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0c, 0x49, 0xc8, 0x1d, 
+0x49, 0x30, 0x02, 0x7a, 0x00, 0x27, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 
+0x08, 0x1c, 0xff, 0xf7, 0x37, 0xff, 0x08, 0x49, 0xc8, 0x1d, 0x49, 0x30, 
+0x02, 0x7a, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7, 
+0x2d, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
+0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 
+0x10, 0x20, 0x18, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xf8, 0x68, 0x01, 0x30, 
+0xf8, 0x60, 0x16, 0x48, 0xc4, 0x1d, 0xb9, 0x34, 0x61, 0x6b, 0x89, 0x00, 
+0x09, 0x18, 0xc0, 0x31, 0x09, 0x69, 0x7a, 0x68, 0x92, 0x00, 0xd2, 0x19, 
+0x51, 0x64, 0x61, 0x6b, 0x89, 0x00, 0x08, 0x18, 0xc0, 0x30, 0x01, 0x69, 
+0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0x01, 0xf0, 0xa2, 0xfa, 
+0x01, 0x23, 0x78, 0x68, 0x58, 0x40, 0x78, 0x60, 0x60, 0x6b, 0x01, 0x30, 
+0x80, 0x07, 0x80, 0x0f, 0x60, 0x63, 0xf8, 0x1d, 0x19, 0x30, 0x40, 0x79, 
+0x00, 0x28, 0x02, 0xd1, 0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
+0x90, 0xb5, 0x07, 0x1c, 0x39, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x05, 0xd0, 
+0xb8, 0x6a, 0xc0, 0x68, 0x80, 0x09, 0x01, 0xd3, 0x02, 0x20, 0x00, 0xe0, 
+0x78, 0x6f, 0xfc, 0xf7, 0x63, 0xf8, 0x04, 0x1c, 0x06, 0xd1, 0x01, 0x20, 
+0xf9, 0x1d, 0x19, 0x31, 0x08, 0x71, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xf8, 0x6c, 0x2f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xba, 0x6a, 0x38, 0x1c, 
+0x21, 0x1c, 0x00, 0xf0, 0x59, 0xf8, 0x67, 0x62, 0x00, 0x28, 0x03, 0xd1, 
+0x20, 0x1c, 0x00, 0xf0, 0x0b, 0xfd, 0xec, 0xe7, 0xf9, 0x6d, 0x09, 0x68, 
+0x09, 0x18, 0x09, 0x09, 0x09, 0x01, 0x7a, 0x6d, 0x8a, 0x42, 0x00, 0xd8, 
+0x89, 0x1a, 0xa1, 0x62, 0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x4a, 0x6c, 
+0x00, 0x2a, 0x07, 0xd0, 0x4a, 0x6c, 0x12, 0x1a, 0x4a, 0x64, 0x80, 0x08, 
+0x80, 0x00, 0xb9, 0x6a, 0x08, 0x18, 0xb8, 0x62, 0x38, 0x68, 0xb9, 0x6a, 
+0x80, 0x00, 0xc0, 0x19, 0x42, 0x6b, 0x91, 0x42, 0x0e, 0xd3, 0x00, 0x21, 
+0x41, 0x64, 0xb8, 0x6a, 0x39, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x49, 0x6b, 
+0x40, 0x1a, 0xb8, 0x62, 0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0xc9, 0x6b, 
+0x40, 0x18, 0xb8, 0x62, 0xb8, 0x68, 0x81, 0x00, 0xc9, 0x19, 0x49, 0x6c, 
+0x00, 0x29, 0xb8, 0xd1, 0xb9, 0x6a, 0xfa, 0x6b, 0x91, 0x42, 0xb4, 0xd0, 
+0x3a, 0x6c, 0x91, 0x42, 0xb1, 0xd0, 0x01, 0x23, 0x58, 0x40, 0xb8, 0x60, 
+0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf8, 0x68, 
+0x00, 0x28, 0x01, 0xd0, 0x01, 0x38, 0xf8, 0x60, 0x38, 0x69, 0x00, 0x28, 
+0xa1, 0xd0, 0x01, 0x38, 0x38, 0x61, 0x9e, 0xe7, 0x68, 0x19, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0xb0, 0xf7, 0xb5, 0x90, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 
+0x00, 0x20, 0x05, 0x90, 0x02, 0x90, 0x00, 0x22, 0x01, 0x92, 0xf9, 0x48, 
+0xc0, 0x6a, 0xc0, 0x46, 0xa8, 0x61, 0xa0, 0x68, 0x81, 0x00, 0x09, 0x19, 
+0x49, 0x6b, 0xc0, 0x46, 0x20, 0x60, 0xe1, 0x62, 0x12, 0x9a, 0xd0, 0x68, 
+0xc0, 0x46, 0xa8, 0x60, 0x12, 0x9a, 0x51, 0x78, 0xc0, 0x46, 0x0c, 0x91, 
+0xf0, 0x48, 0xc0, 0x46, 0x03, 0x90, 0xd7, 0x1d, 0x09, 0x37, 0xe0, 0x6a, 
+0xc1, 0x1b, 0x09, 0x09, 0xe3, 0x1d, 0x19, 0x33, 0x0c, 0x9a, 0xc0, 0x46, 
+0x0f, 0x93, 0xeb, 0x4b, 0xc0, 0x46, 0x0e, 0x93, 
+0x91, 0x42, 0x01, 0xd3, 0xb8, 0x42, 0x21, 0xd8, 0xe1, 0x68, 0x02, 0x29, 
+0x1e, 0xd2, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x00, 0x20, 
+0x03, 0x99, 0x01, 0xf0, 0x57, 0xfb, 0x00, 0x28, 0x03, 0xd1, 0x0e, 0x9b, 
+0xd8, 0x6b, 0x01, 0x30, 0xd8, 0x63, 0x01, 0x20, 0x80, 0x06, 0x00, 0x27, 
+0x68, 0x60, 0xaf, 0x61, 0xdd, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xdd, 0x48, 
+0x01, 0x6d, 0x42, 0x6d, 0xdc, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0x3a, 0xfb, 
+0x38, 0x1c, 0x5c, 0xe3, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 
+0x7b, 0xfc, 0x07, 0x1c, 0xd7, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x64, 0xd0, 
+0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 0x60, 0xd1, 0x05, 0x98, 
+0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x05, 0x90, 0x38, 0x78, 0xf0, 0x23, 
+0x18, 0x40, 0x58, 0xd1, 0xe0, 0x6a, 0xc0, 0x1b, 0x00, 0x09, 0x0c, 0x99, 
+0x88, 0x42, 0x02, 0xd2, 0xe0, 0x68, 0x02, 0x28, 0x05, 0xd3, 0xcb, 0x49, 
+0x88, 0x68, 0x00, 0xf0, 0x83, 0xff, 0x06, 0x1c, 0x06, 0xd1, 0x03, 0x9b, 
+0x28, 0x1c, 0x39, 0x1c, 0x22, 0x1c, 0x00, 0xf0, 0x8b, 0xfc, 0x16, 0xe1, 
+0x2e, 0x62, 0xf8, 0x68, 0x00, 0x28, 0x0d, 0xd0, 0xb8, 0x89, 0x00, 0x28, 
+0x03, 0xd0, 0xc1, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x70, 0xff, 0xf8, 0x89, 
+0x00, 0x28, 0x03, 0xd0, 0xbd, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x69, 0xff, 
+0x7a, 0x68, 0xc0, 0x46, 0x72, 0x61, 0xb9, 0x68, 0xc0, 0x46, 0xb1, 0x61, 
+0x30, 0x1c, 0xb8, 0x49, 0x09, 0x68, 0x00, 0xf0, 0x5e, 0xff, 0x00, 0x28, 
+0x17, 0xd1, 0x30, 0x1c, 0xb4, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x57, 0xff, 
 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 
-0x71, 0xfb, 0x07, 0x1c, 0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 
-0x00, 0xd1, 0xf8, 0xe6, 0xa8, 0x69, 0x03, 0x99, 0x01, 0xf0, 0x2a, 0xfa, 
-0x00, 0x28, 0x2a, 0xd1, 0x38, 0x1c, 0x21, 0x1c, 
-0x00, 0xf0, 0x79, 0xfb, 0xa8, 0x68, 0x80, 0x09, 0x04, 0xd3, 0x30, 0x1c, 
-0x49, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x85, 0xfe, 0x41, 0x49, 0x00, 0x20, 
-0x01, 0xf0, 0x18, 0xfa, 0x00, 0x28, 0x04, 0xd1, 0x0e, 0x9b, 0x98, 0x6b, 
-0x01, 0x30, 0x98, 0x63, 0x11, 0xe0, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 
-0x48, 0x71, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 0xaf, 0x61, 0x3a, 0x4a, 
-0xc0, 0x46, 0x00, 0x92, 0x39, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x39, 0x4b, 
-0x00, 0x20, 0x01, 0xf0, 0xf7, 0xf9, 0x00, 0x20, 0x15, 0xe2, 0x05, 0x98, 
-0x0c, 0x99, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x0c, 0x90, 0x0b, 0x90, 
-0x0c, 0x98, 0x00, 0x28, 0x03, 0xd0, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 
-0x48, 0x71, 0x28, 0x68, 0xc0, 0x46, 0x04, 0x90, 0x00, 0x26, 0x00, 0x20, 
-0x08, 0x90, 0x00, 0x22, 0x0a, 0x92, 0x0c, 0x98, 0x01, 0x38, 0x0d, 0x90, 
-0xa3, 0xe0, 0x78, 0x88, 0x8a, 0x1b, 0x12, 0x04, 0x12, 0x0c, 0x90, 0x42, 
-0x05, 0xdd, 0x07, 0x92, 0x80, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x08, 0x90, 
-0x00, 0xe0, 0x07, 0x90, 0x08, 0x98, 0x00, 0x28, 0x07, 0xd1, 0x0d, 0x98, 
-0x0a, 0x9a, 0x90, 0x42, 0x07, 0xdd, 0x07, 0x98, 0x30, 0x18, 0x88, 0x42, 
-0x03, 0xd8, 0x01, 0x20, 0x40, 0x05, 0x06, 0x90, 0x1c, 0xe0, 0x11, 0x20, 
-0x40, 0x05, 0x06, 0x90, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd1, 
-0x20, 0x48, 0xc0, 0x46, 0x06, 0x90, 0xb1, 0x07, 0x89, 0x0f, 0x0f, 0xd0, 
-0x07, 0x98, 0xc0, 0x06, 0xc0, 0x0e, 0x08, 0xd0, 0x1e, 0x28, 0x09, 0xdb, 
-0x1e, 0x28, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 0x01, 0xe0, 0x02, 0x29, 
-0x02, 0xd3, 0x01, 0x20, 0x02, 0x90, 0xde, 0xe7, 0x0a, 0x9a, 0x00, 0x2a, 
-0x04, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x06, 0x98, 0x18, 0x43, 0x06, 0x90, 
-0x07, 0x98, 0x06, 0x99, 0x08, 0x43, 0x02, 0x1c, 0x00, 0x90, 0x04, 0x98, 
-0x83, 0x19, 0x1d, 0xe0, 0x68, 0x0e, 0x00, 0x80, 0x79, 0x48, 0xff, 0xff, 
-0xa8, 0x0e, 0x00, 0x80, 0x04, 0x00, 0x12, 0x02, 0xf8, 0x28, 0x00, 0x80, 
-0x44, 0x80, 0x20, 0x40, 0xe8, 0x18, 0x00, 0x80, 0xe0, 0x03, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0x80, 0xc8, 0x2a, 0x00, 0x80, 0xc9, 0x31, 0xff, 0xff, 
-0x58, 0x5f, 0x21, 0x40, 0x81, 0x3c, 0xff, 0xff, 0x41, 0x31, 0xff, 0xff, 
-0x00, 0x00, 0x32, 0x02, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 
-0x6f, 0xf9, 0x07, 0x98, 0x36, 0x18, 0x02, 0x98, 0x00, 0x28, 0x16, 0xd0, 
-0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x04, 0xd1, 0x09, 0x23, 0x5b, 0x04, 
-0x06, 0x98, 0x18, 0x43, 0x06, 0x90, 0x06, 0x98, 0xc2, 0x4a, 0x02, 0x43, 
-0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0xc1, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
-0x00, 0x20, 0x01, 0xf0, 0x55, 0xf9, 0x00, 0x20, 0x02, 0x90, 0x08, 0x98, 
-0x00, 0x28, 0x0b, 0xd1, 0x0b, 0x9b, 0x01, 0x3b, 0x0b, 0x93, 0x10, 0x37, 
-0xe0, 0x6a, 0xb8, 0x42, 0x0c, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x8a, 0xfa, 
-0x07, 0x1c, 0x07, 0xe0, 0x78, 0x68, 0x07, 0x9a, 0x80, 0x18, 0x78, 0x60, 
-0x78, 0x88, 0x07, 0x9a, 0x80, 0x1a, 0x78, 0x80, 0x0a, 0x9a, 0x50, 0x1c, 
-0x02, 0x04, 0x12, 0x0c, 0x0a, 0x92, 0x0c, 0x98, 0x0a, 0x9a, 0x82, 0x42, 
-0x03, 0xda, 0xa9, 0x69, 0xb1, 0x42, 0x00, 0xd9, 0x53, 0xe7, 0xa8, 0x69, 
-0xb0, 0x42, 0x6b, 0xd1, 0xa8, 0x68, 0x01, 0x09, 0x69, 0xd2, 0x08, 0x9a, 
-0x00, 0x2a, 0x56, 0xd0, 0x0c, 0x99, 0x0a, 0x9a, 0x8a, 0x42, 0x3e, 0xdb, 
-0xb1, 0x07, 0x89, 0x0f, 0x0c, 0xd0, 0x08, 0x9a, 
-0xd2, 0x06, 0xd2, 0x0e, 0x0b, 0xd0, 0x1e, 0x2a, 0x06, 0xdb, 0x1e, 0x2a, 
-0x02, 0xd1, 0x03, 0x29, 0x05, 0xd0, 0x01, 0xe0, 0x02, 0x29, 0x02, 0xd2, 
-0x02, 0x99, 0x00, 0x29, 0x21, 0xd0, 0x08, 0x9a, 0xc0, 0x46, 0x00, 0x92, 
-0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 
-0x05, 0xf9, 0x08, 0x98, 0x36, 0x18, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 
-0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x92, 0x48, 0x01, 0x22, 
-0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x8e, 0x48, 0x01, 0x6d, 
-0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0xf0, 0xf8, 0x00, 0x20, 0x02, 0x90, 
-0x15, 0xe0, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 
-0x00, 0xe0, 0x88, 0x48, 0x08, 0x9a, 0x02, 0x43, 0x00, 0xe0, 0x08, 0x9a, 
+0x27, 0xfc, 0x07, 0x1c, 0x68, 0x68, 0xaf, 0x4b, 0x18, 0x43, 0x68, 0x60, 
+0x00, 0x20, 0xa8, 0x61, 0xac, 0x23, 0xa8, 0x68, 0x98, 0x43, 0xa8, 0x60, 
+0xb0, 0xe0, 0xa8, 0x69, 0xa8, 0x28, 0x01, 0xd2, 0xa8, 0x20, 0xa8, 0x61, 
+0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x6c, 0xd8, 0x9c, 0xe0, 0xa5, 0xe0, 
+0xa4, 0xe0, 0x10, 0x28, 0x68, 0xd1, 0x03, 0x23, 0x1b, 0x07, 0x68, 0x68, 
+0x18, 0x40, 0x01, 0x0f, 0x48, 0x01, 0x40, 0x1a, 0x80, 0x00, 0xa0, 0x4a, 
+0x82, 0x18, 0x01, 0x92, 0x78, 0x88, 0x42, 0x0b, 0x31, 0xd3, 0x82, 0x0b, 
+0x2f, 0xd3, 0x9d, 0x48, 0xc0, 0x46, 0x03, 0x90, 0x02, 0x20, 0x01, 0x9a, 
+0xc0, 0x46, 0x10, 0x80, 0x78, 0x88, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 
+0xc0, 0x46, 0x50, 0x60, 0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 
+0x78, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 
+0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 
+0x8f, 0x49, 0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x01, 0x9a, 
+0x50, 0x68, 0x36, 0x30, 0x94, 0x28, 0x01, 0xd8, 0x38, 0x20, 0x00, 0xe0, 
+0x94, 0x20, 0xa8, 0x61, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x28, 0xd8, 
+0x58, 0xe0, 0x7a, 0x88, 0x92, 0x0b, 0x03, 0xd3, 0x85, 0x48, 0xc0, 0x46, 
+0x03, 0x90, 0x23, 0xe0, 0x01, 0x22, 0x12, 0x03, 0x02, 0x40, 0x83, 0x4b, 
+0x1d, 0xd0, 0x03, 0x93, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 
+0x50, 0x60, 0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 
+0x01, 0x9a, 0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 
+0x90, 0x64, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x75, 0x49, 
+0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 
+0x02, 0xe0, 0x33, 0xe0, 0x2a, 0xe0, 0x03, 0x93, 0x01, 0x20, 0x0f, 0x99, 
+0xc0, 0x46, 0x48, 0x71, 0x12, 0x9a, 0x50, 0x78, 0x05, 0x99, 0x43, 0x1a, 
+0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 
+0x00, 0xf0, 0x92, 0xfb, 0x07, 0x1c, 0x01, 0x9a, 0x50, 0x6b, 0x91, 0x6b, 
+0x09, 0x01, 0x40, 0x18, 0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 
+0x7d, 0xfb, 0x01, 0x9a, 0xc0, 0x46, 0xd0, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 
+0xc0, 0x46, 0x13, 0x65, 0x01, 0x23, 0x5b, 0x06, 0x68, 0x68, 0x18, 0x43, 
+0x68, 0x60, 0x00, 0x20, 0xa8, 0x61, 0x0d, 0xe0, 0x10, 0x37, 0xe0, 0x6a, 
+0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x71, 0xfb, 0x07, 0x1c, 
+0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 0x00, 0xd1, 0xf8, 0xe6, 
+0xa8, 0x69, 0x03, 0x99, 0x01, 0xf0, 0x26, 0xfa, 0x00, 0x28, 0x2a, 0xd1, 
+0x38, 0x1c, 0x21, 0x1c, 0x00, 0xf0, 0x79, 0xfb, 0xa8, 0x68, 0x80, 0x09, 
+0x04, 0xd3, 0x30, 0x1c, 0x49, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x81, 0xfe, 
+0x41, 0x49, 0x00, 0x20, 0x01, 0xf0, 0x14, 0xfa, 0x00, 0x28, 0x04, 0xd1, 
+0x0e, 0x9b, 0xd8, 0x6b, 0x01, 0x30, 0xd8, 0x63, 0x11, 0xe0, 0x01, 0x20, 
+0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 
+0xaf, 0x61, 0x3a, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x39, 0x48, 0x01, 0x6d, 
+0x42, 0x6d, 0x39, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0xf3, 0xf9, 0x00, 0x20, 
+0x15, 0xe2, 0x05, 0x98, 0x0c, 0x99, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c, 
+0x0c, 0x90, 0x0b, 0x90, 0x0c, 0x98, 0x00, 0x28, 0x03, 0xd0, 0x01, 0x20, 
+0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x28, 0x68, 0xc0, 0x46, 0x04, 0x90, 
+0x00, 0x26, 0x00, 0x20, 0x08, 0x90, 0x00, 0x22, 0x0a, 0x92, 0x0c, 0x98, 
+0x01, 0x38, 0x0d, 0x90, 0xa3, 0xe0, 0x78, 0x88, 0x8a, 0x1b, 0x12, 0x04, 
+0x12, 0x0c, 0x90, 0x42, 0x05, 0xdd, 0x07, 0x92, 0x80, 0x1a, 0x00, 0x04, 
+0x00, 0x0c, 0x08, 0x90, 0x00, 0xe0, 0x07, 0x90, 0x08, 0x98, 0x00, 0x28, 
+0x07, 0xd1, 0x0d, 0x98, 0x0a, 0x9a, 0x90, 0x42, 0x07, 0xdd, 0x07, 0x98, 
+0x30, 0x18, 0x88, 0x42, 0x03, 0xd8, 0x01, 0x20, 0x40, 0x05, 0x06, 0x90, 
+0x1c, 0xe0, 0x11, 0x20, 0x40, 0x05, 0x06, 0x90, 0xa8, 0x68, 0x8c, 0x23, 
+0x18, 0x40, 0x02, 0xd1, 0x20, 0x48, 0xc0, 0x46, 0x06, 0x90, 0xb1, 0x07, 
+0x89, 0x0f, 0x0f, 0xd0, 0x07, 0x98, 0xc0, 0x06, 0xc0, 0x0e, 0x08, 0xd0, 
+0x1e, 0x28, 0x09, 0xdb, 0x1e, 0x28, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 
+0x01, 0xe0, 0x02, 0x29, 0x02, 0xd3, 0x01, 0x20, 0x02, 0x90, 0xde, 0xe7, 
+0x0a, 0x9a, 0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x06, 0x98, 
+0x18, 0x43, 0x06, 0x90, 0x07, 0x98, 0x06, 0x99, 0x08, 0x43, 0x02, 0x1c, 
+0x00, 0x90, 0x04, 0x98, 0x83, 0x19, 0x1d, 0xe0, 0xe8, 0x0e, 0x00, 0x80, 
+0xed, 0x48, 0xff, 0xff, 0x28, 0x0f, 0x00, 0x80, 0x04, 0x00, 0x12, 0x02, 
+0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x68, 0x19, 0x00, 0x80, 
+0x60, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 
+0x41, 0x32, 0xff, 0xff, 0x58, 0x5f, 0x21, 0x40, 0xf9, 0x3c, 0xff, 0xff, 
+0xb9, 0x31, 0xff, 0xff, 0x00, 0x00, 0x32, 0x02, 0x00, 0x20, 0x3a, 0x1d, 
+0x06, 0xca, 0x01, 0xf0, 0x6b, 0xf9, 0x07, 0x98, 0x36, 0x18, 0x02, 0x98, 
+0x00, 0x28, 0x16, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x04, 0xd1, 
+0x09, 0x23, 0x5b, 0x04, 0x06, 0x98, 0x18, 0x43, 
+0x06, 0x90, 0x06, 0x98, 0xc2, 0x4a, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 
+0x83, 0x19, 0xc1, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 
+0x51, 0xf9, 0x00, 0x20, 0x02, 0x90, 0x08, 0x98, 0x00, 0x28, 0x0b, 0xd1, 
+0x0b, 0x9b, 0x01, 0x3b, 0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 
+0x0c, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x8a, 0xfa, 0x07, 0x1c, 0x07, 0xe0, 
+0x78, 0x68, 0x07, 0x9a, 0x80, 0x18, 0x78, 0x60, 0x78, 0x88, 0x07, 0x9a, 
+0x80, 0x1a, 0x78, 0x80, 0x0a, 0x9a, 0x50, 0x1c, 0x02, 0x04, 0x12, 0x0c, 
+0x0a, 0x92, 0x0c, 0x98, 0x0a, 0x9a, 0x82, 0x42, 0x03, 0xda, 0xa9, 0x69, 
+0xb1, 0x42, 0x00, 0xd9, 0x53, 0xe7, 0xa8, 0x69, 0xb0, 0x42, 0x6b, 0xd1, 
+0xa8, 0x68, 0x01, 0x09, 0x69, 0xd2, 0x08, 0x9a, 0x00, 0x2a, 0x56, 0xd0, 
+0x0c, 0x99, 0x0a, 0x9a, 0x8a, 0x42, 0x3e, 0xdb, 0xb1, 0x07, 0x89, 0x0f, 
+0x0c, 0xd0, 0x08, 0x9a, 0xd2, 0x06, 0xd2, 0x0e, 0x0b, 0xd0, 0x1e, 0x2a, 
+0x06, 0xdb, 0x1e, 0x2a, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd0, 0x01, 0xe0, 
+0x02, 0x29, 0x02, 0xd2, 0x02, 0x99, 0x00, 0x29, 0x21, 0xd0, 0x08, 0x9a, 
 0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 
-0x06, 0xca, 0x01, 0xf0, 0xd9, 0xf8, 0x08, 0x98, 0x36, 0x18, 0x10, 0x37, 
-0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x14, 0xfa, 
-0x07, 0x1c, 0x68, 0x68, 0x80, 0x0e, 0x6b, 0xd2, 0x0a, 0x98, 0xc0, 0x46, 
-0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 0x5c, 0xda, 0x0d, 0x98, 0x09, 0x99, 
-0x88, 0x42, 0x03, 0xd0, 0x7a, 0x88, 0x1e, 0xe0, 0x5f, 0xe0, 0x5e, 0xe0, 
-0x78, 0x88, 0x01, 0x22, 0x52, 0x06, 0x02, 0x43, 0xa9, 0x68, 0x8c, 0x23, 
-0x19, 0x40, 0x02, 0xd1, 0x09, 0x23, 0x5b, 0x04, 0x1a, 0x43, 0xb1, 0x07, 
-0x89, 0x0f, 0x0e, 0xd0, 0xc3, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 
-0x09, 0xdb, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 0x01, 0xe0, 
-0x02, 0x29, 0x02, 0xd3, 0x01, 0x21, 0x02, 0x91, 0x02, 0x1c, 0x09, 0x98, 
-0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x1a, 0x43, 0x00, 0x92, 
-0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 
-0x93, 0xf8, 0x78, 0x88, 0x86, 0x19, 0x10, 0x37, 0x02, 0x98, 0x00, 0x28, 
-0x14, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 
-0x40, 0x06, 0x00, 0xe0, 0x57, 0x48, 0x01, 0x22, 0x02, 0x43, 0x00, 0x92, 
-0x04, 0x98, 0x83, 0x19, 0x53, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 
-0x01, 0xf0, 0x7a, 0xf8, 0x00, 0x20, 0x02, 0x90, 0xe0, 0x6a, 0xb8, 0x42, 
-0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9, 0x07, 0x1c, 0x09, 0x98, 
-0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 
-0xa2, 0xdb, 0x68, 0x68, 0x30, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x68, 0x60, 
-0xe8, 0x6a, 0x00, 0xf0, 0x7b, 0xfa, 0x28, 0xe0, 0x27, 0xe0, 0xa8, 0x68, 
-0x00, 0x09, 0x14, 0xd3, 0x68, 0x68, 0x80, 0x0e, 0x15, 0xd2, 0x01, 0x9a, 
-0x00, 0x2a, 0x12, 0xd0, 0x01, 0x9a, 0x50, 0x6b, 0x0b, 0x9b, 0x21, 0x1c, 
-0x3a, 0x1c, 0xff, 0xf7, 0x87, 0xf9, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 
-0x01, 0x9a, 0x0b, 0x9b, 0xc0, 0x46, 0x93, 0x63, 0x03, 0xe0, 0xe8, 0x6a, 
-0x31, 0x1c, 0x00, 0xf0, 0x5d, 0xfa, 0x68, 0x68, 0x30, 0x43, 0x68, 0x60, 
-0xa8, 0x69, 0xb0, 0x42, 0x05, 0xd9, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x1b, 
-0x00, 0xf0, 0xee, 0xf9, 0xae, 0x61, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 
-0x0b, 0xd0, 0x2f, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0xc3, 0x1f, 
-0x05, 0x3b, 0x2a, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 
-0x27, 0xf8, 0x01, 0x23, 0x9b, 0x07, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 
-0xc0, 0x46, 0xa0, 0x61, 0xe1, 0x69, 0x81, 0x42, 
-0x12, 0xd0, 0x22, 0x69, 0x02, 0x2a, 0x0f, 0xd2, 0x41, 0x1a, 0x01, 0xd5, 
-0x60, 0x6d, 0x41, 0x18, 0x20, 0x1c, 0xff, 0xf7, 0x3f, 0xfb, 0xe1, 0x69, 
-0x40, 0x18, 0xe0, 0x61, 0x61, 0x6d, 0x88, 0x42, 0x24, 0xd3, 0x40, 0x1a, 
-0xe0, 0x61, 0x21, 0xe0, 0x81, 0x42, 0x1f, 0xd1, 0x20, 0x69, 0x02, 0x28, 
-0x1c, 0xd2, 0x01, 0x20, 0x60, 0x61, 0x18, 0x48, 0x41, 0x69, 0xe2, 0x6c, 
-0x0a, 0x43, 0x42, 0x61, 0x81, 0x69, 0xe3, 0x6c, 0x99, 0x43, 0x81, 0x61, 
-0x01, 0x21, 0x09, 0x05, 0xca, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x08, 0x61, 
-0x8b, 0x02, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61, 
-0xe1, 0x69, 0x81, 0x42, 0x02, 0xd0, 0x20, 0x1c, 0xff, 0xf7, 0xce, 0xfa, 
-0x28, 0x1c, 0x00, 0xf0, 0x0f, 0xf9, 0x0c, 0x98, 0x05, 0x99, 0x40, 0x18, 
-0x00, 0x01, 0x10, 0x30, 0x68, 0x61, 0x13, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xf8, 0x28, 0x00, 0x80, 
-0x00, 0x00, 0x12, 0x02, 0x04, 0x00, 0x52, 0x02, 0xe8, 0x0d, 0x00, 0x80, 
-0xf0, 0xb5, 0x40, 0x20, 0x2d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0, 
-0x03, 0xf9, 0x07, 0x1c, 0x81, 0x69, 0x44, 0x6a, 0xa0, 0x6f, 0x00, 0xf0, 
-0x49, 0xfe, 0x00, 0x20, 0xe1, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x79, 0x68, 
-0xc9, 0x0e, 0x09, 0xd3, 0xf8, 0x6a, 0x00, 0x01, 0x24, 0x49, 0x40, 0x18, 
-0x24, 0x4b, 0xc0, 0x18, 0x01, 0x68, 0x01, 0x39, 0x01, 0x60, 0x36, 0xe0, 
-0xe1, 0x6d, 0x09, 0x68, 0x22, 0x6e, 0xc0, 0x46, 0x11, 0x60, 0x20, 0x4e, 
-0xf5, 0x1d, 0x79, 0x35, 0x01, 0x23, 0xa9, 0x6b, 0x19, 0x43, 0xa9, 0x63, 
-0xb9, 0x6a, 0xe2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 0xb9, 0x6a, 0x22, 0x6e, 
-0xc0, 0x46, 0x11, 0x60, 0x61, 0x69, 0x00, 0x29, 0x04, 0xd1, 0x69, 0x6b, 
-0x01, 0x31, 0x69, 0x63, 0x08, 0x29, 0x07, 0xd3, 0x68, 0x63, 0x01, 0x20, 
-0x00, 0xf0, 0x86, 0xf8, 0xa8, 0x6b, 0x40, 0x08, 0x40, 0x00, 0xa8, 0x63, 
-0x78, 0x68, 0x81, 0x0e, 0x0f, 0xd2, 0x0b, 0x23, 0x1b, 0x02, 0xf1, 0x18, 
-0x89, 0x68, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x08, 0x04, 0xd2, 0x20, 0x1c, 
-0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 
-0x05, 0xfa, 0x38, 0x1c, 0xfb, 0xf7, 0x4a, 0xfc, 0x20, 0x1c, 0x00, 0xf0, 
-0x0b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
-0x1c, 0x1c, 0x00, 0x80, 0xb4, 0x0c, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0x80, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x19, 0x30, 0x01, 0x79, 0x00, 0x29, 
-0x04, 0xd0, 0x00, 0x21, 0x01, 0x71, 0x38, 0x1c, 0xff, 0xf7, 0x56, 0xfb, 
-0xf8, 0x68, 0x02, 0x28, 0x0d, 0xd0, 0xb8, 0x68, 0x80, 0x00, 0xc2, 0x19, 
-0x50, 0x6c, 0x00, 0x28, 0x11, 0xd0, 0xb8, 0x6a, 0x41, 0x78, 0x09, 0x01, 
-0x10, 0x31, 0x52, 0x6b, 0x10, 0x1a, 0x88, 0x42, 0x05, 0xd3, 0x38, 0x1c, 
-0xff, 0xf7, 0x42, 0xfb, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 
-0xff, 0xf7, 0x2a, 0xfa, 0xf8, 0xe7, 0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 
-0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf1, 0xe7, 0xb0, 0xb5, 0x87, 0xb0, 
-0x0f, 0x1c, 0x80, 0x6f, 0xc0, 0x46, 0x00, 0x90, 0x00, 0x24, 0x13, 0x4d, 
-0x0b, 0x23, 0x1b, 0x02, 0xe8, 0x18, 0x40, 0x69, 0x00, 0x28, 0x17, 0xd0, 
-0x69, 0x46, 0xa2, 0x00, 0x52, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xd2, 0x18, 
-0x52, 0x69, 0x38, 0x1c, 0x00, 0xf0, 0x96, 0xfb, 0x00, 0x28, 0x09, 0xd1, 
-0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 0x0b, 0x23, 
-0x1b, 0x02, 0xc0, 0x18, 0x40, 0x69, 0x00, 0x28, 0xea, 0xd1, 0x01, 0xe0, 
-0x01, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x9d, 0xf9, 0x07, 0xb0, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0xb8, 0xb5, 0xc2, 0x07, 0xd2, 0x0f, 0x16, 0x4c, 0x16, 0x49, 0x01, 0xd0, 
-0x08, 0x22, 0x08, 0xe0, 0x82, 0x08, 0x05, 0xd3, 0x0c, 0x22, 0xa4, 0x18, 
-0x0b, 0x68, 0xdf, 0x1d, 0x15, 0x37, 0x03, 0xe0, 0x1c, 0x22, 0x0b, 0x68, 
-0xdf, 0x1d, 0x09, 0x37, 0x0f, 0x4b, 0x1d, 0x7b, 0x00, 0x2d, 0x13, 0xd0, 
-0x5b, 0x7b, 0x00, 0x2b, 0x10, 0xd0, 0x01, 0x23, 0x5b, 0x06, 0x1a, 0x43, 
-0x00, 0x28, 0x01, 0xd1, 0x5b, 0x08, 0x1a, 0x43, 0x00, 0x92, 0x4a, 0x68, 
-0x01, 0x20, 0x39, 0x1c, 0x23, 0x1c, 0x00, 0xf0, 0xe3, 0xfe, 0xb8, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x03, 0x23, 0x1b, 0x06, 0x1a, 0x43, 0xf1, 0xe7, 
-0x3c, 0xef, 0x20, 0x40, 0xf8, 0x28, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 
-0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x4a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 
-0x48, 0x60, 0x02, 0xe0, 0x8a, 0x68, 0xc0, 0x46, 0xd0, 0x61, 0x88, 0x60, 
-0x70, 0x47, 0x00, 0x00, 0xa8, 0x0e, 0x00, 0x80, 0x03, 0x49, 0x48, 0x68, 
-0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 0x4a, 0x60, 0x70, 0x47, 
-0xa8, 0x0e, 0x00, 0x80, 0x01, 0x1c, 0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 
-0x88, 0x60, 0xca, 0x68, 0x01, 0x3a, 0xca, 0x60, 0x0a, 0x69, 0x01, 0x3a, 
-0x80, 0x00, 0x0a, 0x61, 0x42, 0x18, 0xd0, 0x6b, 0x53, 0x6b, 0xc0, 0x46, 
-0xcb, 0x62, 0x0b, 0x68, 0x9b, 0x00, 0x59, 0x18, 0x49, 0x6c, 0x53, 0x6c, 
-0xc9, 0x18, 0x51, 0x64, 0x70, 0x47, 0x8a, 0x68, 0x92, 0x00, 0x52, 0x18, 
-0xd3, 0x6b, 0x83, 0x42, 0x17, 0xd1, 0xd0, 0x1d, 0x3d, 0x30, 0x0a, 0x68, 
-0x92, 0x00, 0x52, 0x18, 0x52, 0x6c, 0x03, 0x68, 0x9a, 0x1a, 0x02, 0x60, 
-0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 0xca, 0x68, 0x01, 0x32, 
-0xca, 0x60, 0x0a, 0x69, 0x01, 0x32, 0x80, 0x00, 0x40, 0x18, 0x0a, 0x61, 
-0x40, 0x6b, 0xc0, 0x46, 0xc8, 0x62, 0x70, 0x47, 0xb8, 0xb5, 0x04, 0x1c, 
-0x1d, 0x1c, 0x17, 0x1c, 0x08, 0x1c, 0x39, 0x1c, 0xff, 0xf7, 0xd9, 0xff, 
-0x00, 0x20, 0x29, 0x1c, 0x00, 0xf0, 0x80, 0xfe, 0x01, 0x20, 0xf9, 0x1d, 
-0x19, 0x31, 0x48, 0x71, 0x80, 0x06, 0x60, 0x60, 0x00, 0x20, 0xa0, 0x61, 
-0x06, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
-0x05, 0x4b, 0x00, 0x20, 0x00, 0xf0, 0x66, 0xfe, 0xb8, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x04, 0x00, 0x12, 0x02, 0xf8, 0x28, 0x00, 0x80, 
-0x44, 0x80, 0x20, 0x40, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 
+0x06, 0xca, 0x01, 0xf0, 0x01, 0xf9, 0x08, 0x98, 0x36, 0x18, 0xa8, 0x68, 
+0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 
+0x92, 0x48, 0x01, 0x22, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 
+0x8e, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0xec, 0xf8, 
+0x00, 0x20, 0x02, 0x90, 0x15, 0xe0, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 
+0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x88, 0x48, 0x08, 0x9a, 0x02, 0x43, 
+0x00, 0xe0, 0x08, 0x9a, 0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 
+0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 0xd5, 0xf8, 0x08, 0x98, 
+0x36, 0x18, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 
+0x00, 0xf0, 0x14, 0xfa, 0x07, 0x1c, 0x68, 0x68, 0x80, 0x0e, 0x6b, 0xd2, 
+0x0a, 0x98, 0xc0, 0x46, 0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 0x5c, 0xda, 
+0x0d, 0x98, 0x09, 0x99, 0x88, 0x42, 0x03, 0xd0, 0x7a, 0x88, 0x1e, 0xe0, 
+0x5f, 0xe0, 0x5e, 0xe0, 0x78, 0x88, 0x01, 0x22, 0x52, 0x06, 0x02, 0x43, 
+0xa9, 0x68, 0x8c, 0x23, 0x19, 0x40, 0x02, 0xd1, 0x09, 0x23, 0x5b, 0x04, 
+0x1a, 0x43, 0xb1, 0x07, 0x89, 0x0f, 0x0e, 0xd0, 0xc3, 0x06, 0xdb, 0x0e, 
+0x08, 0xd0, 0x1e, 0x2b, 0x09, 0xdb, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x29, 
+0x05, 0xd1, 0x01, 0xe0, 0x02, 0x29, 0x02, 0xd3, 0x01, 0x21, 0x02, 0x91, 
+0x02, 0x1c, 0x09, 0x98, 0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0xdb, 0x05, 
+0x1a, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 
+0x06, 0xca, 0x01, 0xf0, 0x8f, 0xf8, 0x78, 0x88, 0x86, 0x19, 0x10, 0x37, 
+0x02, 0x98, 0x00, 0x28, 0x14, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 
+0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x57, 0x48, 0x01, 0x22, 
+0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x53, 0x48, 0x01, 0x6d, 
+0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x76, 0xf8, 0x00, 0x20, 0x02, 0x90, 
+0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9, 
+0x07, 0x1c, 0x09, 0x98, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x90, 
+0x0c, 0x99, 0x88, 0x42, 0xa2, 0xdb, 0x68, 0x68, 0x30, 0x43, 0x01, 0x04, 
+0x09, 0x0c, 0x68, 0x60, 0xe8, 0x6a, 0x00, 0xf0, 
+0x7b, 0xfa, 0x28, 0xe0, 0x27, 0xe0, 0xa8, 0x68, 0x00, 0x09, 0x14, 0xd3, 
+0x68, 0x68, 0x80, 0x0e, 0x15, 0xd2, 0x01, 0x9a, 0x00, 0x2a, 0x12, 0xd0, 
+0x01, 0x9a, 0x50, 0x6b, 0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 
+0x89, 0xf9, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 
+0xc0, 0x46, 0x93, 0x63, 0x03, 0xe0, 0xe8, 0x6a, 0x31, 0x1c, 0x00, 0xf0, 
+0x5d, 0xfa, 0x68, 0x68, 0x30, 0x43, 0x68, 0x60, 0xa8, 0x69, 0xb0, 0x42, 
+0x05, 0xd9, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x1b, 0x00, 0xf0, 0xee, 0xf9, 
+0xae, 0x61, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x0b, 0xd0, 0x2f, 0x4a, 
+0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0xc3, 0x1f, 0x05, 0x3b, 0x2a, 0x48, 
+0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x23, 0xf8, 0x01, 0x23, 
+0x9b, 0x07, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61, 
+0xe1, 0x69, 0x81, 0x42, 0x12, 0xd0, 0x22, 0x69, 0x02, 0x2a, 0x0f, 0xd2, 
+0x41, 0x1a, 0x01, 0xd5, 0x60, 0x6d, 0x41, 0x18, 0x20, 0x1c, 0xff, 0xf7, 
+0x3f, 0xfb, 0xe1, 0x69, 0x40, 0x18, 0xe0, 0x61, 0x61, 0x6d, 0x88, 0x42, 
+0x24, 0xd3, 0x40, 0x1a, 0xe0, 0x61, 0x21, 0xe0, 0x81, 0x42, 0x1f, 0xd1, 
+0x20, 0x69, 0x02, 0x28, 0x1c, 0xd2, 0x01, 0x20, 0x60, 0x61, 0x18, 0x48, 
+0x41, 0x69, 0xe2, 0x6c, 0x0a, 0x43, 0x42, 0x61, 0x81, 0x69, 0xe3, 0x6c, 
+0x99, 0x43, 0x81, 0x61, 0x01, 0x21, 0x09, 0x05, 0xca, 0x60, 0x80, 0x69, 
+0xc0, 0x46, 0x08, 0x61, 0x8b, 0x02, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 
+0xc0, 0x46, 0xa0, 0x61, 0xe1, 0x69, 0x81, 0x42, 0x02, 0xd0, 0x20, 0x1c, 
+0xff, 0xf7, 0xcc, 0xfa, 0x28, 0x1c, 0x00, 0xf0, 0x0f, 0xf9, 0x0c, 0x98, 
+0x05, 0x99, 0x40, 0x18, 0x00, 0x01, 0x10, 0x30, 0x68, 0x61, 0x13, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 
+0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x12, 0x02, 0x04, 0x00, 0x52, 0x02, 
+0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x40, 0x20, 0x2d, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0x00, 0xf0, 0x03, 0xf9, 0x07, 0x1c, 0x81, 0x69, 0x44, 0x6a, 
+0xa0, 0x6f, 0x00, 0xf0, 0x45, 0xfe, 0x00, 0x20, 0xe1, 0x1d, 0x19, 0x31, 
+0x48, 0x71, 0x79, 0x68, 0xc9, 0x0e, 0x09, 0xd3, 0xf8, 0x6a, 0x00, 0x01, 
+0x24, 0x49, 0x40, 0x18, 0x24, 0x4b, 0xc0, 0x18, 0x01, 0x68, 0x01, 0x39, 
+0x01, 0x60, 0x36, 0xe0, 0xe1, 0x6d, 0x09, 0x68, 0x22, 0x6e, 0xc0, 0x46, 
+0x11, 0x60, 0x20, 0x4e, 0xf5, 0x1d, 0x79, 0x35, 0x01, 0x23, 0xe9, 0x6b, 
+0x19, 0x43, 0xe9, 0x63, 0xb9, 0x6a, 0xe2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 
+0xb9, 0x6a, 0x22, 0x6e, 0xc0, 0x46, 0x11, 0x60, 0x61, 0x69, 0x00, 0x29, 
+0x04, 0xd1, 0xa9, 0x6b, 0x01, 0x31, 0xa9, 0x63, 0x08, 0x29, 0x07, 0xd3, 
+0xa8, 0x63, 0x01, 0x20, 0x00, 0xf0, 0x86, 0xf8, 0xe8, 0x6b, 0x40, 0x08, 
+0x40, 0x00, 0xe8, 0x63, 0x78, 0x68, 0x81, 0x0e, 0x0f, 0xd2, 0x0b, 0x23, 
+0x1b, 0x02, 0xf1, 0x18, 0xc9, 0x68, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x08, 
+0x04, 0xd2, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0x02, 0xe0, 
+0x38, 0x1c, 0x00, 0xf0, 0x05, 0xfa, 0x38, 0x1c, 0xfb, 0xf7, 0x10, 0xfc, 
+0x20, 0x1c, 0x00, 0xf0, 0x0b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0x00, 0x00, 0xb0, 0xa0, 0x1c, 0x00, 0x80, 0xb4, 0x0c, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x19, 0x30, 
+0x01, 0x79, 0x00, 0x29, 0x04, 0xd0, 0x00, 0x21, 
+0x01, 0x71, 0x38, 0x1c, 0xff, 0xf7, 0x56, 0xfb, 0xf8, 0x68, 0x02, 0x28, 
+0x0d, 0xd0, 0xb8, 0x68, 0x80, 0x00, 0xc2, 0x19, 0x50, 0x6c, 0x00, 0x28, 
+0x11, 0xd0, 0xb8, 0x6a, 0x41, 0x78, 0x09, 0x01, 0x10, 0x31, 0x52, 0x6b, 
+0x10, 0x1a, 0x88, 0x42, 0x05, 0xd3, 0x38, 0x1c, 0xff, 0xf7, 0x42, 0xfb, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x28, 0xfa, 
+0xf8, 0xe7, 0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 
+0xb8, 0x62, 0xf1, 0xe7, 0xb0, 0xb5, 0x87, 0xb0, 0x0f, 0x1c, 0x80, 0x6f, 
+0xc0, 0x46, 0x00, 0x90, 0x00, 0x24, 0x13, 0x4d, 0x0b, 0x23, 0x1b, 0x02, 
+0xe8, 0x18, 0x80, 0x69, 0x00, 0x28, 0x17, 0xd0, 0x69, 0x46, 0xa2, 0x00, 
+0x52, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xd2, 0x18, 0x92, 0x69, 0x38, 0x1c, 
+0x00, 0xf0, 0x92, 0xfb, 0x00, 0x28, 0x09, 0xd1, 0x01, 0x34, 0xa0, 0x00, 
+0x40, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 
+0xea, 0xd1, 0x01, 0xe0, 0x01, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
+0x9d, 0xf9, 0x07, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0xb8, 0xb5, 0xc2, 0x07, 0xd2, 0x0f, 0x16, 0x4c, 
+0x16, 0x49, 0x01, 0xd0, 0x08, 0x22, 0x08, 0xe0, 0x82, 0x08, 0x05, 0xd3, 
+0x0c, 0x22, 0xa4, 0x18, 0x0b, 0x68, 0xdf, 0x1d, 0x15, 0x37, 0x03, 0xe0, 
+0x1c, 0x22, 0x0b, 0x68, 0xdf, 0x1d, 0x09, 0x37, 0x0f, 0x4b, 0x1d, 0x78, 
+0x00, 0x2d, 0x13, 0xd0, 0x5b, 0x78, 0x00, 0x2b, 0x10, 0xd0, 0x01, 0x23, 
+0x5b, 0x06, 0x1a, 0x43, 0x00, 0x28, 0x01, 0xd1, 0x5b, 0x08, 0x1a, 0x43, 
+0x00, 0x92, 0x4a, 0x68, 0x01, 0x20, 0x39, 0x1c, 0x23, 0x1c, 0x00, 0xf0, 
+0xdf, 0xfe, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x03, 0x23, 0x1b, 0x06, 
+0x1a, 0x43, 0xf1, 0xe7, 0x3c, 0xef, 0x20, 0x40, 0x7c, 0x29, 0x00, 0x80, 
+0xf8, 0x0e, 0x00, 0x80, 0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x8a, 0x68, 
+0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46, 
+0xd0, 0x61, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 
+0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 
+0x8a, 0x60, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80, 0x01, 0x1c, 0x01, 0x23, 
+0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 0xca, 0x68, 0x01, 0x3a, 0xca, 0x60, 
+0x0a, 0x69, 0x01, 0x3a, 0x80, 0x00, 0x0a, 0x61, 0x42, 0x18, 0xd0, 0x6b, 
+0x53, 0x6b, 0xc0, 0x46, 0xcb, 0x62, 0x0b, 0x68, 0x9b, 0x00, 0x59, 0x18, 
+0x49, 0x6c, 0x53, 0x6c, 0xc9, 0x18, 0x51, 0x64, 0x70, 0x47, 0x8a, 0x68, 
+0x92, 0x00, 0x52, 0x18, 0xd3, 0x6b, 0x83, 0x42, 0x17, 0xd1, 0xd0, 0x1d, 
+0x3d, 0x30, 0x0a, 0x68, 0x92, 0x00, 0x52, 0x18, 0x52, 0x6c, 0x03, 0x68, 
+0x9a, 0x1a, 0x02, 0x60, 0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 
+0xca, 0x68, 0x01, 0x32, 0xca, 0x60, 0x0a, 0x69, 0x01, 0x32, 0x80, 0x00, 
+0x40, 0x18, 0x0a, 0x61, 0x40, 0x6b, 0xc0, 0x46, 0xc8, 0x62, 0x70, 0x47, 
+0xb8, 0xb5, 0x04, 0x1c, 0x1d, 0x1c, 0x17, 0x1c, 0x08, 0x1c, 0x39, 0x1c, 
+0xff, 0xf7, 0xd9, 0xff, 0x00, 0x20, 0x29, 0x1c, 0x00, 0xf0, 0x7c, 0xfe, 
+0x01, 0x20, 0xf9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x80, 0x06, 0x60, 0x60, 
+0x00, 0x20, 0xa0, 0x61, 0x06, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 
+0x01, 0x6d, 0x42, 0x6d, 0x05, 0x4b, 0x00, 0x20, 0x00, 0xf0, 0x62, 0xfe, 
+0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x04, 0x00, 0x12, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 
+0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 
+0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 
+0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
+0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 
 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 
-0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00, 0x50, 0x2d, 0x00, 0x80, 
-0xa0, 0x82, 0x20, 0x40, 0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 
-0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 
-0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00, 
-0x50, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x03, 0x30, 0x80, 0x08, 
-0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 
-0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 
-0x0a, 0x71, 0x70, 0x47, 0x50, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x02, 0x48, 0x41, 0x79, 0x01, 0x31, 0x41, 0x71, 
-0x70, 0x47, 0x00, 0x00, 0xa0, 0x82, 0x20, 0x40, 0x90, 0xb4, 0x82, 0x00, 
-0x17, 0x4b, 0x9a, 0x58, 0x8b, 0x07, 0x02, 0xd0, 0x89, 0x08, 0x0b, 0x1d, 
-0x01, 0xe0, 0x89, 0x08, 0xcb, 0x1c, 0x11, 0x69, 0xd7, 0x68, 0x12, 0x4c, 
-0x80, 0x00, 0x20, 0x58, 0x40, 0x68, 0xb9, 0x42, 0x03, 0xd1, 0x81, 0x42, 
-0x19, 0xd9, 0x11, 0x68, 0x17, 0xe0, 0x00, 0x24, 0xb9, 0x42, 0x09, 0xd9, 
-0x81, 0x42, 0x12, 0xd9, 0x11, 0x68, 0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 
-0x80, 0x10, 0x98, 0x42, 0x0b, 0xd8, 0x07, 0xe0, 0x81, 0x42, 0x05, 0xd8, 
-0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 0x98, 0x42, 0x02, 0xd8, 
-0x20, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0xc8, 0x1d, 0x05, 0x30, 0xfa, 0xe7, 
-0xf0, 0x03, 0x00, 0x80, 0x80, 0xb5, 0x80, 0x00, 0x0f, 0x4a, 0x17, 0x58, 
-0x88, 0x07, 0x02, 0xd0, 0x88, 0x08, 0x04, 0x30, 0x01, 0xe0, 0x88, 0x08, 
-0x03, 0x30, 0x39, 0x69, 0x7a, 0x68, 0x91, 0x42, 0x09, 0xd9, 0x39, 0x68, 
-0xc0, 0x46, 0x39, 0x61, 0xf9, 0x68, 0x7a, 0x68, 0x91, 0x42, 0x02, 0xd9, 
-0x39, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x81, 0x00, 0x38, 0x69, 0x00, 0xf0, 
-0xd5, 0xfd, 0x38, 0x61, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xf0, 0x03, 0x00, 0x80, 0x90, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x01, 0x40, 
-0x0c, 0x0f, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x22, 0x92, 0x07, 0x02, 0x40, 
-0xa3, 0x00, 0x1c, 0x4f, 0xff, 0x58, 0x89, 0x07, 0x89, 0x0f, 0x00, 0x04, 
-0x00, 0x0c, 0x80, 0x08, 0x00, 0x29, 0x00, 0xd0, 0x01, 0x30, 0x00, 0x2a, 
-0x01, 0xd0, 0x02, 0x30, 0x00, 0xe0, 0x03, 0x30, 0xf9, 0x68, 0x7a, 0x68, 
+0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x03, 0x30, 0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 
+0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 
+0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 
+0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x02, 0x48, 0x41, 0x79, 
+0x01, 0x31, 0x41, 0x71, 0x70, 0x47, 0x00, 0x00, 0xa0, 0x82, 0x20, 0x40, 
+0x90, 0xb4, 0x82, 0x00, 0x17, 0x4b, 0x9a, 0x58, 0x8b, 0x07, 0x02, 0xd0, 
+0x89, 0x08, 0x0b, 0x1d, 0x01, 0xe0, 0x89, 0x08, 0xcb, 0x1c, 0x11, 0x69, 
+0xd7, 0x68, 0x12, 0x4c, 0x80, 0x00, 0x20, 0x58, 0x40, 0x68, 0xb9, 0x42, 
+0x03, 0xd1, 0x81, 0x42, 0x19, 0xd9, 0x11, 0x68, 0x17, 0xe0, 0x00, 0x24, 
+0xb9, 0x42, 0x09, 0xd9, 0x81, 0x42, 0x12, 0xd9, 0x11, 0x68, 0x78, 0x1a, 
+0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 0x98, 0x42, 0x0b, 0xd8, 0x07, 0xe0, 
+0x81, 0x42, 0x05, 0xd8, 0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 
+0x98, 0x42, 0x02, 0xd8, 0x20, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0xc8, 0x1d, 
+0x05, 0x30, 0xfa, 0xe7, 0x70, 0x04, 0x00, 0x80, 0x80, 0xb5, 0x80, 0x00, 
+0x0f, 0x4a, 0x17, 0x58, 0x88, 0x07, 0x02, 0xd0, 0x88, 0x08, 0x04, 0x30, 
+0x01, 0xe0, 0x88, 0x08, 0x03, 0x30, 0x39, 0x69, 0x7a, 0x68, 0x91, 0x42, 
+0x09, 0xd9, 0x39, 0x68, 0xc0, 0x46, 0x39, 0x61, 0xf9, 0x68, 0x7a, 0x68, 
 0x91, 0x42, 0x02, 0xd9, 0x39, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x81, 0x00, 
-0xf8, 0x68, 0x00, 0xf0, 0xa9, 0xfd, 0xf8, 0x60, 0x0f, 0x48, 0x00, 0x69, 
-0x00, 0x28, 0x05, 0xd0, 0x01, 0x20, 0xa0, 0x40, 0x02, 0xd0, 0x20, 0x1c, 
-0xfe, 0xf7, 0xc8, 0xfc, 0x0b, 0x49, 0xc8, 0x1d, 0x19, 0x30, 0x03, 0x79, 
-0x00, 0x22, 0x00, 0x2b, 0x05, 0xd1, 0x09, 0x49, 0xc8, 0x1d, 0x19, 0x30, 
-0x03, 0x79, 0x00, 0x2b, 0x03, 0xd0, 0x02, 0x71, 0x08, 0x1c, 0xff, 0xf7, 
-0x79, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0x03, 0x00, 0x80, 
-0x3c, 0x2c, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80, 0x50, 0x2c, 0x00, 0x80, 
-0xb0, 0xb5, 0x2b, 0x49, 0x09, 0x78, 0x00, 0x29, 0x03, 0xd1, 0x41, 0x68, 
-0x29, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68, 0x49, 0x08, 0x02, 0xd3, 
-0x09, 0x21, 0x09, 0x04, 0x01, 0xe0, 0x0d, 0x21, 0x09, 0x04, 0x0c, 0xc8, 
-0x08, 0x38, 0x19, 0x43, 0x87, 0x68, 0xbb, 0x0a, 0x03, 0xd3, 0x43, 0x68, 
-0x5b, 0x08, 0x00, 0xd3, 0x01, 0x31, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 
-0x18, 0x40, 0x07, 0x0f, 0xf8, 0x00, 0x1d, 0x4c, 0x00, 0x19, 0x23, 0x68, 
-0xc0, 0x18, 0x50, 0x30, 0x00, 0x79, 0x01, 0x28, 0x10, 0xd1, 0x60, 0x68, 
-0x01, 0x28, 0x0d, 0xd0, 0x10, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x01, 
-0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 
-0x41, 0x63, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x01, 0x00, 0x19, 
-0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x03, 0x6b, 0x5d, 0x1c, 0x05, 0x63, 
-0xbd, 0x02, 0x2d, 0x19, 0xdb, 0x00, 0xeb, 0x18, 0x80, 0x33, 0x19, 0x63, 
-0xda, 0x62, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 0x01, 0x21, 0xb9, 0x40, 
-0x22, 0x68, 0x11, 0x43, 0x21, 0x60, 0x01, 0x6b, 0x80, 0x29, 0xe2, 0xd3, 
-0x00, 0x21, 0x01, 0x63, 0xdf, 0xe7, 0x00, 0x00, 
-0xa8, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x1c, 0x1c, 0x00, 0x80, 
-0xf0, 0xb5, 0x1f, 0x4e, 0x70, 0x68, 0x00, 0x28, 0x36, 0xd1, 0x00, 0x24, 
-0xb1, 0x68, 0x48, 0x1c, 0xc9, 0x00, 0x89, 0x19, 0xb0, 0x60, 0x32, 0x68, 
-0x89, 0x18, 0x60, 0x31, 0x0d, 0x7b, 0x08, 0x28, 0x00, 0xd3, 0xb4, 0x60, 
-0x28, 0x01, 0x80, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x87, 0x6b, 
-0x00, 0x2f, 0x21, 0xd0, 0xc1, 0x6a, 0x4b, 0x1c, 0xaa, 0x02, 0x92, 0x19, 
-0xc9, 0x00, 0x51, 0x18, 0x80, 0x31, 0xc3, 0x62, 0xca, 0x6a, 0x09, 0x6b, 
-0x01, 0x3f, 0x87, 0x63, 0x80, 0x2b, 0x00, 0xd3, 0xc4, 0x62, 0x00, 0x2f, 
-0x06, 0xd1, 0x01, 0x27, 0xaf, 0x40, 0x3b, 0x1c, 0xdb, 0x43, 0x37, 0x68, 
-0x3b, 0x40, 0x33, 0x60, 0x43, 0x6b, 0x01, 0x3b, 0x43, 0x63, 0x10, 0x1c, 
-0x37, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x78, 0x68, 0x00, 0x28, 0xc9, 0xd0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x80, 
-0xf0, 0xb5, 0xcd, 0x0f, 0xed, 0x07, 0x01, 0x24, 0x00, 0x27, 0x2f, 0x4b, 
-0x2f, 0x4a, 0x00, 0x2d, 0x1d, 0xd0, 0xd8, 0x6a, 0x01, 0x30, 0xd8, 0x62, 
-0x10, 0x1c, 0x52, 0x69, 0x00, 0x2a, 0x12, 0xd0, 0x02, 0x69, 0x53, 0x1c, 
-0x92, 0x00, 0x12, 0x18, 0x03, 0x61, 0x91, 0x61, 0x41, 0x69, 0x01, 0x31, 
-0x41, 0x61, 0x02, 0x69, 0x0f, 0x2a, 0x00, 0xd3, 0x07, 0x61, 0x0f, 0x29, 
-0x00, 0xd3, 0x44, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x08, 0x1c, 
-0xff, 0xf7, 0xee, 0xfe, 0xf8, 0xe7, 0x15, 0x69, 0x6e, 0x1c, 0xad, 0x00, 
-0xad, 0x18, 0x16, 0x61, 0xa9, 0x61, 0x55, 0x69, 0x01, 0x35, 0x55, 0x61, 
-0x16, 0x69, 0x0f, 0x2e, 0x00, 0xd3, 0x17, 0x61, 0x0f, 0x2d, 0x00, 0xd3, 
-0x54, 0x60, 0x8c, 0x02, 0xa4, 0x0a, 0x17, 0x4f, 0x3a, 0x6f, 0xfd, 0x68, 
-0xf9, 0x1d, 0x79, 0x31, 0x01, 0x2d, 0x0e, 0xd1, 0xdb, 0x6d, 0x5b, 0x08, 
-0x0b, 0xd3, 0x8b, 0x88, 0x00, 0x2b, 0x08, 0xd1, 0x03, 0x3b, 0xfd, 0x6f, 
-0x2b, 0x40, 0xfb, 0x67, 0x0f, 0x4d, 0xc0, 0x46, 0x2b, 0x60, 0x14, 0x23, 
-0x8b, 0x80, 0x10, 0x60, 0x80, 0x07, 0x80, 0x0a, 0x20, 0x43, 0x03, 0x04, 
-0x00, 0xd0, 0x01, 0x38, 0x50, 0x60, 0xc9, 0x69, 0x08, 0x32, 0x91, 0x42, 
-0x00, 0xd8, 0x08, 0x4a, 0x00, 0x0d, 0x02, 0xd3, 0x51, 0x20, 0x80, 0x03, 
-0x82, 0x61, 0x3a, 0x67, 0xbc, 0xe7, 0x00, 0x00, 0x10, 0x2a, 0x00, 0x80, 
-0x1c, 0x1c, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x01, 0x11, 0x00, 
-0x24, 0xa7, 0x20, 0x40, 0xb0, 0xb5, 0x00, 0x28, 0x04, 0xd1, 0x01, 0x20, 
-0xc0, 0x05, 0x16, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x15, 0x4c, 0x00, 0x25, 
+0x38, 0x69, 0x00, 0xf0, 0xd1, 0xfd, 0x38, 0x61, 0x80, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x70, 0x04, 0x00, 0x80, 0x90, 0xb5, 0x03, 0x21, 
+0x09, 0x07, 0x01, 0x40, 0x0c, 0x0f, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x22, 
+0x92, 0x07, 0x02, 0x40, 0xa3, 0x00, 0x1c, 0x4f, 0xff, 0x58, 0x89, 0x07, 
+0x89, 0x0f, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x08, 0x00, 0x29, 0x00, 0xd0, 
+0x01, 0x30, 0x00, 0x2a, 0x01, 0xd0, 0x02, 0x30, 0x00, 0xe0, 0x03, 0x30, 
+0xf9, 0x68, 0x7a, 0x68, 0x91, 0x42, 0x02, 0xd9, 0x39, 0x68, 0xc0, 0x46, 
+0xf9, 0x60, 0x81, 0x00, 0xf8, 0x68, 0x00, 0xf0, 0xa5, 0xfd, 0xf8, 0x60, 
+0x0f, 0x48, 0x00, 0x69, 0x00, 0x28, 0x05, 0xd0, 0x01, 0x20, 0xa0, 0x40, 
+0x02, 0xd0, 0x20, 0x1c, 0xfe, 0xf7, 0xca, 0xfc, 0x0b, 0x49, 0xc8, 0x1d, 
+0x19, 0x30, 0x03, 0x79, 0x00, 0x22, 0x00, 0x2b, 0x05, 0xd1, 0x09, 0x49, 
+0xc8, 0x1d, 0x19, 0x30, 0x03, 0x79, 0x00, 0x2b, 0x03, 0xd0, 0x02, 0x71, 
+0x08, 0x1c, 0xff, 0xf7, 0x79, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x70, 0x04, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80, 0x64, 0x2d, 0x00, 0x80, 
+0xe4, 0x2c, 0x00, 0x80, 0xb0, 0xb5, 0x2b, 0x49, 0x09, 0x79, 0x00, 0x29, 
+0x03, 0xd1, 0x41, 0x68, 0x29, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68, 
+0x49, 0x08, 0x02, 0xd3, 0x09, 0x21, 0x09, 0x04, 0x01, 0xe0, 0x0d, 0x21, 
+0x09, 0x04, 0x0c, 0xc8, 0x08, 0x38, 0x19, 0x43, 
+0x87, 0x68, 0xbb, 0x0a, 0x03, 0xd3, 0x43, 0x68, 0x5b, 0x08, 0x00, 0xd3, 
+0x01, 0x31, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x07, 0x0f, 
+0xf8, 0x00, 0x1d, 0x4c, 0x00, 0x19, 0x23, 0x68, 0xc0, 0x18, 0x50, 0x30, 
+0x00, 0x79, 0x01, 0x28, 0x10, 0xd1, 0x60, 0x68, 0x01, 0x28, 0x0d, 0xd0, 
+0x10, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 
+0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0xb0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 
+0xc0, 0x18, 0x03, 0x6b, 0x5d, 0x1c, 0x05, 0x63, 0xbd, 0x02, 0x2d, 0x19, 
+0xdb, 0x00, 0xeb, 0x18, 0x80, 0x33, 0x19, 0x63, 0xda, 0x62, 0x81, 0x6b, 
+0x01, 0x31, 0x81, 0x63, 0x01, 0x21, 0xb9, 0x40, 0x22, 0x68, 0x11, 0x43, 
+0x21, 0x60, 0x01, 0x6b, 0x80, 0x29, 0xe2, 0xd3, 0x00, 0x21, 0x01, 0x63, 
+0xdf, 0xe7, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
+0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0x1f, 0x4e, 0x70, 0x68, 0x00, 0x28, 
+0x36, 0xd1, 0x00, 0x24, 0xb1, 0x68, 0x48, 0x1c, 0xc9, 0x00, 0x89, 0x19, 
+0xb0, 0x60, 0x32, 0x68, 0x89, 0x18, 0x60, 0x31, 0x0d, 0x7b, 0x08, 0x28, 
+0x00, 0xd3, 0xb4, 0x60, 0x28, 0x01, 0x80, 0x19, 0x19, 0x23, 0xdb, 0x01, 
+0xc0, 0x18, 0x87, 0x6b, 0x00, 0x2f, 0x21, 0xd0, 0xc1, 0x6a, 0x4b, 0x1c, 
+0xaa, 0x02, 0x92, 0x19, 0xc9, 0x00, 0x51, 0x18, 0x80, 0x31, 0xc3, 0x62, 
+0xca, 0x6a, 0x09, 0x6b, 0x01, 0x3f, 0x87, 0x63, 0x80, 0x2b, 0x00, 0xd3, 
+0xc4, 0x62, 0x00, 0x2f, 0x06, 0xd1, 0x01, 0x27, 0xaf, 0x40, 0x3b, 0x1c, 
+0xdb, 0x43, 0x37, 0x68, 0x3b, 0x40, 0x33, 0x60, 0x43, 0x6b, 0x01, 0x3b, 
+0x43, 0x63, 0x10, 0x1c, 0x37, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x78, 0x68, 
+0x00, 0x28, 0xc9, 0xd0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0xcd, 0x0f, 0xed, 0x07, 0x01, 0x24, 
+0x00, 0x27, 0x2e, 0x4b, 0x2e, 0x4a, 0x00, 0x2d, 0x1d, 0xd0, 0xd8, 0x6a, 
+0x01, 0x30, 0xd8, 0x62, 0x10, 0x1c, 0x52, 0x69, 0x00, 0x2a, 0x12, 0xd0, 
+0x02, 0x69, 0x53, 0x1c, 0x92, 0x00, 0x12, 0x18, 0x03, 0x61, 0x91, 0x61, 
+0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x02, 0x69, 0x0f, 0x2a, 0x00, 0xd3, 
+0x07, 0x61, 0x0f, 0x29, 0x00, 0xd3, 0x44, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x08, 0x1c, 0xff, 0xf7, 0xee, 0xfe, 0xf8, 0xe7, 0x15, 0x69, 
+0x6e, 0x1c, 0xad, 0x00, 0xad, 0x18, 0x16, 0x61, 0xa9, 0x61, 0x55, 0x69, 
+0x01, 0x35, 0x55, 0x61, 0x16, 0x69, 0x0f, 0x2e, 0x00, 0xd3, 0x17, 0x61, 
+0x0f, 0x2d, 0x00, 0xd3, 0x54, 0x60, 0x8c, 0x02, 0xa4, 0x0a, 0x16, 0x4f, 
+0x3a, 0x6f, 0xfd, 0x68, 0xf9, 0x1d, 0x79, 0x31, 0x01, 0x2d, 0x0c, 0xd1, 
+0xdb, 0x6d, 0x5b, 0x08, 0x09, 0xd3, 0x0b, 0x89, 0x00, 0x2b, 0x06, 0xd1, 
+0xfd, 0x6f, 0x03, 0x3b, 0x2e, 0x68, 0x33, 0x40, 0x2b, 0x60, 0x14, 0x23, 
+0x0b, 0x81, 0x10, 0x60, 0x80, 0x07, 0x80, 0x0a, 0x20, 0x43, 0x03, 0x04, 
+0x00, 0xd0, 0x01, 0x38, 0x50, 0x60, 0x09, 0x6a, 0x08, 0x32, 0x91, 0x42, 
+0x00, 0xd8, 0x07, 0x4a, 0x00, 0x0d, 0x02, 0xd3, 0x51, 0x20, 0x80, 0x03, 
+0x82, 0x61, 0x3a, 0x67, 0xbe, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 
+0xa0, 0x1c, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 
+0xb0, 0xb5, 0x00, 0x28, 0x04, 0xd1, 0x01, 0x20, 0xc0, 0x05, 0x16, 0x49, 
+0xc0, 0x46, 0x08, 0x60, 0x15, 0x4c, 0x00, 0x25, 
 0x67, 0x69, 0x00, 0x2f, 0x16, 0xd0, 0xe0, 0x68, 0x41, 0x1c, 0x80, 0x00, 
-0x00, 0x19, 0xe1, 0x60, 0x80, 0x69, 0x01, 0x3f, 0xff, 0xf7, 0x90, 0xfe, 
+0x00, 0x19, 0xe1, 0x60, 0x80, 0x69, 0x01, 0x3f, 0xff, 0xf7, 0x94, 0xfe, 
 0xe0, 0x68, 0x0f, 0x28, 0x00, 0xd3, 0xe5, 0x60, 0xe0, 0x68, 0x80, 0x00, 
 0x00, 0x19, 0x80, 0x69, 0x00, 0x08, 0x01, 0xd3, 0x00, 0x2f, 0xea, 0xd1, 
 0x67, 0x61, 0x03, 0xe0, 0x08, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 
-0x65, 0x60, 0x20, 0x68, 0x00, 0x28, 0x01, 0xd0, 0xff, 0xf7, 0x22, 0xff, 
+0x65, 0x60, 0x20, 0x68, 0x00, 0x28, 0x01, 0xd0, 0xff, 0xf7, 0x26, 0xff, 
 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
-0x1c, 0x1c, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x00, 0x20, 0x70, 0x47, 
+0xa0, 0x1c, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x00, 0x20, 0x70, 0x47, 
 0xb0, 0xb4, 0x10, 0x23, 0x82, 0x68, 0x13, 0x40, 0x00, 0x21, 0x00, 0x2b, 
 0x15, 0xd0, 0x0c, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x24, 0x14, 0x43, 
-0x02, 0x68, 0x15, 0x68, 0x13, 0x1d, 0x80, 0xcb, 
-0x1b, 0x68, 0x04, 0x3a, 0x02, 0x60, 0x20, 0xc2, 0x80, 0xc2, 0x08, 0xc2, 
-0x14, 0x60, 0x42, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x04, 0x32, 0x1a, 0x43, 
-0x42, 0x60, 0x08, 0x1c, 0xb0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 
-0xf0, 0xb4, 0x82, 0x68, 0x53, 0x09, 0x34, 0xd3, 0x1b, 0x4b, 0x1a, 0x40, 
-0x12, 0x01, 0x81, 0x26, 0x16, 0x43, 0x03, 0x68, 0x1d, 0x68, 0x1f, 0x1d, 
-0x10, 0xcf, 0x3f, 0x68, 0x04, 0x3b, 0x03, 0x60, 0x20, 0xc3, 0x10, 0xc3, 
-0x80, 0xc3, 0x1e, 0x60, 0x43, 0x68, 0x1f, 0x1d, 0x01, 0x23, 0x9b, 0x07, 
-0x3b, 0x43, 0x43, 0x60, 0xcb, 0x6b, 0x18, 0x1f, 0xc8, 0x63, 0x80, 0xcb, 
-0x80, 0xc0, 0x1c, 0x68, 0x1f, 0x1d, 0x03, 0x1d, 0x04, 0x60, 0x38, 0x1c, 
-0x3f, 0x68, 0xc0, 0x46, 0x1f, 0x60, 0x1f, 0x1d, 0x43, 0x68, 0x1c, 0x04, 
-0x24, 0x0c, 0x81, 0x23, 0x23, 0x43, 0x3b, 0x60, 0x40, 0x68, 0x00, 0x0c, 
-0x00, 0x04, 0x10, 0x43, 0x78, 0x60, 0x08, 0x6e, 0x04, 0x30, 0x08, 0x66, 
-0x48, 0x6e, 0x04, 0x30, 0x48, 0x66, 0x00, 0x20, 0xf0, 0xbc, 0x70, 0x47, 
-0x00, 0xf0, 0xff, 0x0f, 0x80, 0xb4, 0x81, 0x6a, 0x01, 0x23, 0x9b, 0x07, 
-0xca, 0x1d, 0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 0xcf, 0x1d, 0x01, 0x37, 
-0x3b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x60, 0x01, 0x23, 0x9b, 0x07, 
-0x0f, 0x1d, 0x3b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x8b, 0x60, 0x01, 0x23, 
-0x9b, 0x07, 0x0b, 0x43, 0x1b, 0x68, 0x0c, 0xc1, 0x02, 0x62, 0x01, 0x6b, 
-0xc0, 0x46, 0x0a, 0x62, 0x04, 0x23, 0x81, 0x69, 0x19, 0x43, 0x81, 0x61, 
-0x02, 0x6b, 0xc0, 0x46, 0x91, 0x61, 0x81, 0x6a, 0x04, 0x31, 0x81, 0x62, 
-0x02, 0x6b, 0xc0, 0x46, 0x91, 0x62, 0xc1, 0x1d, 0x39, 0x31, 0x4a, 0x8b, 
-0x04, 0x3a, 0x4a, 0x83, 0x49, 0x8b, 0x02, 0x6b, 0x40, 0x32, 0x51, 0x83, 
-0xc1, 0x89, 0x04, 0x39, 0xc1, 0x81, 0xc1, 0x68, 0x00, 0x6b, 0xc0, 0x46, 
-0xc1, 0x60, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x47, 0x08, 0x47, 
-0x10, 0x47, 0x18, 0x47, 0x20, 0x47, 0x28, 0x47, 0x30, 0x47, 0x38, 0x47, 
-0x30, 0x40, 0x2d, 0xe9, 0x0c, 0xc0, 0x9d, 0xe5, 0x0c, 0x48, 0xa0, 0xe1, 
-0x24, 0x48, 0xb0, 0xe1, 0x1e, 0x00, 0x00, 0x0a, 0x01, 0xc0, 0x4c, 0xe2, 
-0x18, 0x40, 0xa0, 0xe3, 0x64, 0x51, 0x9f, 0xe5, 0x94, 0x50, 0x20, 0xe0, 
-0x00, 0x50, 0x90, 0xe5, 0x14, 0x40, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 
-0x04, 0xc0, 0x85, 0xe5, 0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 
-0x10, 0x10, 0x90, 0xe5, 0x10, 0x50, 0x85, 0xe2, 0x01, 0x00, 0x55, 0xe1, 
-0x0c, 0x50, 0x90, 0x55, 0x04, 0x00, 0x55, 0xe1, 0x05, 0x00, 0x00, 0x0a, 
+0x02, 0x68, 0x15, 0x68, 0x13, 0x1d, 0x80, 0xcb, 0x1b, 0x68, 0x04, 0x3a, 
+0x02, 0x60, 0x20, 0xc2, 0x80, 0xc2, 0x08, 0xc2, 0x14, 0x60, 0x42, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x04, 0x32, 0x1a, 0x43, 0x42, 0x60, 0x08, 0x1c, 
+0xb0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 0xf0, 0xb4, 0x82, 0x68, 
+0x53, 0x09, 0x34, 0xd3, 0x1b, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x26, 
+0x16, 0x43, 0x03, 0x68, 0x1d, 0x68, 0x1f, 0x1d, 0x10, 0xcf, 0x3f, 0x68, 
+0x04, 0x3b, 0x03, 0x60, 0x20, 0xc3, 0x10, 0xc3, 0x80, 0xc3, 0x1e, 0x60, 
+0x43, 0x68, 0x1f, 0x1d, 0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 0x43, 0x60, 
+0xcb, 0x6b, 0x18, 0x1f, 0xc8, 0x63, 0x80, 0xcb, 0x80, 0xc0, 0x1c, 0x68, 
+0x1f, 0x1d, 0x03, 0x1d, 0x04, 0x60, 0x38, 0x1c, 0x3f, 0x68, 0xc0, 0x46, 
+0x1f, 0x60, 0x1f, 0x1d, 0x43, 0x68, 0x1c, 0x04, 0x24, 0x0c, 0x81, 0x23, 
+0x23, 0x43, 0x3b, 0x60, 0x40, 0x68, 0x00, 0x0c, 0x00, 0x04, 0x10, 0x43, 
+0x78, 0x60, 0x08, 0x6e, 0x04, 0x30, 0x08, 0x66, 0x48, 0x6e, 0x04, 0x30, 
+0x48, 0x66, 0x00, 0x20, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 
+0x80, 0xb4, 0x81, 0x6a, 0x01, 0x23, 0x9b, 0x07, 0xca, 0x1d, 0x05, 0x32, 
+0x1a, 0x43, 0x12, 0x68, 0xcf, 0x1d, 0x01, 0x37, 0x3b, 0x43, 0x1b, 0x68, 
+0xc0, 0x46, 0xcb, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0f, 0x1d, 0x3b, 0x43, 
+0x1b, 0x68, 0xc0, 0x46, 0x8b, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0b, 0x43, 
+0x1b, 0x68, 0x0c, 0xc1, 0x02, 0x62, 0x01, 0x6b, 0xc0, 0x46, 0x0a, 0x62, 
+0x04, 0x23, 0x81, 0x69, 0x19, 0x43, 0x81, 0x61, 0x02, 0x6b, 0xc0, 0x46, 
+0x91, 0x61, 0x81, 0x6a, 0x04, 0x31, 0x81, 0x62, 0x02, 0x6b, 0xc0, 0x46, 
+0x91, 0x62, 0xc1, 0x1d, 0x39, 0x31, 0x4a, 0x8b, 0x04, 0x3a, 0x4a, 0x83, 
+0x49, 0x8b, 0x02, 0x6b, 0x40, 0x32, 0x51, 0x83, 0xc1, 0x89, 0x04, 0x39, 
+0xc1, 0x81, 0xc1, 0x68, 0x00, 0x6b, 0xc0, 0x46, 0xc1, 0x60, 0x00, 0x20, 
+0x80, 0xbc, 0x70, 0x47, 0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 
+0x20, 0x47, 0x28, 0x47, 0x30, 0x47, 0x38, 0x47, 0x30, 0x40, 0x2d, 0xe9, 
+0x0c, 0xc0, 0x9d, 0xe5, 0x0c, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xb0, 0xe1, 
+0x1e, 0x00, 0x00, 0x0a, 0x01, 0xc0, 0x4c, 0xe2, 0x18, 0x40, 0xa0, 0xe3, 
+0x64, 0x51, 0x9f, 0xe5, 0x94, 0x50, 0x20, 0xe0, 0x00, 0x50, 0x90, 0xe5, 
+0x14, 0x40, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 
+0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 0x10, 0x10, 0x90, 0xe5, 
+0x10, 0x50, 0x85, 0xe2, 0x01, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55, 
+0x04, 0x00, 0x55, 0xe1, 0x05, 0x00, 0x00, 0x0a, 
 0x04, 0x10, 0x90, 0xe5, 0x00, 0x50, 0x80, 0xe5, 0x00, 0x50, 0x81, 0xe5, 
 0x00, 0x00, 0xa0, 0xe3, 0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 
 0x00, 0x30, 0x93, 0xe5, 0x08, 0x20, 0x90, 0xe5, 0x01, 0x31, 0x83, 0xe3, 
@@ -1793,39 +1805,39 @@ const u8 typhoon_firmware_image[] = {
 0x50, 0x10, 0x91, 0xe5, 0xd9, 0xff, 0xff, 0xea, 0xf0, 0x47, 0x2d, 0xe9, 
 0x20, 0xc0, 0x9d, 0xe5, 0x0c, 0x68, 0xa0, 0xe1, 0x26, 0x68, 0xb0, 0xe1, 
 0x25, 0x00, 0x00, 0x0a, 0x18, 0x40, 0xa0, 0xe3, 0xb8, 0x50, 0x9f, 0xe5, 
-0x94, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x80, 0xe0, 
-0x08, 0x40, 0x90, 0xe5, 0x04, 0x80, 0x90, 0xe5, 0x00, 0x70, 0xa0, 0xe3, 
-0x1f, 0xc0, 0xa0, 0xe3, 0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x50, 0x90, 0xe5, 
-0x10, 0x90, 0x90, 0xe5, 0x14, 0xa0, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 
-0x04, 0xc0, 0x85, 0xe5, 0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 
-0x10, 0x50, 0x85, 0xe2, 0x09, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55, 
-0x0a, 0x00, 0x55, 0xe1, 0x15, 0x00, 0x00, 0x0a, 0x03, 0x70, 0x17, 0xe2, 
-0x20, 0x10, 0x81, 0xe2, 0x20, 0x30, 0x83, 0xe2, 0x0a, 0x00, 0x00, 0x0a, 
-0x00, 0x60, 0x96, 0xe2, 0x01, 0x70, 0x87, 0xe2, 0x09, 0x00, 0x00, 0x0a, 
-0x20, 0x60, 0x46, 0xe2, 0x20, 0x00, 0x56, 0xe3, 0xec, 0xff, 0xff, 0xca, 
-0x00, 0x70, 0xa0, 0xe3, 0x01, 0xc0, 0x46, 0xe2, 0x02, 0xc4, 0x8c, 0xe3, 
-0x00, 0x60, 0xa0, 0xe3, 0xe7, 0xff, 0xff, 0xea, 0x00, 0x50, 0x88, 0xe5, 
-0xf2, 0xff, 0xff, 0xea, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x50, 0x80, 0xe5, 
-0x01, 0x00, 0xa0, 0xe1, 0xf0, 0x47, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 
-0x00, 0xa0, 0x94, 0xe5, 0x0a, 0x00, 0x55, 0xe1, 0x14, 0xa0, 0x80, 0xe5, 
-0xe5, 0xff, 0xff, 0x1a, 0x01, 0x10, 0xa0, 0xe3, 0xf5, 0xff, 0xff, 0xea, 
-0x28, 0x03, 0x00, 0x80, 0xf8, 0x28, 0x00, 0x80, 0x00, 0x80, 0x20, 0x40, 
-0x68, 0x82, 0x9f, 0xe5, 0x0b, 0x92, 0xa0, 0xe3, 0x64, 0xa2, 0x9f, 0xe5, 
-0x58, 0xb0, 0x9a, 0xe5, 0x0e, 0xf0, 0xa0, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 
-0x1e, 0xff, 0x2f, 0xe1, 0x3f, 0x40, 0x2d, 0xe9, 0x00, 0x00, 0x4f, 0xe1, 
-0x1f, 0x00, 0x00, 0xe2, 0x12, 0x00, 0x50, 0xe3, 0x54, 0x00, 0x00, 0x0a, 
-0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xc0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
-0x04, 0x50, 0xa0, 0xe3, 0x00, 0x40, 0x99, 0xe5, 0x09, 0x00, 0x00, 0xea, 
-0x02, 0x00, 0x14, 0xe3, 0x53, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x14, 0xe3, 
-0x59, 0x00, 0x00, 0x1b, 0x20, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 
-0x02, 0x07, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x01, 0x06, 0x14, 0xe3, 
-0x59, 0x00, 0x00, 0x1b, 0x08, 0x00, 0x14, 0xe3, 0x45, 0x00, 0x00, 0x1b, 
-0x02, 0x05, 0x14, 0xe3, 0x4a, 0x00, 0x00, 0x1b, 0x02, 0x08, 0x14, 0xe3, 
-0x4b, 0x00, 0x00, 0x1b, 0xe5, 0x0e, 0x14, 0xe3, 0x07, 0x00, 0x00, 0x0a, 
-0x04, 0x20, 0x98, 0xe5, 0x0c, 0x10, 0x98, 0xe5, 0x04, 0x30, 0x52, 0xe2, 
-0x3c, 0x30, 0xa0, 0xb3, 0x04, 0x30, 0x88, 0xe5, 0x02, 0x00, 0x91, 0xe7, 
-0x0f, 0xe0, 0xa0, 0xe1, 0x10, 0xff, 0x2f, 0xe1, 0x01, 0x50, 0x55, 0xe2, 
-0x03, 0x00, 0x00, 0x0a, 0x00, 0x40, 0x99, 0xe5, 0x0c, 0x00, 0x9a, 0xe5, 
+0x94, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x80, 0xe0, 0x08, 0x40, 0x90, 0xe5, 
+0x04, 0x80, 0x90, 0xe5, 0x00, 0x70, 0xa0, 0xe3, 0x1f, 0xc0, 0xa0, 0xe3, 
+0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x50, 0x90, 0xe5, 0x10, 0x90, 0x90, 0xe5, 
+0x14, 0xa0, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 
+0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 0x10, 0x50, 0x85, 0xe2, 
+0x09, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55, 0x0a, 0x00, 0x55, 0xe1, 
+0x15, 0x00, 0x00, 0x0a, 0x03, 0x70, 0x17, 0xe2, 0x20, 0x10, 0x81, 0xe2, 
+0x20, 0x30, 0x83, 0xe2, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x96, 0xe2, 
+0x01, 0x70, 0x87, 0xe2, 0x09, 0x00, 0x00, 0x0a, 0x20, 0x60, 0x46, 0xe2, 
+0x20, 0x00, 0x56, 0xe3, 0xec, 0xff, 0xff, 0xca, 0x00, 0x70, 0xa0, 0xe3, 
+0x01, 0xc0, 0x46, 0xe2, 0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x60, 0xa0, 0xe3, 
+0xe7, 0xff, 0xff, 0xea, 0x00, 0x50, 0x88, 0xe5, 0xf2, 0xff, 0xff, 0xea, 
+0x00, 0x10, 0xa0, 0xe3, 0x00, 0x50, 0x80, 0xe5, 0x01, 0x00, 0xa0, 0xe1, 
+0xf0, 0x47, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xa0, 0x94, 0xe5, 
+0x0a, 0x00, 0x55, 0xe1, 0x14, 0xa0, 0x80, 0xe5, 0xe5, 0xff, 0xff, 0x1a, 
+0x01, 0x10, 0xa0, 0xe3, 0xf5, 0xff, 0xff, 0xea, 0xa8, 0x03, 0x00, 0x80, 
+0x7c, 0x29, 0x00, 0x80, 0x00, 0x80, 0x20, 0x40, 0x68, 0x82, 0x9f, 0xe5, 
+0x0b, 0x92, 0xa0, 0xe3, 0x64, 0xa2, 0x9f, 0xe5, 0x58, 0xb0, 0x9a, 0xe5, 
+0x0e, 0xf0, 0xa0, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
+0x3f, 0x40, 0x2d, 0xe9, 0x00, 0x00, 0x4f, 0xe1, 0x1f, 0x00, 0x00, 0xe2, 
+0x12, 0x00, 0x50, 0xe3, 0x54, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0f, 0xe1, 
+0x80, 0x00, 0xc0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x04, 0x50, 0xa0, 0xe3, 
+0x00, 0x40, 0x99, 0xe5, 0x09, 0x00, 0x00, 0xea, 0x02, 0x00, 0x14, 0xe3, 
+0x53, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 
+0x20, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x02, 0x07, 0x14, 0xe3, 
+0x59, 0x00, 0x00, 0x1b, 0x01, 0x06, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 
+0x08, 0x00, 0x14, 0xe3, 0x45, 0x00, 0x00, 0x1b, 0x02, 0x05, 0x14, 0xe3, 
+0x4a, 0x00, 0x00, 0x1b, 0x02, 0x08, 0x14, 0xe3, 0x4b, 0x00, 0x00, 0x1b, 
+0xe5, 0x0e, 0x14, 0xe3, 0x07, 0x00, 0x00, 0x0a, 0x04, 0x20, 0x98, 0xe5, 
+0x0c, 0x10, 0x98, 0xe5, 0x04, 0x30, 0x52, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 
+0x04, 0x30, 0x88, 0xe5, 0x02, 0x00, 0x91, 0xe7, 0x0f, 0xe0, 0xa0, 0xe1, 
+0x10, 0xff, 0x2f, 0xe1, 0x01, 0x50, 0x55, 0xe2, 0x03, 0x00, 0x00, 0x0a, 
+0x00, 0x40, 0x99, 0xe5, 0x0c, 0x00, 0x9a, 0xe5, 
 0x00, 0x00, 0x14, 0xe1, 0x1b, 0xff, 0x2f, 0x11, 0x08, 0x00, 0x9a, 0xe5, 
 0x00, 0x00, 0x14, 0xe1, 0x0b, 0x00, 0x00, 0x0a, 0x01, 0x0c, 0x14, 0xe3, 
 0x98, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 
@@ -1836,38 +1848,39 @@ const u8 typhoon_firmware_image[] = {
 0x04, 0x00, 0x14, 0xe3, 0x40, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
 0x02, 0x0a, 0x14, 0xe3, 0x44, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
 0x02, 0x09, 0x14, 0xe3, 0x48, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
-0x01, 0x02, 0x14, 0xe3, 0x4c, 0x00, 0x9a, 0x15, 
-0x10, 0xff, 0x2f, 0x11, 0x01, 0x04, 0x14, 0xe3, 0x50, 0x00, 0x9a, 0x15, 
-0x10, 0xff, 0x2f, 0x11, 0x01, 0x0a, 0x14, 0xe3, 0x21, 0x00, 0x00, 0x1b, 
-0x02, 0x00, 0x14, 0xe3, 0x0e, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x9a, 0xe5, 
-0x00, 0x00, 0x14, 0xe1, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x40, 0x99, 0xe5, 
-0x04, 0x50, 0xa0, 0xe3, 0x00, 0x40, 0x94, 0xe2, 0x1b, 0xff, 0x2f, 0x11, 
-0x3f, 0x40, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 0xc0, 0x00, 0x80, 0xe3, 
-0x00, 0xf0, 0x61, 0xe1, 0xfa, 0xff, 0xff, 0xea, 0x18, 0x00, 0x9a, 0xe5, 
-0x1c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 
-0x1c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
-0x20, 0x10, 0x9a, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0x11, 0xff, 0x2f, 0xe1, 
-0x24, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x28, 0x10, 0x9a, 0xe5, 
-0x11, 0xff, 0x2f, 0xe1, 0x2c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
-0x30, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x34, 0x10, 0x9a, 0xe5, 
-0x11, 0xff, 0x2f, 0xe1, 0xfe, 0xff, 0xff, 0xea, 0x38, 0xe0, 0x9a, 0xe5, 
-0x3c, 0x10, 0x9a, 0xe5, 0x18, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
-0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5, 
-0x11, 0xff, 0x2f, 0xe1, 0x64, 0x20, 0x9f, 0xe5, 0x00, 0x30, 0x92, 0xe5, 
-0x00, 0x30, 0x53, 0xe0, 0x0a, 0x00, 0x00, 0xba, 0x00, 0x30, 0x82, 0xe5, 
-0x0c, 0x00, 0x92, 0xe5, 0x08, 0x30, 0x92, 0xe5, 0x00, 0x10, 0x91, 0xe2, 
-0x03, 0x00, 0x00, 0x0a, 0x03, 0x10, 0x80, 0xe7, 0x04, 0x30, 0x53, 0xe2, 
-0x3c, 0x30, 0xa0, 0xb3, 0x08, 0x30, 0x82, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 
-0x1e, 0xff, 0x2f, 0xe1, 0x3c, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 
-0x01, 0x00, 0x80, 0xe2, 0x00, 0x00, 0x81, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 
-0xf8, 0xff, 0xff, 0xea, 0x10, 0x00, 0x9f, 0xe5, 0x08, 0x10, 0x90, 0xe5, 
-0x04, 0x10, 0x51, 0xe2, 0x3c, 0x10, 0xa0, 0xb3, 0x08, 0x10, 0x80, 0xe5, 
-0x1e, 0xff, 0x2f, 0xe1, 0x50, 0x2d, 0x00, 0x80, 0x4c, 0x04, 0x00, 0x80, 
-0xe5, 0x2a, 0xff, 0xff, 0x45, 0x3d, 0xff, 0xff, 0x3d, 0x2b, 0xff, 0xff, 
-0xa0, 0x82, 0x20, 0x40, 0xc9, 0x1c, 0x89, 0x08, 0x89, 0x00, 0x01, 0x23, 
-0x85, 0x4a, 0x5b, 0x07, 0x18, 0x43, 0x13, 0x68, 0x5b, 0x18, 0x13, 0x60, 
-0x00, 0x1f, 0x81, 0xa3, 0x5b, 0x1a, 0x18, 0x47, 0x04, 0x20, 0xa0, 0xe5, 
+0x01, 0x02, 0x14, 0xe3, 0x4c, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
+0x01, 0x04, 0x14, 0xe3, 0x50, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
+0x01, 0x0a, 0x14, 0xe3, 0x21, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x14, 0xe3, 
+0x0e, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 
+0x1c, 0x00, 0x00, 0x1b, 0x00, 0x40, 0x99, 0xe5, 0x04, 0x50, 0xa0, 0xe3, 
+0x00, 0x40, 0x94, 0xe2, 0x1b, 0xff, 0x2f, 0x11, 0x3f, 0x40, 0xbd, 0xe8, 
+0x04, 0xf0, 0x5e, 0xe2, 0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x61, 0xe1, 
+0xfa, 0xff, 0xff, 0xea, 0x18, 0x00, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 
+0x11, 0xff, 0x2f, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 
+0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x20, 0x10, 0x9a, 0xe5, 
+0x00, 0x00, 0xa0, 0xe3, 0x11, 0xff, 0x2f, 0xe1, 0x24, 0x10, 0x9a, 0xe5, 
+0x11, 0xff, 0x2f, 0xe1, 0x28, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
+0x2c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x30, 0x10, 0x9a, 0xe5, 
+0x11, 0xff, 0x2f, 0xe1, 0x34, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
+0xfe, 0xff, 0xff, 0xea, 0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5, 
+0x18, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x38, 0xe0, 0x9a, 0xe5, 
+0x3c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
+0x64, 0x20, 0x9f, 0xe5, 0x00, 0x30, 0x92, 0xe5, 0x00, 0x30, 0x53, 0xe0, 
+0x0a, 0x00, 0x00, 0xba, 0x00, 0x30, 0x82, 0xe5, 0x0c, 0x00, 0x92, 0xe5, 
+0x08, 0x30, 0x92, 0xe5, 0x00, 0x10, 0x91, 0xe2, 0x03, 0x00, 0x00, 0x0a, 
+0x03, 0x10, 0x80, 0xe7, 0x04, 0x30, 0x53, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 
+0x08, 0x30, 0x82, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1, 
+0x3c, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x80, 0xe2, 
+0x00, 0x00, 0x81, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0xf8, 0xff, 0xff, 0xea, 
+0x10, 0x00, 0x9f, 0xe5, 0x08, 0x10, 0x90, 0xe5, 0x04, 0x10, 0x51, 0xe2, 
+0x3c, 0x10, 0xa0, 0xb3, 0x08, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
+0xe4, 0x2d, 0x00, 0x80, 0xcc, 0x04, 0x00, 0x80, 0x5d, 0x2b, 0xff, 0xff, 
+0xbd, 0x3d, 0xff, 0xff, 0xb5, 0x2b, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 
+0xc9, 0x1c, 0x89, 0x08, 0x89, 0x00, 0x01, 0x23, 0x85, 0x4a, 0x5b, 0x07, 
+0x18, 0x43, 0x13, 0x68, 0x5b, 0x18, 0x13, 0x60, 0x00, 0x1f, 0x81, 0xa3, 
+0x5b, 0x1a, 0x18, 0x47, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
+0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
@@ -1879,7 +1892,6 @@ const u8 typhoon_firmware_image[] = {
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
-0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
@@ -1909,9 +1921,9 @@ const u8 typhoon_firmware_image[] = {
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
-0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0x50, 0x2d, 0x00, 0x80, 0x98, 0x00, 0x9f, 0xe5, 0x98, 0x10, 0x9f, 0xe5, 
-0x01, 0x20, 0x40, 0xe0, 0x94, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 
+0x04, 0x20, 0xa0, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80, 
+0x98, 0x00, 0x9f, 0xe5, 0x98, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 
+0x94, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 
 0x03, 0x00, 0x50, 0xe1, 0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 
 0x04, 0x20, 0x52, 0xe2, 0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 
 0x78, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 0x74, 0x00, 0x9f, 0xe5, 
@@ -1922,125 +1934,125 @@ const u8 typhoon_firmware_image[] = {
 0x4c, 0x00, 0x9f, 0xe5, 0x4c, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 
 0x2c, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1, 
 0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2, 
-0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 
-0x28, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0x7c, 0x34, 0x00, 0x80, 0x80, 0x30, 0x00, 0x80, 0xad, 0xde, 0xad, 0xde, 
-0x40, 0x04, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80, 0x80, 0x34, 0x00, 0x80, 
-0x44, 0x04, 0x00, 0x80, 0xfc, 0x3f, 0x00, 0x80, 0x40, 0x38, 0x00, 0x80, 
-0x48, 0x04, 0x00, 0x80, 0x78, 0x47, 0x00, 0x00, 0x91, 0xea, 0xff, 0xea, 
-0x78, 0x47, 0x00, 0x00, 0x39, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 
-0x63, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x1b, 0xff, 0xff, 0xea, 
-0x78, 0x47, 0x00, 0x00, 0x8b, 0xea, 0xff, 0xea, 0x00, 0x00, 0x00, 0x00, 
-0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x28, 0x04, 0x00, 0x00, 
-0x61, 0x6d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xff, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0xb9, 0x0b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0xd5, 0x0b, 0xff, 0xff, 0x03, 0xff, 0x06, 0x54, 0x03, 0x00, 0x00, 0x00, 
-0x75, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x05, 0xff, 0xff, 
-0x04, 0xff, 0x07, 0x54, 0x03, 0x00, 0x00, 0x00, 0xb5, 0x04, 0xff, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0xf1, 0x05, 0xff, 0xff, 0x05, 0xff, 0x05, 0x54, 
-0x03, 0x00, 0x00, 0x00, 0x39, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0x55, 0x05, 0xff, 0xff, 0x00, 0xff, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 
-0xf5, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x29, 0x0e, 0xff, 0xff, 
-0x01, 0xff, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x02, 0xff, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0xf1, 0x02, 0xff, 0xff, 0xff, 0xff, 0x01, 0x44, 
-0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x65, 0x0d, 0xff, 0xff, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0xbd, 0x4f, 0xff, 0xff, 0x01, 0x50, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 0x28, 0x00, 0x9f, 0xe5, 
+0x00, 0x20, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x7c, 0x34, 0x00, 0x80, 
+0x80, 0x30, 0x00, 0x80, 0xad, 0xde, 0xad, 0xde, 0xc0, 0x04, 0x00, 0x80, 
+0xfc, 0x37, 0x00, 0x80, 0x80, 0x34, 0x00, 0x80, 0xc4, 0x04, 0x00, 0x80, 
+0xfc, 0x3f, 0x00, 0x80, 0x40, 0x38, 0x00, 0x80, 0xc8, 0x04, 0x00, 0x80, 
+0x78, 0x47, 0x00, 0x00, 0x76, 0xea, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 
+0x39, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x63, 0xfe, 0xff, 0xea, 
+0x78, 0x47, 0x00, 0x00, 0x1b, 0xff, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 
+0x70, 0xea, 0xff, 0xea, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x80, 0x28, 0x04, 0x00, 0x00, 0x95, 0x22, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xb9, 0x0b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x0b, 0xff, 0xff, 
+0x03, 0xff, 0x06, 0x54, 0x03, 0x00, 0x00, 0x00, 0x75, 0x04, 0xff, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0xa1, 0x05, 0xff, 0xff, 0x04, 0xff, 0x07, 0x54, 
+0x03, 0x00, 0x00, 0x00, 0xb5, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
+0xf1, 0x05, 0xff, 0xff, 0x05, 0xff, 0x05, 0x54, 0x03, 0x00, 0x00, 0x00, 
+0x39, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x55, 0x05, 0xff, 0xff, 
+0x01, 0xff, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x41, 0x18, 0xff, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x61, 0x0e, 0xff, 0xff, 0x02, 0xff, 0x02, 0x08, 
+0x00, 0x00, 0x00, 0x00, 0xa1, 0x02, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
+0xf1, 0x02, 0xff, 0xff, 0xff, 0xff, 0x01, 0x44, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x0d, 0xff, 0xff, 
+0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x50, 0xff, 0xff, 
+0x6d, 0x50, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0xff, 0xff, 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, 0xc8, 0x04, 0x00, 0x80, 
-0x19, 0x78, 0x21, 0x40, 0x23, 0x78, 0x21, 0x40, 0x39, 0x78, 0x21, 0x40, 
-0x51, 0x78, 0x21, 0x40, 0x5d, 0x78, 0x21, 0x40, 0x6b, 0x78, 0x21, 0x40, 
-0x85, 0x78, 0x21, 0x40, 0xb1, 0x78, 0x21, 0x40, 0x75, 0x79, 0x21, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0x48, 0x05, 0x00, 0x80, 0x19, 0x78, 0x21, 0x40, 
+0x23, 0x78, 0x21, 0x40, 0x39, 0x78, 0x21, 0x40, 0x51, 0x78, 0x21, 0x40, 
+0x5d, 0x78, 0x21, 0x40, 0x6b, 0x78, 0x21, 0x40, 0x85, 0x78, 0x21, 0x40, 
+0xb1, 0x78, 0x21, 0x40, 0x75, 0x79, 0x21, 0x40, 
 0xcd, 0x79, 0x21, 0x40, 0xdb, 0x79, 0x21, 0x40, 0xe5, 0x79, 0x21, 0x40, 
-0xef, 0x79, 0x21, 0x40, 0x81, 0x7a, 0x21, 0x40, 0x8f, 0x7a, 0x21, 0x40, 
-0x9d, 0x7a, 0x21, 0x40, 0x35, 0x7b, 0x21, 0x40, 0x03, 0x7f, 0x21, 0x40, 
-0x71, 0x7f, 0x21, 0x40, 0x19, 0x80, 0x21, 0x40, 0x4d, 0x81, 0x21, 0x40, 
-0x59, 0x81, 0x21, 0x40, 0xb9, 0x81, 0x21, 0x40, 0x1d, 0x82, 0x21, 0x40, 
-0x49, 0x82, 0x21, 0x40, 0x6d, 0x82, 0x21, 0x40, 0xad, 0x82, 0x21, 0x40, 
-0xd5, 0x82, 0x21, 0x40, 0x1d, 0x83, 0x21, 0x40, 0x2d, 0x83, 0x21, 0x40, 
-0x55, 0x83, 0x21, 0x40, 0x65, 0x83, 0x21, 0x40, 0xad, 0x83, 0x21, 0x40, 
-0xeb, 0x83, 0x21, 0x40, 0x41, 0x84, 0x21, 0x40, 0xa1, 0x84, 0x21, 0x40, 
-0xab, 0x84, 0x21, 0x40, 0xaf, 0x84, 0x21, 0x40, 0x1d, 0x85, 0x21, 0x40, 
-0x75, 0x85, 0x21, 0x40, 0xcd, 0x85, 0x21, 0x40, 
-0x09, 0x86, 0x21, 0x40, 0x6d, 0x86, 0x21, 0x40, 0xa5, 0x86, 0x21, 0x40, 
-0xb5, 0x86, 0x21, 0x40, 0xed, 0x86, 0x21, 0x40, 0xfd, 0x86, 0x21, 0x40, 
-0x11, 0x87, 0x21, 0x40, 0x39, 0x87, 0x21, 0x40, 0x43, 0x87, 0x21, 0x40, 
-0x4d, 0x87, 0x21, 0x40, 0x57, 0x87, 0x21, 0x40, 0xc1, 0x87, 0x21, 0x40, 
-0xcd, 0x87, 0x21, 0x40, 0x41, 0x88, 0x21, 0x40, 0x4b, 0x88, 0x21, 0x40, 
-0x55, 0x88, 0x21, 0x40, 0x5f, 0x88, 0x21, 0x40, 0x69, 0x88, 0x21, 0x40, 
-0x73, 0x88, 0x21, 0x40, 0x7d, 0x88, 0x21, 0x40, 0x87, 0x88, 0x21, 0x40, 
-0x91, 0x88, 0x21, 0x40, 0x9b, 0x88, 0x21, 0x40, 0xa5, 0x88, 0x21, 0x40, 
-0xaf, 0x88, 0x21, 0x40, 0xb9, 0x88, 0x21, 0x40, 0xc3, 0x88, 0x21, 0x40, 
-0xeb, 0x88, 0x21, 0x40, 0xf5, 0x88, 0x21, 0x40, 0x51, 0x89, 0x21, 0x40, 
-0x5b, 0x89, 0x21, 0x40, 0x65, 0x89, 0x21, 0x40, 0x6f, 0x89, 0x21, 0x40, 
-0x79, 0x89, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 0x83, 0x89, 0x21, 0x40, 
-0xe9, 0x89, 0x21, 0x40, 0x35, 0x8a, 0x21, 0x40, 0x81, 0x8a, 0x21, 0x40, 
-0x91, 0x8a, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 0xdd, 0x8a, 0x21, 0x40, 
-0xe1, 0x8a, 0x21, 0x40, 0xe5, 0x8a, 0x21, 0x40, 0x3d, 0x8b, 0x21, 0x40, 
-0x65, 0x8b, 0x21, 0x40, 0x71, 0x8b, 0x21, 0x40, 0x75, 0x8b, 0x21, 0x40, 
-0x79, 0x8b, 0x21, 0x40, 0xe9, 0x8b, 0x21, 0x40, 0xed, 0x8b, 0x21, 0x40, 
-0xf1, 0x8b, 0x21, 0x40, 0x7d, 0x8b, 0x21, 0x40, 0x05, 0x88, 0x21, 0x40, 
-0xa5, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 0xf5, 0x8b, 0x21, 0x40, 
-0xe9, 0xc1, 0x21, 0x40, 0xe9, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 
-0xa5, 0x77, 0x21, 0x40, 0xcd, 0xc2, 0x21, 0x40, 0x03, 0xc3, 0x21, 0x40, 
-0x35, 0xc3, 0x21, 0x40, 0x4d, 0x8c, 0x21, 0x40, 0x3f, 0x7b, 0x21, 0x40, 
-0x99, 0x7e, 0x21, 0x40, 0xd5, 0x7e, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x5c, 0x01, 0x18, 0x40, 0x58, 0x01, 0x18, 0x40, 0x24, 0xa3, 0x20, 0x40, 
-0x24, 0xa7, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x6c, 0x01, 0x18, 0x40, 0x68, 0x01, 0x18, 0x40, 0x24, 0x83, 0x20, 0x40, 
-0x24, 0xa3, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x7c, 0x01, 0x18, 0x40, 0x78, 0x01, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x8c, 0x01, 0x18, 0x40, 0x88, 0x01, 0x18, 0x40, 0x24, 0xa9, 0x20, 0x40, 
-0x24, 0xab, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xef, 0x79, 0x21, 0x40, 0x8d, 0x7a, 0x21, 0x40, 0x9b, 0x7a, 0x21, 0x40, 
+0xa9, 0x7a, 0x21, 0x40, 0x51, 0x7b, 0x21, 0x40, 0x4f, 0x7f, 0x21, 0x40, 
+0xc9, 0x7f, 0x21, 0x40, 0x69, 0x80, 0x21, 0x40, 0x9d, 0x81, 0x21, 0x40, 
+0xa9, 0x81, 0x21, 0x40, 0x09, 0x82, 0x21, 0x40, 0x6d, 0x82, 0x21, 0x40, 
+0x99, 0x82, 0x21, 0x40, 0xbd, 0x82, 0x21, 0x40, 0xfd, 0x82, 0x21, 0x40, 
+0x25, 0x83, 0x21, 0x40, 0x6d, 0x83, 0x21, 0x40, 0x7d, 0x83, 0x21, 0x40, 
+0xa5, 0x83, 0x21, 0x40, 0xb5, 0x83, 0x21, 0x40, 0xfd, 0x83, 0x21, 0x40, 
+0x3b, 0x84, 0x21, 0x40, 0x91, 0x84, 0x21, 0x40, 0xf1, 0x84, 0x21, 0x40, 
+0xfb, 0x84, 0x21, 0x40, 0xff, 0x84, 0x21, 0x40, 0x6d, 0x85, 0x21, 0x40, 
+0xb9, 0x85, 0x21, 0x40, 0x11, 0x86, 0x21, 0x40, 0x4d, 0x86, 0x21, 0x40, 
+0xb1, 0x86, 0x21, 0x40, 0xe9, 0x86, 0x21, 0x40, 0xf9, 0x86, 0x21, 0x40, 
+0x31, 0x87, 0x21, 0x40, 0x41, 0x87, 0x21, 0x40, 0x55, 0x87, 0x21, 0x40, 
+0x7d, 0x87, 0x21, 0x40, 0x87, 0x87, 0x21, 0x40, 0x91, 0x87, 0x21, 0x40, 
+0xf5, 0x87, 0x21, 0x40, 0x25, 0x88, 0x21, 0x40, 0x31, 0x88, 0x21, 0x40, 
+0xa5, 0x88, 0x21, 0x40, 0xaf, 0x88, 0x21, 0x40, 0xb9, 0x88, 0x21, 0x40, 
+0xc3, 0x88, 0x21, 0x40, 0xcd, 0x88, 0x21, 0x40, 0xd7, 0x88, 0x21, 0x40, 
+0xe1, 0x88, 0x21, 0x40, 0xeb, 0x88, 0x21, 0x40, 0xf5, 0x88, 0x21, 0x40, 
+0xe9, 0x8b, 0x21, 0x40, 0xff, 0x88, 0x21, 0x40, 0x09, 0x89, 0x21, 0x40, 
+0x13, 0x89, 0x21, 0x40, 0x1d, 0x89, 0x21, 0x40, 0x45, 0x89, 0x21, 0x40, 
+0x4f, 0x89, 0x21, 0x40, 0xb1, 0x89, 0x21, 0x40, 0xbb, 0x89, 0x21, 0x40, 
+0xc5, 0x89, 0x21, 0x40, 0xcf, 0x89, 0x21, 0x40, 0xd9, 0x89, 0x21, 0x40, 
+0xa5, 0x77, 0x21, 0x40, 0xe3, 0x89, 0x21, 0x40, 0x49, 0x8a, 0x21, 0x40, 
+0x95, 0x8a, 0x21, 0x40, 0xe1, 0x8a, 0x21, 0x40, 0xf1, 0x8a, 0x21, 0x40, 
+0xa5, 0x77, 0x21, 0x40, 0x3d, 0x8b, 0x21, 0x40, 0x41, 0x8b, 0x21, 0x40, 
+0x45, 0x8b, 0x21, 0x40, 0x9d, 0x8b, 0x21, 0x40, 0xc5, 0x8b, 0x21, 0x40, 
+0xd1, 0x8b, 0x21, 0x40, 0xd5, 0x8b, 0x21, 0x40, 0xd9, 0x8b, 0x21, 0x40, 
+0xdd, 0x8b, 0x21, 0x40, 0xe1, 0x8b, 0x21, 0x40, 0xe5, 0x8b, 0x21, 0x40, 
+0x0d, 0x88, 0x21, 0x40, 0x69, 0x88, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 
+0xa5, 0x77, 0x21, 0x40, 0xf5, 0x8b, 0x21, 0x40, 0xe1, 0xc9, 0x21, 0x40, 
+0xe9, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 
+0xdd, 0xca, 0x21, 0x40, 0x13, 0xcb, 0x21, 0x40, 0x45, 0xcb, 0x21, 0x40, 
+0x4d, 0x8c, 0x21, 0x40, 0x5b, 0x7b, 0x21, 0x40, 0xe5, 0x7e, 0x21, 0x40, 
+0x21, 0x7f, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x18, 0x40, 
+0x58, 0x01, 0x18, 0x40, 0x24, 0xa3, 0x20, 0x40, 0x24, 0xa7, 0x20, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x18, 0x40, 
+0x68, 0x01, 0x18, 0x40, 0x24, 0x83, 0x20, 0x40, 0x24, 0xa3, 0x20, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x18, 0x40, 
+0x78, 0x01, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x18, 0x40, 
+0x88, 0x01, 0x18, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x24, 0xab, 0x20, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x12, 0x00, 
 0x0c, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x24, 0xa8, 0x20, 0x40, 
 0xa4, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x11, 0xb2, 0x21, 0x40, 0x6d, 0xb3, 0x21, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x91, 0x73, 0x21, 0x40, 0x89, 0xaa, 0x21, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0xa5, 0xb9, 0x21, 0x40, 0x01, 0xbb, 0x21, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0x91, 0x73, 0x21, 0x40, 0x19, 0xb2, 0x21, 0x40, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x67, 0x92, 0x21, 0x40, 0x11, 0xb2, 0x21, 0x40, 
-0x39, 0x2f, 0xff, 0xff, 0xad, 0x20, 0xff, 0xff, 0x97, 0x20, 0xff, 0xff, 
-0xe9, 0xb0, 0x21, 0x40, 0xa0, 0x2d, 0x00, 0x80, 0xb4, 0x2d, 0x00, 0x80, 
-0xc8, 0x2d, 0x00, 0x80, 0x30, 0x33, 0x3a, 0x31, 0x31, 0x3a, 0x31, 0x31, 
-0x00, 0x30, 0x37, 0x2f, 0x32, 0x33, 0x2f, 0x30, 
-0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x36, 0x39, 0x00, 0x43, 
-0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 
-0x20, 0x32, 0x30, 0x30, 0x31, 0x20, 0x33, 0x43, 0x6f, 0x6d, 0x20, 0x43, 
-0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x00, 
-0x17, 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x0c, 0x53, 0xff, 0xff, 0x27, 0xf0, 0x7d, 0xfd, 
-0x00, 0x01, 0x00, 0x02, 0xda, 0x0e, 0x82, 0x00, 0x01, 0x40, 0x64, 0x04, 
-0xd0, 0x2c, 0x00, 0x80, 0x50, 0x2c, 0x00, 0x80, 0xe5, 0x3d, 0xff, 0xff, 
-0x49, 0x4f, 0xff, 0xff, 0x79, 0x24, 0xff, 0xff, 0x3d, 0x3b, 0xff, 0xff, 
-0x9d, 0x3b, 0xff, 0xff, 0xa1, 0x19, 0xff, 0xff, 0x19, 0x11, 0xff, 0xff, 
-0x4c, 0x53, 0xff, 0xff, 0x99, 0x3f, 0xff, 0xff, 0x91, 0x73, 0x21, 0x40, 
-0x51, 0x75, 0x21, 0x40, 0x51, 0x3f, 0xff, 0xff, 0x11, 0xa3, 0x21, 0x40, 
-0x29, 0x24, 0xff, 0xff, 0xe4, 0x52, 0xff, 0xff, 0x0c, 0x53, 0xff, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 
-0xb8, 0x60, 0x00, 0x00, 0x74, 0x6c, 0x00, 0x00, 0x00, 0x6e, 0x21, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
-0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
-0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
-0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 
-0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 
-0xfd, 0x92, 0x21, 0x40, 0x9b, 0x92, 0x21, 0x40, 0xc1, 0x95, 0x21, 0x40, 
-0x21, 0x96, 0x21, 0x40, 0xe9, 0x96, 0x21, 0x40, 0xa7, 0x94, 0x21, 0x40, 
-0xc5, 0x97, 0x21, 0x40, 0x31, 0x98, 0x21, 0x40, 0x85, 0x94, 0x21, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0xa7, 0x99, 0x21, 0x40, 0xa5, 0xb9, 0x21, 0x40, 
+0xb1, 0x2f, 0xff, 0xff, 0xf1, 0x20, 0xff, 0xff, 0xdb, 0x20, 0xff, 0xff, 
+0x2d, 0xb8, 0x21, 0x40, 0x34, 0x2e, 0x00, 0x80, 0x48, 0x2e, 0x00, 0x80, 
+0x5c, 0x2e, 0x00, 0x80, 0x30, 0x33, 0x3a, 0x31, 0x31, 0x3a, 0x31, 0x31, 
+0x00, 0x30, 0x37, 0x2f, 0x32, 0x33, 0x2f, 0x30, 0x31, 0x00, 0x30, 0x30, 
+0x30, 0x30, 0x31, 0x35, 0x36, 0x39, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 
+0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 
+0x31, 0x20, 0x33, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 
+0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x00, 0x02, 0x10, 0x00, 0x03, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x78, 0x53, 0xff, 0xff, 0x27, 0xf0, 0x7d, 0xfd, 0x00, 0x01, 0x00, 0x02, 
+0xda, 0x0e, 0x82, 0x00, 0x01, 0x40, 0x64, 0x04, 0x64, 0x2d, 0x00, 0x80, 
+0xe4, 0x2c, 0x00, 0x80, 0x55, 0x3e, 0xff, 0xff, 0xb5, 0x4f, 0xff, 0xff, 
+0xc1, 0x24, 0xff, 0xff, 0xb5, 0x3b, 0xff, 0xff, 0x15, 0x3c, 0xff, 0xff, 
+0x05, 0x1a, 0xff, 0xff, 0x65, 0x11, 0xff, 0xff, 0xb8, 0x53, 0xff, 0xff, 
+0x0d, 0x40, 0xff, 0xff, 0x91, 0x73, 0x21, 0x40, 0x51, 0x75, 0x21, 0x40, 
+0xc5, 0x3f, 0xff, 0xff, 0x71, 0xaa, 0x21, 0x40, 0x71, 0x24, 0xff, 0xff, 
+0x50, 0x53, 0xff, 0xff, 0x78, 0x53, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0xff, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0xec, 0x68, 0x00, 0x00, 
+0x10, 0x5c, 0x00, 0x00, 0x00, 0x6e, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 
+0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
+0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
+0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
+0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 
+0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 
+0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 
+0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x9a, 0x21, 0x40, 
+0xdb, 0x99, 0x21, 0x40, 0xf5, 0x9c, 0x21, 0x40, 0x55, 0x9d, 0x21, 0x40, 
+0x1d, 0x9e, 0x21, 0x40, 0xdb, 0x9b, 0x21, 0x40, 0xf9, 0x9e, 0x21, 0x40, 
+0x65, 0x9f, 0x21, 0x40, 0xb9, 0x9b, 0x21, 0x40, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
@@ -2051,7 +2063,6 @@ const u8 typhoon_firmware_image[] = {
 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, 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, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
@@ -2084,92 +2095,93 @@ const u8 typhoon_firmware_image[] = {
 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, 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, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
-0xb5, 0xce, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xc3, 0x21, 0x40, 
-0x45, 0xc5, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xcc, 0x21, 0x40, 
-0x59, 0xcd, 0x21, 0x40, 0xc5, 0xcd, 0x21, 0x40, 0x09, 0x29, 0x09, 0xd1, 
+0xe9, 0xd6, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xcb, 0x21, 0x40, 
+0x55, 0xcd, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x25, 0xd5, 0x21, 0x40, 
+0x8d, 0xd5, 0x21, 0x40, 0xf9, 0xd5, 0x21, 0x40, 0x09, 0x29, 0x09, 0xd1, 
 0x20, 0x28, 0x07, 0xd2, 0x04, 0x48, 0x01, 0x78, 0x00, 0x29, 0x03, 0xd1, 
 0x01, 0x21, 0x01, 0x70, 0x02, 0x48, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7, 
 0x00, 0x6e, 0x21, 0x40, 0x24, 0xab, 0x20, 0x40, 0x03, 0x49, 0x88, 0x42, 
 0x03, 0xd1, 0x00, 0x20, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x70, 0x70, 0x47, 
-0x24, 0xab, 0x20, 0x40, 0x00, 0x6e, 0x21, 0x40, 
-0x00, 0xb5, 0x00, 0x20, 0x0b, 0x4a, 0x0b, 0x23, 0x1b, 0x02, 0xd1, 0x18, 
-0x2d, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x48, 0x61, 0x98, 0x60, 0x98, 0x63, 
-0x80, 0x32, 0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0x62, 0x05, 0x48, 
-0xc0, 0x46, 0x08, 0x60, 0x48, 0x60, 0x05, 0xf0, 0xc3, 0xf9, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0xfe, 0x03, 0x00, 0x00, 
-0xf0, 0xb5, 0x84, 0xb0, 0x0c, 0x1c, 0x05, 0x1c, 0x00, 0x23, 0x00, 0x93, 
-0xff, 0xf7, 0xda, 0xff, 0x68, 0x49, 0x0b, 0x23, 0x1b, 0x02, 0xcf, 0x18, 
-0x38, 0x68, 0x28, 0x40, 0x00, 0x22, 0xb8, 0x60, 0xfa, 0x60, 0x7a, 0x68, 
-0x22, 0x40, 0x3a, 0x61, 0x0c, 0x1c, 0x41, 0x09, 0x03, 0xd2, 0x51, 0x09, 
-0x01, 0xd2, 0x80, 0x0a, 0x02, 0xd3, 0x60, 0x48, 0x00, 0xf0, 0xc2, 0xf8, 
-0x01, 0x20, 0xb9, 0x68, 0x49, 0x09, 0x03, 0xd2, 0x39, 0x69, 0x49, 0x09, 
-0x00, 0xd2, 0x00, 0x20, 0x00, 0x06, 0x00, 0x0e, 0x03, 0xf0, 0xf8, 0xfd, 
-0xb8, 0x68, 0x00, 0x28, 0x70, 0xd0, 0x00, 0x23, 0x02, 0x93, 0x01, 0x93, 
-0x54, 0x4a, 0x01, 0x23, 0x18, 0x43, 0xb8, 0x60, 0x00, 0x20, 0xd5, 0x1d, 
-0x79, 0x35, 0x03, 0x95, 0x01, 0x24, 0x00, 0x21, 0x4f, 0x4d, 0xba, 0x68, 
-0x22, 0x40, 0x39, 0xd0, 0x8a, 0x00, 0x52, 0x18, 0x92, 0x00, 0x4e, 0x4b, 
-0x9b, 0x5c, 0x1e, 0x1c, 0x83, 0x42, 0x04, 0xd0, 0x4b, 0x4b, 0xd3, 0x18, 
-0x5b, 0x78, 0x83, 0x42, 0x2c, 0xd1, 0x49, 0x4b, 0xd2, 0x18, 0xd3, 0x78, 
-0x03, 0x9d, 0xad, 0x6a, 0xab, 0x42, 0x02, 0xd9, 0x03, 0x9d, 0xc0, 0x46, 
-0xab, 0x62, 0x53, 0x68, 0x5b, 0x08, 0x01, 0xd3, 0x01, 0x23, 0x00, 0x93, 
-0x86, 0x42, 0x0a, 0xd1, 0x95, 0x68, 0x02, 0x9b, 0x5e, 0x1c, 0x02, 0x96, 
-0x9b, 0x00, 0x3c, 0x4e, 0x9e, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xf3, 0x18, 
-0x5d, 0x61, 0x53, 0x78, 0x83, 0x42, 0x0d, 0xd1, 0xd2, 0x68, 0x01, 0x9b, 
-0x5d, 0x1c, 0x01, 0x95, 0x9b, 0x00, 0x35, 0x4d, 0x5d, 0x19, 0x2d, 0x23, 
-0x9b, 0x01, 0xeb, 0x18, 0x9a, 0x60, 0xfa, 0x68, 0x01, 0x32, 0xfa, 0x60, 
-0x64, 0x00, 0x01, 0x31, 0x0b, 0x29, 0xbd, 0xd3, 0x01, 0x30, 0x09, 0x28, 
-0xb8, 0xd3, 0x00, 0x20, 0x02, 0x9b, 0x99, 0x00, 0x2b, 0x4a, 0x89, 0x18, 
-0x0b, 0x23, 0x1b, 0x02, 0xc9, 0x18, 0x48, 0x61, 0x01, 0x9b, 0x99, 0x00, 
-0x89, 0x18, 0x2d, 0x23, 0x9b, 0x01, 0xc9, 0x18, 0x88, 0x60, 0x00, 0x9b, 
-0x00, 0x2b, 0x0c, 0xd1, 0x81, 0x00, 0x89, 0x18, 0x0b, 0x23, 0x1b, 0x02, 
-0xc9, 0x18, 0x8b, 0x69, 0xc0, 0x46, 0x4b, 0x61, 0x01, 0x30, 0x0b, 0x28, 
-0xf4, 0xd3, 0x08, 0xe0, 0x07, 0xe0, 0x03, 0x9d, 0xa8, 0x6a, 0x30, 0x28, 
-0x03, 0xd2, 0x30, 0x20, 0x03, 0x9d, 0xc0, 0x46, 0xa8, 0x62, 0x19, 0x4a, 
-0x38, 0x69, 0x00, 0x28, 0x2a, 0xd0, 0x00, 0x21, 0x01, 0x23, 0x18, 0x43, 
-0x38, 0x61, 0x00, 0x20, 0x01, 0x24, 0x00, 0x22, 0x13, 0x4e, 0x3b, 0x69, 
+0x24, 0xab, 0x20, 0x40, 0x00, 0x6e, 0x21, 0x40, 0x00, 0xb5, 0x00, 0x20, 
+0x0b, 0x4a, 0x0b, 0x23, 0x1b, 0x02, 0xd1, 0x18, 0x2d, 0x23, 0x9b, 0x01, 
+0xd3, 0x18, 0x88, 0x61, 0xd8, 0x60, 0xd8, 0x63, 0x80, 0x32, 0xc8, 0x60, 
+0x08, 0x61, 0x48, 0x61, 0xd0, 0x62, 0x05, 0x48, 0xc0, 0x46, 0x48, 0x60, 
+0x88, 0x60, 0x05, 0xf0, 0xcb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0xfe, 0x03, 0x00, 0x00, 0xf0, 0xb5, 0x84, 0xb0, 
+0x0c, 0x1c, 0x05, 0x1c, 0x00, 0x23, 0x00, 0x93, 0xff, 0xf7, 0xda, 0xff, 
+0x68, 0x49, 0x0b, 0x23, 0x1b, 0x02, 0xcf, 0x18, 0x78, 0x68, 0x28, 0x40, 
+0x00, 0x22, 0xf8, 0x60, 0x3a, 0x61, 0xba, 0x68, 0x22, 0x40, 0x7a, 0x61, 
+0x0c, 0x1c, 0x41, 0x09, 0x03, 0xd2, 0x51, 0x09, 0x01, 0xd2, 0x80, 0x0a, 
+0x02, 0xd3, 0x60, 0x48, 0x00, 0xf0, 0xc2, 0xf8, 0x01, 0x20, 0xf9, 0x68, 
+0x49, 0x09, 0x03, 0xd2, 0x79, 0x69, 0x49, 0x09, 0x00, 0xd2, 0x00, 0x20, 
+0x00, 0x06, 0x00, 0x0e, 0x04, 0xf0, 0xc8, 0xf9, 0xf8, 0x68, 0x00, 0x28, 
+0x70, 0xd0, 0x00, 0x23, 0x02, 0x93, 0x01, 0x93, 0x54, 0x4a, 0x01, 0x23, 
+0x18, 0x43, 0xf8, 0x60, 0x00, 0x20, 0xd5, 0x1d, 0x79, 0x35, 0x03, 0x95, 
+0x01, 0x24, 0x00, 0x21, 0x4f, 0x4d, 0xfa, 0x68, 0x22, 0x40, 0x39, 0xd0, 
+0x8a, 0x00, 0x52, 0x18, 0x92, 0x00, 0x4e, 0x4b, 0x9b, 0x5c, 0x1e, 0x1c, 
+0x83, 0x42, 0x04, 0xd0, 0x4b, 0x4b, 0xd3, 0x18, 0x5b, 0x78, 0x83, 0x42, 
+0x2c, 0xd1, 0x49, 0x4b, 0xd2, 0x18, 0xd3, 0x78, 0x03, 0x9d, 0xed, 0x6a, 
+0xab, 0x42, 0x02, 0xd9, 0x03, 0x9d, 0xc0, 0x46, 0xeb, 0x62, 0x53, 0x68, 
+0x5b, 0x08, 0x01, 0xd3, 0x01, 0x23, 0x00, 0x93, 0x86, 0x42, 0x0a, 0xd1, 
+0x95, 0x68, 0x02, 0x9b, 0x5e, 0x1c, 0x02, 0x96, 0x9b, 0x00, 0x3c, 0x4e, 
+0x9e, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xf3, 0x18, 0x9d, 0x61, 0x53, 0x78, 
+0x83, 0x42, 0x0d, 0xd1, 0xd2, 0x68, 0x01, 0x9b, 0x5d, 0x1c, 0x01, 0x95, 
+0x9b, 0x00, 0x35, 0x4d, 0x5d, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xeb, 0x18, 
+0xda, 0x60, 0x3a, 0x69, 0x01, 0x32, 0x3a, 0x61, 0x64, 0x00, 0x01, 0x31, 
+0x0b, 0x29, 0xbd, 0xd3, 0x01, 0x30, 0x09, 0x28, 0xb8, 0xd3, 0x00, 0x20, 
+0x02, 0x9b, 0x99, 0x00, 0x2b, 0x4a, 0x89, 0x18, 0x0b, 0x23, 0x1b, 0x02, 
+0xc9, 0x18, 0x88, 0x61, 0x01, 0x9b, 0x99, 0x00, 0x89, 0x18, 0x2d, 0x23, 
+0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x60, 0x00, 0x9b, 0x00, 0x2b, 0x0c, 0xd1, 
+0x81, 0x00, 0x89, 0x18, 0x0b, 0x23, 0x1b, 0x02, 0xc9, 0x18, 0xcb, 0x69, 
+0xc0, 0x46, 0x8b, 0x61, 0x01, 0x30, 0x0b, 0x28, 0xf4, 0xd3, 0x08, 0xe0, 
+0x07, 0xe0, 0x03, 0x9d, 0xe8, 0x6a, 0x30, 0x28, 
+0x03, 0xd2, 0x30, 0x20, 0x03, 0x9d, 0xc0, 0x46, 0xe8, 0x62, 0x19, 0x4a, 
+0x78, 0x69, 0x00, 0x28, 0x2a, 0xd0, 0x00, 0x21, 0x01, 0x23, 0x18, 0x43, 
+0x78, 0x61, 0x00, 0x20, 0x01, 0x24, 0x00, 0x22, 0x13, 0x4e, 0x7b, 0x69, 
 0x23, 0x40, 0x10, 0xd0, 0x93, 0x00, 0x9b, 0x18, 0x9b, 0x00, 0x12, 0x4d, 
 0x5b, 0x19, 0x9d, 0x78, 0x85, 0x42, 0x08, 0xd1, 0x1d, 0x69, 0x0b, 0x1c, 
-0x9b, 0x00, 0x9e, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0x9d, 0x63, 
+0x9b, 0x00, 0x9e, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0xdd, 0x63, 
 0x01, 0x31, 0x64, 0x00, 0x01, 0x32, 0x0b, 0x2a, 0xe6, 0xd3, 0x01, 0x30, 
 0x09, 0x28, 0xe1, 0xd3, 0x00, 0x20, 0x89, 0x00, 0x04, 0x4a, 0x89, 0x18, 
-0x2d, 0x23, 0x9b, 0x01, 0xc9, 0x18, 0x88, 0x63, 0x04, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0xb0, 0x52, 0xff, 0xff, 
-0x80, 0x00, 0x00, 0x80, 0x00, 0x47, 0x08, 0x47, 
-0x10, 0x47, 0x18, 0x47, 0x78, 0x47, 0xc0, 0x46, 0x34, 0xc0, 0x9f, 0xe5, 
-0x1c, 0xff, 0x2f, 0xe1, 0x78, 0x47, 0xc0, 0x46, 0x2c, 0xc0, 0x9f, 0xe5, 
-0x1c, 0xff, 0x2f, 0xe1, 0x78, 0x47, 0xc0, 0x46, 0x24, 0xc0, 0x9f, 0xe5, 
-0x1c, 0xff, 0x2f, 0xe1, 0xc0, 0x46, 0xff, 0xb4, 0x75, 0x46, 0x20, 0xb4, 
-0x01, 0x21, 0x08, 0x43, 0x01, 0xa4, 0xa6, 0x46, 0x00, 0x47, 0xc0, 0x46, 
-0x20, 0xbc, 0xae, 0x46, 0xff, 0xbc, 0xf7, 0x46, 0xb8, 0x51, 0xff, 0xff, 
-0x08, 0x51, 0xff, 0xff, 0xd7, 0xb7, 0x21, 0x40, 0xf0, 0xb5, 0x04, 0x20, 
-0x1a, 0x49, 0x01, 0x25, 0x08, 0x60, 0x1a, 0x4f, 0xbb, 0x23, 0x1b, 0x01, 
-0xf8, 0x18, 0x05, 0x72, 0x18, 0x48, 0x41, 0x6b, 0x2c, 0x05, 0x00, 0x20, 
-0x7a, 0x6e, 0x17, 0x4b, 0x8a, 0x42, 0x1d, 0xd0, 0x19, 0x7b, 0x00, 0x29, 
-0x17, 0xd1, 0xd9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x1e, 0x1c, 
-0x00, 0x29, 0x10, 0xd1, 0xb0, 0x60, 0x10, 0x20, 0x70, 0x60, 0x10, 0x4a, 
-0x10, 0x49, 0xff, 0xf7, 0xb5, 0xff, 0x00, 0x28, 0x07, 0xd0, 0x35, 0x73, 
-0x04, 0x23, 0xb8, 0x69, 0x18, 0x43, 0xb8, 0x61, 0x20, 0x61, 0x00, 0xf0, 
-0x17, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x18, 0x73, 0x04, 0x23, 
-0xb8, 0x69, 0x98, 0x43, 0xb8, 0x61, 0x20, 0x61, 0xf5, 0xe7, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x01, 0x18, 0x40, 
-0xa8, 0x04, 0x00, 0x80, 0xa0, 0x54, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40, 
-0xf8, 0xb5, 0x15, 0x4f, 0x39, 0x6c, 0x15, 0x48, 0x40, 0x6e, 0x0c, 0x1a, 
-0x14, 0x4e, 0x71, 0x68, 0x14, 0x4d, 0xa1, 0x42, 0x06, 0xd8, 0x14, 0x4a, 
-0x0a, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18, 0xfa, 0x6b, 0x11, 0xe0, 
-0x11, 0x22, 0x52, 0x05, 0x22, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18, 
-0x00, 0x20, 0xfa, 0x6b, 0x2b, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x70, 0x68, 
-0x00, 0x1b, 0x0a, 0x4a, 0x02, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0xfa, 0x6b, 
-0x00, 0x20, 0x2b, 0x1c, 0xff, 0xf7, 0x74, 0xff, 0xf8, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xf8, 0x28, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 
-0xa8, 0x04, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x37, 0x02, 
-0xf0, 0xb5, 0x2b, 0x4f, 0xb8, 0x68, 0x79, 0x68, 0xc0, 0x19, 0x20, 0x30, 
-0x29, 0x4a, 0xff, 0xf7, 0x55, 0xff, 0x01, 0x20, 0xc0, 0x02, 0x28, 0x49, 
-0xc0, 0x46, 0x08, 0x60, 0xb9, 0x68, 0x38, 0x1c, 0x26, 0x4d, 0x00, 0x24, 
-0x26, 0x4e, 0xef, 0x1d, 0x79, 0x37, 0x00, 0x29, 0x31, 0xd1, 0x31, 0x68, 
-0x0a, 0x78, 0x12, 0x0a, 0x03, 0xd2, 0x04, 0x73, 0xf0, 0xbc, 0x08, 0xbc, 
+0x2d, 0x23, 0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x63, 0x04, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x1c, 0x53, 0xff, 0xff, 
+0x00, 0x01, 0x00, 0x80, 0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 
+0x78, 0x47, 0xc0, 0x46, 0x34, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 
+0x78, 0x47, 0xc0, 0x46, 0x2c, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 
+0x78, 0x47, 0xc0, 0x46, 0x24, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 
+0xc0, 0x46, 0xff, 0xb4, 0x75, 0x46, 0x20, 0xb4, 0x01, 0x21, 0x08, 0x43, 
+0x01, 0xa4, 0xa6, 0x46, 0x00, 0x47, 0xc0, 0x46, 0x20, 0xbc, 0xae, 0x46, 
+0xff, 0xbc, 0xf7, 0x46, 0x24, 0x52, 0xff, 0xff, 0x74, 0x51, 0xff, 0xff, 
+0x51, 0xc0, 0x21, 0x40, 0xf0, 0xb5, 0x04, 0x20, 0x1a, 0x49, 0x01, 0x25, 
+0x08, 0x60, 0x1a, 0x4f, 0xbb, 0x23, 0x1b, 0x01, 0xf8, 0x18, 0x05, 0x73, 
+0x18, 0x48, 0x41, 0x6b, 0x2c, 0x05, 0x00, 0x20, 0x7a, 0x6e, 0x17, 0x4b, 
+0x8a, 0x42, 0x1d, 0xd0, 0x19, 0x7b, 0x00, 0x29, 0x17, 0xd1, 0xd9, 0x1d, 
+0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x1e, 0x1c, 0x00, 0x29, 0x10, 0xd1, 
+0xb0, 0x60, 0x10, 0x20, 0x70, 0x60, 0x10, 0x4a, 0x10, 0x49, 0xff, 0xf7, 
+0xb5, 0xff, 0x00, 0x28, 0x07, 0xd0, 0x35, 0x73, 0x04, 0x23, 0xb8, 0x69, 
+0x18, 0x43, 0xb8, 0x61, 0x20, 0x61, 0x00, 0xf0, 0x17, 0xf8, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x18, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x98, 0x43, 
+0xb8, 0x61, 0x20, 0x61, 0xf5, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x18, 0x40, 0x28, 0x05, 0x00, 0x80, 
+0x0c, 0x55, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40, 0xf8, 0xb5, 0x15, 0x4f, 
+0x39, 0x6c, 0x15, 0x48, 0x40, 0x6e, 0x0c, 0x1a, 0x14, 0x4e, 0x71, 0x68, 
+0x14, 0x4d, 0xa1, 0x42, 0x06, 0xd8, 0x14, 0x4a, 0x0a, 0x43, 0x00, 0x92, 
+0xb9, 0x6b, 0x09, 0x18, 0xfa, 0x6b, 0x11, 0xe0, 0x11, 0x22, 0x52, 0x05, 
+0x22, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18, 0x00, 0x20, 0xfa, 0x6b, 
+0x2b, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x70, 0x68, 0x00, 0x1b, 0x0a, 0x4a, 
+0x02, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0xfa, 0x6b, 0x00, 0x20, 0x2b, 0x1c, 
+0xff, 0xf7, 0x74, 0xff, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x7c, 0x29, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 
+0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x37, 0x02, 0xf0, 0xb5, 0x2b, 0x4f, 
+0xb8, 0x68, 0x79, 0x68, 0xc0, 0x19, 0x20, 0x30, 0x29, 0x4a, 0xff, 0xf7, 
+0x55, 0xff, 0x01, 0x20, 0xc0, 0x02, 0x28, 0x49, 0xc0, 0x46, 0x08, 0x60, 
+0xb9, 0x68, 0x38, 0x1c, 0x26, 0x4d, 0x00, 0x24, 0x26, 0x4e, 0xef, 0x1d, 
+0x79, 0x37, 0x00, 0x29, 0x31, 0xd1, 0x31, 0x68, 0x0a, 0x78, 0x12, 0x0a, 
+0x03, 0xd2, 0x04, 0x73, 0xf0, 0xbc, 0x08, 0xbc, 
 0x18, 0x47, 0x49, 0x78, 0x00, 0x29, 0x0c, 0xd1, 0x05, 0x1c, 0x40, 0x68, 
 0x00, 0xf0, 0x3e, 0xf9, 0x30, 0x68, 0x00, 0xf0, 0x67, 0xf8, 0x00, 0x28, 
 0x26, 0xd1, 0x2c, 0x73, 0xff, 0xf7, 0x58, 0xff, 0x22, 0xe0, 0x09, 0x01, 
@@ -2178,85 +2190,85 @@ const u8 typhoon_firmware_image[] = {
 0x98, 0x43, 0x99, 0x04, 0xa8, 0x61, 0x08, 0x61, 0xda, 0xe7, 0x10, 0x20, 
 0x00, 0xf0, 0x20, 0xf9, 0x10, 0x20, 0xb8, 0x60, 0xff, 0xf7, 0x82, 0xff, 
 0xd2, 0xe7, 0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0, 0x17, 0xf9, 0x30, 0x68, 
-0x00, 0xf0, 0x40, 0xf8, 0x00, 0x28, 0xd8, 0xd0, 0x02, 0x23, 0xb8, 0x6b, 
-0x18, 0x43, 0xb8, 0x63, 0xc4, 0xe7, 0x00, 0x00, 0xa8, 0x04, 0x00, 0x80, 
-0x25, 0x55, 0xff, 0xff, 0x00, 0x00, 0x00, 0xb0, 
-0xe8, 0x0d, 0x00, 0x80, 0x64, 0x01, 0x00, 0x80, 0xa0, 0x54, 0xff, 0xff, 
-0x85, 0x74, 0x21, 0x40, 0x90, 0xb5, 0x01, 0x20, 0x40, 0x03, 0x10, 0x49, 
-0x00, 0x27, 0x08, 0x60, 0x0f, 0x4c, 0xe0, 0x1d, 0xff, 0x30, 0x3a, 0x30, 
-0x47, 0x70, 0xe0, 0x69, 0x80, 0x00, 0x00, 0x19, 0x00, 0x69, 0x00, 0xf0, 
-0xd7, 0xf8, 0xe0, 0x69, 0x00, 0x28, 0x01, 0xd0, 0xe7, 0x61, 0x01, 0xe0, 
-0x01, 0x20, 0xe0, 0x61, 0x07, 0x48, 0x02, 0x23, 0x81, 0x6b, 0x19, 0x43, 
-0x81, 0x63, 0x27, 0x73, 0xff, 0xf7, 0x00, 0xff, 0x90, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa8, 0x04, 0x00, 0x80, 
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x78, 0x88, 
-0x6d, 0x28, 0x03, 0xdb, 0x38, 0x1c, 0x00, 0xf0, 0xf7, 0xf8, 0x17, 0xe0, 
-0x80, 0x00, 0x0d, 0x49, 0x09, 0x58, 0x38, 0x1c, 0xff, 0xf7, 0xbd, 0xfe, 
-0x00, 0x28, 0x0f, 0xd1, 0x39, 0x78, 0xc9, 0x09, 0x0c, 0xd3, 0x69, 0x46, 
-0x38, 0x1c, 0x00, 0xf0, 0xcf, 0xf8, 0x68, 0x46, 0x00, 0x21, 0x00, 0xf0, 
-0x0b, 0xf8, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 
-0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x01, 0x00, 0x80, 
-0xf0, 0xb5, 0x82, 0xb0, 0x02, 0x1c, 0x41, 0x4b, 0xdd, 0x1d, 0xff, 0x35, 
-0x3a, 0x35, 0x2f, 0x78, 0x00, 0x2f, 0x01, 0xd0, 0x00, 0x27, 0x00, 0xe0, 
-0x01, 0x27, 0x2f, 0x70, 0x2f, 0x78, 0xfb, 0x00, 0xdb, 0x19, 0x5b, 0x01, 
-0x3a, 0x4f, 0xdc, 0x19, 0x40, 0x78, 0x00, 0x01, 0xc7, 0x1d, 0x09, 0x37, 
-0x00, 0x20, 0x83, 0x00, 0xd6, 0x58, 0xc0, 0x46, 0xe6, 0x50, 0x01, 0x30, 
-0x04, 0x28, 0xf8, 0xd3, 0x00, 0x29, 0x0f, 0xd0, 0x00, 0x22, 0xbb, 0x08, 
-0x01, 0x93, 0x83, 0x42, 0x0b, 0xd9, 0x13, 0x1c, 0x9b, 0x00, 0xcb, 0x58, 
-0x86, 0x00, 0xa3, 0x51, 0x01, 0x9b, 0x01, 0x30, 0x01, 0x32, 0x83, 0x42, 
-0xf5, 0xd8, 0x00, 0xe0, 0x10, 0x27, 0x2b, 0x48, 0x02, 0x6d, 0x80, 0x6e, 
-0x2a, 0x49, 0x82, 0x42, 0x03, 0xd8, 0x82, 0x1a, 0xcb, 0x6c, 0x9a, 0x1a, 
-0x00, 0xe0, 0x12, 0x1a, 0xba, 0x42, 0x05, 0xd8, 0x26, 0x48, 0x81, 0x6b, 
-0x01, 0x31, 0x81, 0x63, 0x01, 0x20, 0x37, 0xe0, 0xc3, 0x19, 0xca, 0x6c, 
-0x93, 0x42, 0x08, 0xd8, 0x22, 0x4a, 0x3a, 0x43, 0x00, 0x92, 0x0a, 0x1c, 
-0x49, 0x6c, 0x09, 0x18, 0x92, 0x6c, 0x23, 0x1c, 0x12, 0xe0, 0x16, 0x1a, 
-0x00, 0x96, 0x1b, 0x49, 0x49, 0x6c, 0x09, 0x18, 0x19, 0x48, 0x82, 0x6c, 
-0x03, 0x20, 0x23, 0x1c, 0xff, 0xf7, 0x50, 0xfe, 0xb8, 0x1b, 0x18, 0x4a, 
-0x02, 0x43, 0x00, 0x92, 0xa3, 0x19, 0x14, 0x48, 0x82, 0x6c, 0x41, 0x6c, 
+0x00, 0xf0, 0x40, 0xf8, 0x00, 0x28, 0xd8, 0xd0, 0x02, 0x23, 0xf8, 0x6b, 
+0x18, 0x43, 0xf8, 0x63, 0xc4, 0xe7, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 
+0x91, 0x55, 0xff, 0xff, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
+0xe4, 0x01, 0x00, 0x80, 0x0c, 0x55, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40, 
+0x90, 0xb5, 0x01, 0x20, 0x40, 0x03, 0x10, 0x49, 0x00, 0x27, 0x08, 0x60, 
+0x0f, 0x4c, 0xe0, 0x1d, 0xff, 0x30, 0x3a, 0x30, 0x47, 0x70, 0xe0, 0x69, 
+0x80, 0x00, 0x00, 0x19, 0x00, 0x69, 0x00, 0xf0, 0xd7, 0xf8, 0xe0, 0x69, 
+0x00, 0x28, 0x01, 0xd0, 0xe7, 0x61, 0x01, 0xe0, 0x01, 0x20, 0xe0, 0x61, 
+0x07, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x27, 0x73, 
+0xff, 0xf7, 0x00, 0xff, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xb0, 0x28, 0x05, 0x00, 0x80, 0xe8, 0x0e, 0x00, 0x80, 
+0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x78, 0x88, 0x6d, 0x28, 0x03, 0xdb, 
+0x38, 0x1c, 0x00, 0xf0, 0xf7, 0xf8, 0x17, 0xe0, 0x80, 0x00, 0x0d, 0x49, 
+0x09, 0x58, 0x38, 0x1c, 0xff, 0xf7, 0xbd, 0xfe, 0x00, 0x28, 0x0f, 0xd1, 
+0x39, 0x78, 0xc9, 0x09, 0x0c, 0xd3, 0x69, 0x46, 0x38, 0x1c, 0x00, 0xf0, 
+0xcf, 0xf8, 0x68, 0x46, 0x00, 0x21, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0x28, 
+0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xe8, 0x01, 0x00, 0x80, 0xf0, 0xb5, 0x82, 0xb0, 
+0x02, 0x1c, 0x41, 0x4b, 0xdd, 0x1d, 0xff, 0x35, 0x3a, 0x35, 0x2f, 0x78, 
+0x00, 0x2f, 0x01, 0xd0, 0x00, 0x27, 0x00, 0xe0, 0x01, 0x27, 0x2f, 0x70, 
+0x2f, 0x78, 0xfb, 0x00, 0xdb, 0x19, 0x5b, 0x01, 0x3a, 0x4f, 0xdc, 0x19, 
+0x40, 0x78, 0x00, 0x01, 0xc7, 0x1d, 0x09, 0x37, 0x00, 0x20, 0x83, 0x00, 
+0xd6, 0x58, 0xc0, 0x46, 0xe6, 0x50, 0x01, 0x30, 0x04, 0x28, 0xf8, 0xd3, 
+0x00, 0x29, 0x0f, 0xd0, 0x00, 0x22, 0xbb, 0x08, 0x01, 0x93, 0x83, 0x42, 
+0x0b, 0xd9, 0x13, 0x1c, 0x9b, 0x00, 0xcb, 0x58, 0x86, 0x00, 0xa3, 0x51, 
+0x01, 0x9b, 0x01, 0x30, 0x01, 0x32, 0x83, 0x42, 0xf5, 0xd8, 0x00, 0xe0, 
+0x10, 0x27, 0x2b, 0x48, 0x02, 0x6d, 0x80, 0x6e, 0x2a, 0x49, 0x82, 0x42, 
+0x03, 0xd8, 0x82, 0x1a, 0xcb, 0x6c, 0x9a, 0x1a, 0x00, 0xe0, 0x12, 0x1a, 
+0xba, 0x42, 0x05, 0xd8, 0x26, 0x48, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 
+0x01, 0x20, 0x37, 0xe0, 0xc3, 0x19, 0xca, 0x6c, 0x93, 0x42, 0x08, 0xd8, 
+0x22, 0x4a, 0x3a, 0x43, 0x00, 0x92, 0x0a, 0x1c, 0x49, 0x6c, 0x09, 0x18, 
+0x92, 0x6c, 0x23, 0x1c, 0x12, 0xe0, 0x16, 0x1a, 0x00, 0x96, 0x1b, 0x49, 
+0x49, 0x6c, 0x09, 0x18, 0x19, 0x48, 0x82, 0x6c, 0x03, 0x20, 0x23, 0x1c, 
+0xff, 0xf7, 0x50, 0xfe, 0xb8, 0x1b, 0x18, 0x4a, 0x02, 0x43, 0x00, 0x92, 
+0xa3, 0x19, 0x14, 0x48, 0x82, 0x6c, 0x41, 0x6c, 
 0x03, 0x20, 0xff, 0xf7, 0x45, 0xfe, 0x01, 0x20, 0x0d, 0x49, 0xc0, 0x46, 
 0x68, 0x70, 0x8a, 0x69, 0x92, 0x00, 0x52, 0x18, 0x17, 0x61, 0x8a, 0x69, 
 0x00, 0x2a, 0x02, 0xd0, 0x00, 0x27, 0x8f, 0x61, 0x00, 0xe0, 0x88, 0x61, 
-0x0c, 0x48, 0x02, 0x23, 0x81, 0x6b, 0x19, 0x43, 0x81, 0x63, 0x00, 0x20, 
-0x01, 0x27, 0x0a, 0x49, 0xc0, 0x46, 0x4f, 0x72, 0x02, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xa8, 0x04, 0x00, 0x80, 0xfc, 0xba, 0x20, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0xf8, 0x28, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x00, 0x00, 0x19, 0x02, 0x68, 0x0e, 0x00, 0x80, 0x98, 0x19, 0x00, 0x80, 
+0x0c, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x00, 0x20, 
+0x01, 0x27, 0x0a, 0x49, 0xc0, 0x46, 0x4f, 0x73, 0x02, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x28, 0x05, 0x00, 0x80, 0xfc, 0xba, 0x20, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
+0x00, 0x00, 0x19, 0x02, 0xe8, 0x0e, 0x00, 0x80, 0x18, 0x1a, 0x00, 0x80, 
 0x07, 0x49, 0x8a, 0x6e, 0x10, 0x18, 0x07, 0x4a, 0xd2, 0x6c, 0x13, 0x04, 
 0x1b, 0x0c, 0x83, 0x42, 0x00, 0xd8, 0x80, 0x1a, 0x88, 0x66, 0x88, 0x6e, 
-0x03, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x70, 0x47, 
-0xe8, 0x0d, 0x00, 0x80, 0xf8, 0x28, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 
-0x06, 0x49, 0x4a, 0x6e, 0x10, 0x18, 0x06, 0x4a, 0x12, 0x6c, 0x82, 0x42, 
-0x00, 0xd8, 0x80, 0x1a, 0x48, 0x66, 0x48, 0x6e, 0x03, 0x49, 0xc0, 0x46, 
-0x08, 0x61, 0x70, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0xf8, 0x28, 0x00, 0x80, 
-0x3c, 0xef, 0x20, 0x40, 0x05, 0x22, 0x0a, 0x60, 0x82, 0x88, 0xc0, 0x46, 
-0x8a, 0x80, 0x00, 0x22, 0x4a, 0x70, 0x40, 0x88, 0xc0, 0x46, 0x48, 0x80, 
-0xca, 0x80, 0x8a, 0x60, 0xca, 0x60, 0x70, 0x47, 0x05, 0x22, 0x02, 0x60, 
-0x00, 0x22, 0x82, 0x80, 0x42, 0x70, 0x41, 0x80, 0xc2, 0x80, 0x82, 0x60, 
-0xc2, 0x60, 0x70, 0x47, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x0e, 0x48, 
-0x41, 0x6b, 0x01, 0x31, 0x41, 0x63, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
-0xdd, 0xff, 0x38, 0x68, 0xc0, 0x46, 0x00, 0x90, 0x45, 0x20, 0x00, 0xab, 
-0x18, 0x70, 0x01, 0x27, 0xdf, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0x11, 0xff, 0x00, 0x28, 0x01, 0xd1, 0x38, 0x1c, 0x00, 0xe0, 0x00, 0x20, 
-0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xa0, 0x82, 0x20, 0x40, 
-0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x09, 0x4a, 0xc0, 0x46, 0x11, 0x81, 
-0x69, 0x46, 0xff, 0xf7, 0xbd, 0xff, 0x01, 0x20, 0x40, 0x02, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xf5, 0xfe, 0x01, 0x20, 
-0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
-0x00, 0xb5, 0xff, 0xf7, 0xc3, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 
-0x03, 0x49, 0xc0, 0x46, 0x08, 0x70, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 
-0x00, 0x20, 0x70, 0x47, 0xa8, 0x0e, 0x00, 0x80, 0x00, 0x20, 0x04, 0x49, 
-0xc0, 0x46, 0x08, 0x70, 0xff, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x01, 0x31, 
-0x91, 0x60, 0x70, 0x47, 0xa8, 0x0e, 0x00, 0x80, 0x02, 0x20, 0xa1, 0x21, 
-0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x40, 0x02, 
-0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0xc0, 0x88, 
-0xc0, 0x06, 0xc0, 0x0e, 0xa1, 0x21, 0x49, 0x03, 0x48, 0x61, 0x02, 0x49, 
-0xc0, 0x46, 0x88, 0x63, 0x00, 0x20, 0x70, 0x47, 0x68, 0x1a, 0x00, 0x80, 
-0x80, 0xb5, 0x84, 0xb0, 0x08, 0x49, 0x0f, 0x6b, 0x69, 0x46, 0xff, 0xf7, 
-0x71, 0xff, 0xf8, 0x06, 0xc0, 0x0e, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xff, 0xf7, 0xa9, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x80, 0x00, 0x14, 0x40, 0x80, 0xb5, 0x85, 0xb0, 
-0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0x5b, 0xff, 0xf8, 0x88, 
-0x04, 0xa9, 0x04, 0xf0, 0xef, 0xfd, 0x01, 0xab, 0x58, 0x80, 0x01, 0xa8, 
+0x03, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x7c, 0x29, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x06, 0x49, 0x4a, 0x6e, 
+0x10, 0x18, 0x06, 0x4a, 0x12, 0x6c, 0x82, 0x42, 0x00, 0xd8, 0x80, 0x1a, 
+0x48, 0x66, 0x48, 0x6e, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x61, 0x70, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 
+0x05, 0x22, 0x0a, 0x60, 0x82, 0x88, 0xc0, 0x46, 0x8a, 0x80, 0x00, 0x22, 
+0x4a, 0x70, 0x40, 0x88, 0xc0, 0x46, 0x48, 0x80, 0xca, 0x80, 0x8a, 0x60, 
+0xca, 0x60, 0x70, 0x47, 0x05, 0x22, 0x02, 0x60, 0x00, 0x22, 0x82, 0x80, 
+0x42, 0x70, 0x41, 0x80, 0xc2, 0x80, 0x82, 0x60, 0xc2, 0x60, 0x70, 0x47, 
+0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x0e, 0x48, 0x41, 0x6b, 0x01, 0x31, 
+0x41, 0x63, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0xdd, 0xff, 0x38, 0x68, 
+0xc0, 0x46, 0x00, 0x90, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x01, 0x27, 
+0xdf, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x11, 0xff, 0x00, 0x28, 
+0x01, 0xd1, 0x38, 0x1c, 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x84, 0xb0, 
+0xc1, 0x88, 0x09, 0x4a, 0xc0, 0x46, 0x91, 0x81, 0x69, 0x46, 0xff, 0xf7, 
+0xbd, 0xff, 0x01, 0x20, 0x40, 0x02, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xff, 0xf7, 0xf5, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7, 
+0xc3, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0x03, 0x49, 0xc0, 0x46, 
+0x08, 0x71, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 
+0x28, 0x0f, 0x00, 0x80, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x08, 0x71, 
+0xff, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x01, 0x31, 0x91, 0x60, 0x70, 0x47, 
+0x28, 0x0f, 0x00, 0x80, 0x02, 0x20, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 
+0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 
+0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0xc0, 0x88, 0xc0, 0x06, 0xc0, 0x0e, 
+0xa1, 0x21, 0x49, 0x03, 0x48, 0x61, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x63, 
+0x00, 0x20, 0x70, 0x47, 0xe8, 0x1a, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 
+0x08, 0x49, 0x0f, 0x6b, 0x69, 0x46, 0xff, 0xf7, 0x71, 0xff, 0xf8, 0x06, 
+0xc0, 0x0e, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
+0xa9, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0x00, 0x14, 0x40, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
+0x38, 0x1c, 0xff, 0xf7, 0x5b, 0xff, 0xf8, 0x88, 
+0x04, 0xa9, 0x05, 0xf0, 0xf7, 0xf9, 0x01, 0xab, 0x58, 0x80, 0x01, 0xa8, 
 0x40, 0x88, 0x00, 0x28, 0x0f, 0xd0, 0x01, 0xa8, 0x40, 0x88, 0x80, 0x08, 
 0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x04, 0x3b, 0x58, 0x70, 0x04, 0x98, 
 0x01, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x40, 0x68, 0xc0, 0x46, 0x03, 0x90, 
@@ -2266,52 +2278,54 @@ const u8 typhoon_firmware_image[] = {
 0x90, 0xb5, 0x84, 0xb0, 0x14, 0x4f, 0x39, 0x7b, 0x00, 0x29, 0x20, 0xd1, 
 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x00, 0x29, 0x1a, 0xd1, 
 0x10, 0x49, 0x05, 0x22, 0x00, 0x92, 0x08, 0x22, 0x00, 0xab, 0x5a, 0x80, 
-0x98, 0x80, 0x06, 0x20, 0x00, 0xab, 0x58, 0x70, 
-0x00, 0x24, 0xdc, 0x80, 0x08, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x48, 0x68, 
-0xc0, 0x46, 0x03, 0x90, 0x01, 0x20, 0x38, 0x73, 0x68, 0x46, 0x08, 0x31, 
-0xff, 0xf7, 0x4c, 0xfe, 0x00, 0x28, 0x00, 0xd0, 0x3c, 0x73, 0x04, 0xb0, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa8, 0x04, 0x00, 0x80, 
-0x10, 0x2a, 0x00, 0x80, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
-0x38, 0x1c, 0xff, 0xf7, 0xf9, 0xfe, 0xba, 0x68, 0x0d, 0x4c, 0x0e, 0x48, 
-0x00, 0x2a, 0x05, 0xd1, 0x0d, 0x49, 0xff, 0xf7, 0xd6, 0xfc, 0x00, 0x28, 
-0x0c, 0xda, 0x05, 0xe0, 0xb9, 0x88, 0x0b, 0x4b, 0xff, 0xf7, 0xd1, 0xfc, 
-0x00, 0x28, 0x05, 0xda, 0x01, 0xab, 0x5c, 0x80, 0x68, 0x46, 0x00, 0x21, 
-0xff, 0xf7, 0x22, 0xfe, 0x00, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x15, 0x79, 0x21, 0x40, 
-0x59, 0xcd, 0x21, 0x40, 0xf1, 0xcc, 0x21, 0x40, 0x00, 0xb5, 0xc0, 0x88, 
-0x04, 0xf0, 0x54, 0xfd, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xff, 0xf7, 0xe2, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 
-0xdd, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 
-0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 
-0x04, 0x1c, 0x08, 0x1c, 0x69, 0x46, 0xff, 0xf7, 0xb5, 0xfe, 0x1b, 0x48, 
-0xff, 0xf7, 0x96, 0xfc, 0x07, 0x1c, 0x00, 0x21, 0x20, 0x1c, 0x03, 0xf0, 
-0x4f, 0xff, 0x00, 0x28, 0x1c, 0xd0, 0x20, 0x1c, 0x04, 0xa9, 0x03, 0xf0, 
-0x2d, 0xfe, 0x04, 0x98, 0x04, 0x28, 0x05, 0xd9, 0x04, 0x98, 0x80, 0x08, 
+0x98, 0x80, 0x06, 0x20, 0x00, 0xab, 0x58, 0x70, 0x00, 0x24, 0xdc, 0x80, 
+0x08, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x48, 0x68, 0xc0, 0x46, 0x03, 0x90, 
+0x01, 0x20, 0x38, 0x73, 0x68, 0x46, 0x08, 0x31, 0xff, 0xf7, 0x4c, 0xfe, 
+0x00, 0x28, 0x00, 0xd0, 0x3c, 0x73, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80, 
+0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
+0xf9, 0xfe, 0xba, 0x68, 0x0d, 0x4c, 0x0e, 0x48, 0x00, 0x2a, 0x05, 0xd1, 
+0x0d, 0x49, 0xff, 0xf7, 0xd6, 0xfc, 0x00, 0x28, 0x0c, 0xda, 0x05, 0xe0, 
+0xb9, 0x88, 0x0b, 0x4b, 0xff, 0xf7, 0xd1, 0xfc, 0x00, 0x28, 0x05, 0xda, 
+0x01, 0xab, 0x5c, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x22, 0xfe, 
+0x00, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xff, 0xff, 0x00, 0x00, 0x15, 0x79, 0x21, 0x40, 0x8d, 0xd5, 0x21, 0x40, 
+0x25, 0xd5, 0x21, 0x40, 0x00, 0xb5, 0xc0, 0x88, 0x05, 0xf0, 0x5c, 0xf9, 
+0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xe2, 0xfe, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xdd, 0xfe, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 0x02, 0xf8, 
+0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 0x04, 0x1c, 0x08, 0x1c, 
+0x69, 0x46, 0xff, 0xf7, 0xb5, 0xfe, 0x1c, 0x48, 0xff, 0xf7, 0x96, 0xfc, 
+0x07, 0x1c, 0x1b, 0x4a, 0x00, 0x21, 0x20, 0x1c, 0xff, 0xf7, 0x92, 0xfc, 
+0x00, 0x28, 0x1d, 0xd0, 0x04, 0xa9, 0x18, 0x4a, 0x20, 0x1c, 0xff, 0xf7, 
+0x8b, 0xfc, 0x04, 0x98, 0x04, 0x28, 0x05, 0xd9, 0x04, 0x98, 0x80, 0x08, 
 0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x00, 0xe0, 0x00, 0x20, 0x00, 0xab, 
 0x58, 0x70, 0x06, 0xa8, 0x00, 0x78, 0xc0, 0x46, 0xd8, 0x80, 0x04, 0x98, 
 0xc0, 0x46, 0x02, 0x90, 0x07, 0x98, 0xc0, 0x46, 0x03, 0x90, 0x04, 0x33, 
-0x08, 0xad, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x07, 0x49, 
-0x38, 0x1c, 0xff, 0xf7, 0x6c, 0xfc, 0x68, 0x46, 0x29, 0x1c, 0xff, 0xf7, 
-0xc3, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x01, 0x1c, 
-0x02, 0x20, 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0x01, 0x1c, 0x01, 0x20, 0xff, 0xf7, 0xb2, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0x01, 0x1c, 0x01, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 
-0x18, 0x47, 0xf3, 0xb5, 0xc6, 0xb0, 0x0f, 0x1c, 0x69, 0x46, 0x38, 0x1c, 
-0xff, 0xf7, 0x5e, 0xfe, 0x1c, 0x48, 0xff, 0xf7, 0x3f, 0xfc, 0xba, 0x68, 
-0x04, 0x1c, 0xfc, 0x2a, 0x1f, 0xd8, 0xfd, 0x88, 0xf8, 0x68, 0xc0, 0x46, 
-0x04, 0x90, 0xf9, 0x1d, 0x09, 0x31, 0x05, 0xab, 0x00, 0x20, 0x7e, 0x78, 
-0x00, 0x2e, 0x0d, 0xdd, 0x40, 0xc9, 0x40, 0xc3, 0x40, 0xc9, 0x40, 0xc3, 
-0x40, 0xc9, 0x40, 0xc3, 0x40, 0xc9, 0x40, 0xc3, 0x01, 0x30, 0x00, 0x04, 
-0x00, 0x0c, 0x7e, 0x78, 0x86, 0x42, 0xf1, 0xdc, 0x46, 0x98, 0x04, 0xa9, 
-0x2b, 0x1c, 0xff, 0xf7, 0x2d, 0xfc, 0x00, 0x28, 0x05, 0xd0, 0x00, 0xa8, 
-0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x07, 0x49, 
-0x20, 0x1c, 0xff, 0xf7, 0x12, 0xfc, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0x69, 0xfd, 0x01, 0x20, 0x48, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 
-0x35, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
+0x08, 0xad, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49, 
+0x38, 0x1c, 0xff, 0xf7, 0x6a, 0xfc, 0x68, 0x46, 0x29, 0x1c, 0xff, 0xf7, 
+0xc1, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x24, 0x02, 0xff, 0xff, 0xcd, 0xc0, 0x21, 0x40, 0x29, 0xbf, 0x21, 0x40, 
+0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 
+0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x01, 0x20, 
+0xff, 0xf7, 0xac, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 
+0x01, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 
+0xc6, 0xb0, 0x0f, 0x1c, 0x69, 0x46, 0x38, 0x1c, 
+0xff, 0xf7, 0x58, 0xfe, 0x20, 0x48, 0xff, 0xf7, 0x39, 0xfc, 0x04, 0x1c, 
+0x78, 0x78, 0x00, 0x01, 0xba, 0x68, 0x04, 0x30, 0xfc, 0x2a, 0x23, 0xd8, 
+0xff, 0x23, 0x09, 0x33, 0x98, 0x42, 0x1f, 0xd8, 0xfd, 0x88, 0xf8, 0x68, 
+0xc0, 0x46, 0x04, 0x90, 0x05, 0xa9, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 
+0x7e, 0x78, 0x00, 0x2e, 0x0d, 0xdd, 0x40, 0xcb, 0x40, 0xc1, 0x40, 0xcb, 
+0x40, 0xc1, 0x40, 0xcb, 0x40, 0xc1, 0x40, 0xcb, 0x40, 0xc1, 0x01, 0x30, 
+0x00, 0x04, 0x00, 0x0c, 0x7e, 0x78, 0x86, 0x42, 0xf1, 0xdc, 0x46, 0x98, 
+0x04, 0xa9, 0x2b, 0x1c, 0xff, 0xf7, 0x20, 0xfc, 0x00, 0x28, 0x05, 0xd0, 
+0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 
+0x07, 0x49, 0x20, 0x1c, 0xff, 0xf7, 0x05, 0xfc, 0x68, 0x46, 0x00, 0x21, 
+0xff, 0xf7, 0x5c, 0xfd, 0x01, 0x20, 0x48, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 
+0x00, 0xb5, 0xff, 0xf7, 0x27, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
 0xc6, 0xb0, 0x07, 0x1c, 0xfc, 0x88, 0x25, 0x4d, 0x68, 0x68, 0x01, 0x30, 
-0x69, 0x46, 0x68, 0x60, 0x38, 0x1c, 0xff, 0xf7, 0x0f, 0xfe, 0x10, 0x2c, 
+0x69, 0x46, 0x68, 0x60, 0x38, 0x1c, 0xff, 0xf7, 0x01, 0xfe, 0x10, 0x2c, 
 0x08, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 
 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x17, 0xe0, 0x78, 0x78, 0x82, 0x00, 
 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 0xb9, 0x68, 0x00, 0x2a, 0x15, 0xd9, 
@@ -2322,1121 +2336,1275 @@ const u8 typhoon_firmware_image[] = {
 0x02, 0x94, 0x69, 0x68, 0xc0, 0x46, 0x03, 0x91, 0xa2, 0x00, 0x00, 0x20, 
 0x10, 0x33, 0x00, 0x2a, 0x05, 0xd9, 0x0f, 0x1c, 0x80, 0xc3, 0x01, 0x30, 
 0x01, 0x31, 0x90, 0x42, 0xf9, 0xd3, 0x68, 0x46, 0x04, 0xa9, 0xff, 0xf7, 
-0x11, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x1c, 0x03, 0x00, 0x80, 0x90, 0xb4, 0x22, 0x48, 0x00, 0x68, 0x01, 0x21, 
+0x03, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x9c, 0x03, 0x00, 0x80, 0x90, 0xb4, 0x23, 0x48, 0x00, 0x68, 0x01, 0x21, 
 0x42, 0x09, 0x00, 0xd3, 0x00, 0x21, 0x00, 0x27, 0x3a, 0x1c, 0x43, 0x0b, 
-0x00, 0xd2, 0x02, 0x22, 0x11, 0x43, 0x1d, 0x4a, 0x20, 0x24, 0xd3, 0x68, 
-0x01, 0x2b, 0x2c, 0xd1, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 
-0x20, 0x1c, 0x1b, 0x23, 0xdb, 0x01, 0xd1, 0x18, 0x09, 0x8b, 0x09, 0x0b, 
-0x00, 0xd2, 0x04, 0x27, 0x38, 0x43, 0xd1, 0x6f, 0x09, 0x0a, 0x06, 0xd2, 
-0xd1, 0x1d, 0x79, 0x31, 0x09, 0x68, 0x09, 0x0a, 0x01, 0xd3, 0x08, 0x23, 
-0x18, 0x43, 0xe3, 0x23, 0x1b, 0x01, 0xd1, 0x18, 0x89, 0x78, 0x03, 0x29, 
-0x02, 0xd1, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43, 0x0b, 0x49, 0x09, 0x6a, 
-0x10, 0x22, 0x4b, 0x0a, 0x00, 0xd2, 0x00, 0x22, 0x10, 0x43, 0x89, 0x07, 
-0x89, 0x0f, 0x89, 0x01, 0x08, 0x43, 0x90, 0xbc, 0x70, 0x47, 0x40, 0x0c, 
-0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 0xec, 0xe7, 0x00, 0x00, 
-0x00, 0x00, 0x10, 0x40, 0xe8, 0x0d, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 
-0xf0, 0xb5, 0x33, 0x4d, 0x28, 0x1c, 0x05, 0xf0, 0x6b, 0xf8, 0x32, 0x49, 
-0xe3, 0x23, 0x1b, 0x01, 0xcf, 0x18, 0xba, 0x78, 0x30, 0x4e, 0x00, 0x20, 
-0xcc, 0x1d, 0x79, 0x34, 0x05, 0x2a, 0x53, 0xd2, 0x01, 0xa3, 0x9b, 0x5c, 
-0x5b, 0x00, 0x9f, 0x44, 0x02, 0x0e, 0x23, 0x3c, 0x3e, 0x00, 0x01, 0x21, 
-0xb9, 0x70, 0xb0, 0x60, 0xff, 0xf7, 0x98, 0xff, 0x04, 0x23, 0x98, 0x43, 
-0x00, 0xf0, 0x62, 0xf8, 0x14, 0x22, 0x28, 0x1c, 0x0e, 0xe0, 0xff, 0xf7, 
-0x8f, 0xff, 0xc0, 0x08, 0x06, 0xd3, 0xb1, 0x68, 0x48, 0x1c, 0xb0, 0x60, 
-0x0a, 0x29, 0x03, 0xd9, 0x04, 0x20, 0x00, 0xe0, 0x02, 0x20, 0xb8, 0x70, 
-0x02, 0x22, 0x28, 0x1c, 0x00, 0x21, 0x05, 0xf0, 0x07, 0xf8, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x80, 0x23, 0xc8, 0x6f, 0x18, 0x43, 0xc8, 0x67, 
-0x18, 0x4e, 0xc0, 0x46, 0x30, 0x60, 0x03, 0x20, 0xb8, 0x70, 0x28, 0x1c, 
-0x16, 0x4a, 0x00, 0x21, 0x04, 0xf0, 0xf6, 0xff, 0x11, 0x48, 0x04, 0x23, 
-0xc1, 0x6f, 0x99, 0x43, 0xc1, 0x67, 0x31, 0x60, 0x20, 0x68, 0x18, 0x43, 
-0x20, 0x60, 0x70, 0x60, 0xe3, 0xe7, 0x05, 0x21, 0xb9, 0x70, 0x51, 0x21, 
-0x89, 0x03, 0x08, 0x62, 0x04, 0x23, 0x20, 0x68, 0x98, 0x43, 0x20, 0x60, 
-0x09, 0x4e, 0xc0, 0x46, 0x70, 0x60, 0xff, 0xf7, 0x55, 0xff, 0x04, 0x23, 
-0x18, 0x43, 0x00, 0xf0, 0x1f, 0xf8, 0xd0, 0xe7, 
-0x06, 0x20, 0xb8, 0x70, 0xcd, 0xe7, 0x00, 0x00, 0x79, 0x7c, 0x21, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0x1c, 0x03, 0x00, 0x80, 0x00, 0x01, 0x11, 0x00, 
-0x88, 0x13, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 
-0x88, 0x70, 0x04, 0x48, 0x01, 0x22, 0x00, 0x21, 0x04, 0xf0, 0xc0, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x18, 0x1c, 0x00, 0x80, 0x79, 0x7c, 0x21, 0x40, 
-0x90, 0xb5, 0x07, 0x1c, 0x30, 0x48, 0x00, 0x68, 0x01, 0x1c, 0x7a, 0x08, 
-0x02, 0xd3, 0x10, 0x23, 0x98, 0x43, 0x01, 0xe0, 0x10, 0x23, 0x18, 0x43, 
-0xba, 0x08, 0x03, 0xd3, 0x01, 0x23, 0x1b, 0x03, 0x98, 0x43, 0x02, 0xe0, 
-0x01, 0x23, 0x1b, 0x03, 0x18, 0x43, 0x88, 0x42, 0x02, 0xd0, 0x01, 0x21, 
-0x09, 0x05, 0x08, 0x60, 0x25, 0x4c, 0xe0, 0x68, 0x01, 0x28, 0x1e, 0xd1, 
-0x1b, 0x23, 0xdb, 0x01, 0xe0, 0x18, 0x00, 0x8b, 0xf9, 0x08, 0x04, 0xd3, 
-0x01, 0x23, 0xdb, 0x02, 0x01, 0x1c, 0x99, 0x43, 0x01, 0xe0, 0x01, 0x21, 
-0xc9, 0x02, 0x81, 0x42, 0x02, 0xd0, 0x00, 0x20, 0x02, 0xf0, 0x20, 0xfe, 
-0x08, 0x21, 0x39, 0x40, 0x1a, 0x48, 0x03, 0xd0, 0x80, 0x23, 0xe1, 0x6f, 
-0x99, 0x43, 0x02, 0xe0, 0x80, 0x23, 0xe1, 0x6f, 0x19, 0x43, 0xe1, 0x67, 
-0x01, 0x60, 0x16, 0x48, 0x01, 0x6a, 0x78, 0x09, 0x03, 0xd3, 0xff, 0x20, 
+0x00, 0xd2, 0x02, 0x22, 0x11, 0x43, 0x1e, 0x4a, 0x20, 0x24, 0xd3, 0x68, 
+0x01, 0x2b, 0x2e, 0xd1, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 
+0x20, 0x1c, 0x1b, 0x23, 0xdb, 0x01, 0xd1, 0x18, 0x89, 0x8b, 0x09, 0x0b, 
+0x00, 0xd2, 0x04, 0x27, 0x38, 0x43, 0xd1, 0x6f, 0x09, 0x68, 0x09, 0x0a, 
+0x07, 0xd2, 0xd1, 0x1d, 0x79, 0x31, 0x09, 0x68, 0x09, 0x68, 0x09, 0x0a, 
+0x01, 0xd3, 0x08, 0x23, 0x18, 0x43, 0xe3, 0x23, 0x1b, 0x01, 0xd1, 0x18, 
+0x89, 0x79, 0x03, 0x29, 0x02, 0xd1, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43, 
+0x0b, 0x49, 0x09, 0x6a, 0x10, 0x22, 0x4b, 0x0a, 0x00, 0xd2, 0x00, 0x22, 
+0x10, 0x43, 0x89, 0x07, 0x89, 0x0f, 0x89, 0x01, 0x08, 0x43, 0x90, 0xbc, 
+0x70, 0x47, 0x40, 0x0c, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 
+0xec, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0xc0, 0x00, 0x18, 0x40, 0xf0, 0xb5, 0x3a, 0x4c, 0x20, 0x1c, 0x05, 0xf0, 
+0x75, 0xfc, 0x39, 0x48, 0xe3, 0x23, 0x1b, 0x01, 0xc7, 0x18, 0xb9, 0x79, 
+0x37, 0x4e, 0xc5, 0x1d, 0x79, 0x35, 0x06, 0x29, 0x62, 0xd2, 0x02, 0xa3, 
+0x5b, 0x5c, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c, 
+0x03, 0x0e, 0x1e, 0x37, 0x4e, 0x55, 0x01, 0x20, 0xb8, 0x71, 0x00, 0x20, 
+0xb0, 0x60, 0xff, 0xf7, 0x95, 0xff, 0x05, 0x23, 0x98, 0x43, 0x00, 0xf0, 
+0x6f, 0xf8, 0x0c, 0xe0, 0xff, 0xf7, 0x8e, 0xff, 0xc0, 0x08, 0x06, 0xd3, 
+0xb0, 0x68, 0x41, 0x1c, 0xb1, 0x60, 0x0a, 0x28, 0x03, 0xd9, 0x04, 0x20, 
+0x00, 0xe0, 0x02, 0x20, 0xb8, 0x71, 0x64, 0x22, 0x20, 0x1c, 0x2b, 0xe0, 
+0x06, 0x1c, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0x03, 0x20, 0xb8, 0x71, 0x20, 0x1c, 0x20, 0x4a, 0x00, 0x21, 0x05, 0xf0, 
+0x07, 0xfc, 0xf0, 0x6f, 0x04, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 
+0x28, 0x68, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x05, 0x21, 0xb9, 0x71, 0x29, 0x68, 0x04, 0x23, 0x0a, 0x68, 
+0x9a, 0x43, 0x0a, 0x60, 0xc0, 0x6f, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0xff, 0xf7, 0x5a, 0xff, 0x08, 0x23, 0x18, 0x43, 0x00, 0xf0, 0x34, 0xf8, 
+0x20, 0x1c, 0x10, 0x4a, 0x00, 0x21, 0x05, 0xf0, 0xe5, 0xfb, 0xe5, 0xe7, 
+0xff, 0xf7, 0x4e, 0xff, 0x04, 0x23, 0x18, 0x43, 0x00, 0xf0, 0x28, 0xf8, 
+0xde, 0xe7, 0x00, 0x20, 0x29, 0x68, 0x60, 0x23, 0x0a, 0x68, 0x9a, 0x43, 
+0x0a, 0x60, 0xff, 0xf7, 0xe1, 0xfa, 0xd5, 0xe7, 0x06, 0x20, 0xb8, 0x71, 
+0xd2, 0xe7, 0x00, 0x00, 0x99, 0x7c, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0x9c, 0x03, 0x00, 0x80, 0x30, 0x75, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 
+0x00, 0xb5, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x88, 0x71, 0x04, 0x48, 
+0x01, 0x22, 0x00, 0x21, 0x05, 0xf0, 0xbc, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
+0x98, 0x1c, 0x00, 0x80, 0x99, 0x7c, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 
+0x31, 0x48, 0x00, 0x68, 0x79, 0x08, 0x03, 0xd3, 0x10, 0x23, 0x01, 0x1c, 
+0x99, 0x43, 0x01, 0xe0, 0x10, 0x21, 0x01, 0x43, 0x2d, 0x4c, 0xe2, 0x68, 
+0x01, 0x2a, 0x05, 0xd1, 0x22, 0x79, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x23, 
+0x9b, 0x02, 0x19, 0x43, 0x81, 0x42, 0x02, 0xd0, 0x01, 0x20, 0x00, 0x05, 
+0x01, 0x60, 0xe0, 0x68, 0x01, 0x28, 0x20, 0xd1, 0x1b, 0x23, 0xdb, 0x01, 
+0xe0, 0x18, 0x80, 0x8b, 0xf9, 0x08, 0x04, 0xd3, 0x01, 0x23, 0xdb, 0x02, 
+0x01, 0x1c, 0x99, 0x43, 0x01, 0xe0, 0x01, 0x21, 0xc9, 0x02, 0x81, 0x42, 
+0x02, 0xd0, 0x00, 0x20, 0x03, 0xf0, 0xca, 0xf9, 0x38, 0x09, 0x07, 0xd3, 
+0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xe0, 0x18, 
+0x00, 0x68, 0x00, 0xe0, 0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 
+0x01, 0x60, 0x15, 0x48, 0x01, 0x6a, 0x78, 0x09, 0x03, 0xd3, 0xff, 0x20, 
 0x01, 0x30, 0x08, 0x43, 0x03, 0xe0, 0xff, 0x23, 0x08, 0x1c, 0x01, 0x33, 
 0x98, 0x43, 0x80, 0x08, 0x80, 0x00, 0xba, 0x09, 0x92, 0x07, 0x92, 0x0f, 
-0x10, 0x43, 0x88, 0x42, 0x02, 0xd0, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x62, 
+0x10, 0x43, 0x88, 0x42, 0x02, 0xd0, 0x0c, 0x49, 0xc0, 0x46, 0x08, 0x62, 
 0xe1, 0x68, 0x01, 0x29, 0x08, 0xd1, 0x79, 0x0a, 0x06, 0xd3, 0xff, 0x23, 
-0x04, 0x33, 0x18, 0x40, 0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x90, 0xff, 
+0x04, 0x33, 0x18, 0x40, 0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x8e, 0xff, 
 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0x00, 0x01, 0x11, 0x00, 0xc0, 0x00, 0x18, 0x40, 
-0xc0, 0x00, 0x18, 0x00, 0x80, 0xb5, 0xff, 0xf7, 0xc1, 0xfe, 0x80, 0x09, 
-0x12, 0xd2, 0x0b, 0x48, 0x41, 0x78, 0x00, 0x29, 0x0e, 0xd1, 0x01, 0x21, 
-0x41, 0x70, 0x00, 0x27, 0x08, 0x48, 0x06, 0xe0, 0x02, 0x20, 0x03, 0xf0, 
-0x03, 0xf8, 0x07, 0x20, 0x02, 0xf0, 0xd2, 0xff, 0x38, 0x1c, 0xff, 0xf7, 
-0x5b, 0xfa, 0xf5, 0xe7, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x18, 0x1c, 0x00, 0x80, 0xf4, 0x01, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 
-0x69, 0x46, 0xff, 0xf7, 0x69, 0xfc, 0xff, 0xf7, 0x9d, 0xfe, 0x01, 0xab, 
-0x58, 0x80, 0x08, 0x48, 0x00, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x07, 0x48, 
-0x00, 0x6a, 0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0x99, 0xfb, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x40, 0x80, 0xb5, 0x84, 0xb0, 
-0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0x49, 0xfc, 0xf8, 0x88, 
-0xff, 0xf7, 0x4a, 0xff, 0xff, 0xf7, 0x7a, 0xfe, 0x01, 0xab, 0x58, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x7e, 0xfb, 0x01, 0x20, 0x04, 0xb0, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 0xc7, 0x88, 
-0x69, 0x46, 0xff, 0xf7, 0x33, 0xfc, 0x01, 0x24, 0x63, 0x02, 0x9f, 0x42, 
-0x0a, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 
-0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 0x16, 0xe0, 
-0x0e, 0x48, 0xff, 0xf7, 0x05, 0xfa, 0x05, 0x1c, 0x38, 0x1c, 0x04, 0xa9, 
-0x03, 0xf0, 0xa2, 0xfb, 0x0b, 0x49, 0x28, 0x1c, 
-0xff, 0xf7, 0xfd, 0xf9, 0x10, 0x20, 0x00, 0xab, 0x58, 0x70, 0x04, 0x98, 
-0xc0, 0x46, 0x02, 0x90, 0x05, 0x98, 0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 
-0x06, 0xa9, 0xff, 0xf7, 0x4b, 0xfb, 0x20, 0x1c, 0x46, 0xb0, 0xb0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 
+0x68, 0x0e, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 
+0x80, 0xb5, 0xff, 0xf7, 0xb1, 0xfe, 0x80, 0x09, 0x1b, 0xd2, 0x0f, 0x48, 
+0xe3, 0x23, 0x1b, 0x01, 0xc1, 0x18, 0x4a, 0x79, 0x00, 0x2a, 0x14, 0xd1, 
+0x01, 0x22, 0x4a, 0x71, 0x00, 0x27, 0x80, 0x30, 0x00, 0x68, 0x60, 0x23, 
+0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0x08, 0x48, 
+0x06, 0xe0, 0x02, 0x20, 0x03, 0xf0, 0x7e, 0xfb, 0x07, 0x20, 0x03, 0xf0, 
+0x4d, 0xfb, 0x38, 0x1c, 0xff, 0xf7, 0x34, 0xfa, 0xf5, 0xe7, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xf4, 0x01, 0xff, 0xff, 
+0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 0x43, 0xfc, 0xff, 0xf7, 
+0x85, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x08, 0x48, 0x00, 0x68, 0xc0, 0x46, 
+0x02, 0x90, 0x07, 0x48, 0x00, 0x6a, 0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 
+0x00, 0x21, 0xff, 0xf7, 0x73, 0xfb, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x40, 
+0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
+0x23, 0xfc, 0xf8, 0x88, 0xff, 0xf7, 0x42, 0xff, 0xff, 0xf7, 0x62, 0xfe, 
+0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x58, 0xfb, 
+0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 
+0xc6, 0xb0, 0xc7, 0x88, 0x69, 0x46, 0xff, 0xf7, 0x0d, 0xfc, 0x01, 0x24, 
+0x16, 0x4b, 0x9f, 0x42, 0x0a, 0xd9, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
+0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0x17, 0xe0, 0x10, 0x48, 0xff, 0xf7, 0xdf, 0xf9, 0x05, 0x1c, 
+0x0f, 0x4a, 0x38, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 0xdb, 0xf9, 0x0e, 0x49, 
+0x28, 0x1c, 0xff, 0xf7, 0xd6, 0xf9, 0x10, 0x20, 0x00, 0xab, 0x58, 0x70, 
+0x04, 0x98, 0xc0, 0x46, 0x02, 0x90, 0x05, 0x98, 0xc0, 0x46, 0x03, 0x90, 
+0x68, 0x46, 0x06, 0xa9, 0xff, 0xf7, 0x24, 0xfb, 0x20, 0x1c, 0x46, 0xb0, 
+0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 
+0x24, 0x02, 0xff, 0xff, 0x29, 0xbf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 
 0xf0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
-0xfb, 0xfb, 0xfc, 0x88, 0x78, 0x78, 0x01, 0x25, 0x10, 0x28, 0x02, 0xd1, 
+0xcf, 0xfb, 0xfc, 0x88, 0x78, 0x78, 0x01, 0x25, 0x10, 0x28, 0x02, 0xd1, 
 0x43, 0x01, 0x9c, 0x42, 0x09, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x04, 0x33, 
-0x2c, 0xe0, 0xb8, 0x68, 0xc0, 0x46, 0x04, 0x90, 0xf8, 0x68, 0xc0, 0x46, 
+0x27, 0xe0, 0xb8, 0x68, 0xc0, 0x46, 0x04, 0x90, 0xf8, 0x68, 0xc0, 0x46, 
 0x05, 0x90, 0x06, 0xaa, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x21, 0x78, 0x78, 
 0x00, 0x28, 0x0d, 0xdd, 0x00, 0x20, 0x40, 0xcb, 0x40, 0xc2, 0x01, 0x30, 
 0x00, 0x04, 0x00, 0x0c, 0x04, 0x28, 0xf8, 0xdb, 0x48, 0x1c, 0x01, 0x04, 
-0x09, 0x0c, 0x78, 0x78, 0x88, 0x42, 0xf1, 0xdc, 0x0d, 0x48, 0xff, 0xf7, 
-0xaf, 0xf9, 0x06, 0x1c, 0x20, 0x1c, 0x04, 0xa9, 0x03, 0xf0, 0x76, 0xfb, 
-0x0a, 0x49, 0x30, 0x1c, 0xff, 0xf7, 0xa7, 0xf9, 0x38, 0x68, 0xc0, 0x46, 
-0x00, 0x90, 0x00, 0x20, 0x00, 0xab, 0x58, 0x70, 0x68, 0x46, 0x00, 0x21, 
-0xff, 0xf7, 0xf8, 0xfa, 0x28, 0x1c, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 
-0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x00, 0x27, 0xe6, 0x88, 0xa2, 0x68, 
-0x47, 0x49, 0x08, 0x79, 0x00, 0x28, 0x08, 0xd0, 0x00, 0x2e, 0x01, 0xd0, 
-0x01, 0x2e, 0x01, 0xd1, 0x01, 0x27, 0x01, 0xe0, 0x04, 0x2e, 0x00, 0xd1, 
-0x03, 0x26, 0x01, 0x25, 0x41, 0x48, 0x05, 0x2e, 0x66, 0xd2, 0x02, 0xa3, 
-0x9b, 0x5d, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c, 0x03, 0x06, 0x08, 0x0c, 
-0x10, 0x00, 0x85, 0x83, 0x00, 0x23, 0x03, 0xe0, 0x85, 0x83, 0x05, 0xe0, 
-0x00, 0x23, 0x83, 0x83, 0xc3, 0x83, 0x06, 0xe0, 0x00, 0x23, 0x83, 0x83, 
-0xc5, 0x83, 0x02, 0xe0, 0xff, 0x23, 0x01, 0x33, 0x83, 0x83, 0xcb, 0x1d, 
-0x79, 0x33, 0x1e, 0x89, 0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 0x02, 0xdb, 
-0xd2, 0x07, 0xd2, 0x0f, 0x00, 0xe0, 0x01, 0x22, 0x6d, 0x23, 0x5b, 0x01, 
-0xc9, 0x18, 0x09, 0x88, 0xff, 0x23, 0xe1, 0x33, 0x99, 0x43, 0x01, 0x23, 
-0x19, 0x43, 0x86, 0x8b, 0xff, 0x33, 0x9e, 0x42, 0x0d, 0xd1, 0xff, 0x20, 
-0xe1, 0x30, 0x08, 0x43, 0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0x9b, 0x02, 
-0x98, 0x43, 0x01, 0x1c, 0x20, 0xe0, 0x01, 0x21, 0x89, 0x02, 0x01, 0x43, 
-0x1c, 0xe0, 0x01, 0x2e, 0x0a, 0xd1, 0xc0, 0x8b, 0x01, 0x28, 0x04, 0xd1, 
-0x60, 0x23, 0x19, 0x43, 0x00, 0x2a, 0x13, 0xd0, 0x0c, 0xe0, 0x20, 0x23, 
-0x19, 0x43, 0x0f, 0xe0, 0x00, 0x2e, 0x0d, 0xd1, 0xc0, 0x8b, 0x01, 0x28, 
-0x08, 0xd1, 0xff, 0x23, 0x81, 0x33, 0x19, 0x43, 0x00, 0x2a, 0x05, 0xd0, 
-0x01, 0x23, 0x9b, 0x02, 0x19, 0x43, 0x01, 0xe0, 0x80, 0x23, 0x19, 0x43, 
-0x04, 0x20, 0x02, 0xf0, 0x8d, 0xfc, 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 
-0x02, 0xf0, 0x88, 0xfc, 0x00, 0x2f, 0x02, 0xd1, 0x00, 0x20, 0x12, 0xe0, 
-0xff, 0xe7, 0x69, 0x46, 0x20, 0x1c, 0xff, 0xf7, 0x2b, 0xfb, 0x00, 0xa8, 
-0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 
-0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0x5e, 0xfa, 
-0x28, 0x1c, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0xe8, 0x1b, 0x00, 0x80, 
-0xc0, 0x88, 0x51, 0x21, 0x89, 0x03, 0x08, 0x62, 0x00, 0x20, 0x70, 0x47, 
-0x80, 0xb5, 0x16, 0x4f, 0xf8, 0x68, 0x01, 0x28, 0x07, 0xd1, 0x37, 0x23, 
-0x9b, 0x01, 0xf8, 0x18, 0xc0, 0x89, 0x80, 0x21, 0x01, 0x43, 0x1b, 0x20, 
-0x07, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 0xf8, 0x18, 0x00, 0x8b, 0x01, 0x21, 
-0x49, 0x03, 0x01, 0x43, 0x10, 0x20, 0x02, 0xf0, 0x4b, 0xfc, 0x01, 0x20, 
-0x07, 0x23, 0x5b, 0x02, 0xf9, 0x18, 0x88, 0x83, 0xc8, 0x83, 0x1b, 0x23, 
-0xdb, 0x01, 0xf8, 0x18, 0x00, 0x8b, 0x01, 0x23, 0x1b, 0x03, 0x98, 0x43, 
-0x41, 0x21, 0x09, 0x02, 0x01, 0x43, 0x00, 0x20, 0x02, 0xf0, 0x38, 0xfc, 
-0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0x80, 0xb5, 0x17, 0x4f, 0xf8, 0x68, 0x01, 0x28, 0x08, 0xd1, 0x37, 0x23, 
-0x9b, 0x01, 0xf8, 0x18, 0xc0, 0x89, 0x80, 0x23, 0x98, 0x43, 0x01, 0x1c, 
-0x1b, 0x20, 0x08, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 0xf8, 0x18, 0x00, 0x8b, 
-0x01, 0x23, 0x5b, 0x03, 0x98, 0x43, 0x01, 0x1c, 0x10, 0x20, 0x02, 0xf0, 
-0x19, 0xfc, 0xff, 0x20, 0x07, 0x23, 0x5b, 0x02, 0xf9, 0x18, 0x01, 0x30, 
-0x88, 0x83, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18, 0x00, 0x8b, 0x41, 0x23, 
-0x1b, 0x02, 0x98, 0x43, 0x09, 0x21, 0x49, 0x02, 0x01, 0x43, 0x00, 0x20, 
-0x02, 0xf0, 0x06, 0xfc, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xe8, 0x0d, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 0x08, 0x49, 0xcf, 0x6a, 
-0x69, 0x46, 0xff, 0xf7, 0xa5, 0xfa, 0xb8, 0x05, 0x80, 0x0d, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xdd, 0xf9, 0x01, 0x20, 
-0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0x00, 0x14, 0x40, 
-0xc0, 0x88, 0x9f, 0x23, 0x18, 0x40, 0x05, 0x49, 0xc9, 0x6a, 0x1b, 0x23, 
-0x5b, 0x01, 0x19, 0x40, 0x08, 0x43, 0x03, 0x49, 0xc0, 0x46, 0xc8, 0x62, 
-0x00, 0x20, 0x70, 0x47, 0x40, 0x00, 0x14, 0x40, 0x40, 0x00, 0x14, 0x00, 
-0x80, 0xb5, 0x84, 0xb0, 0x0d, 0x49, 0x0f, 0x6a, 0x01, 0x2f, 0x01, 0xd1, 
-0xff, 0x03, 0x07, 0xe0, 0x02, 0x2f, 0x01, 0xd1, 0x3f, 0x03, 0x03, 0xe0, 
-0x00, 0x2f, 0x01, 0xd1, 0x01, 0x27, 0xff, 0x02, 0x69, 0x46, 0xff, 0xf7, 
-0x71, 0xfa, 0x01, 0xab, 0x5f, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0xab, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x20, 0x14, 0x40, 0xc2, 0x88, 0xa1, 0x20, 0x40, 0x03, 0x00, 0x21, 
-0x01, 0x23, 0x5b, 0x03, 0x9a, 0x42, 0x01, 0xd1, 0x02, 0x22, 0x04, 0xe0, 
-0x01, 0x23, 0xdb, 0x03, 0x9a, 0x42, 0x02, 0xd1, 0x01, 0x22, 0x02, 0x62, 
-0x00, 0xe0, 0x01, 0x62, 0x08, 0x1c, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 
-0x07, 0x1c, 0x02, 0xf0, 0xb7, 0xfb, 0x69, 0x46, 0x04, 0x1c, 0x38, 0x1c, 
-0xff, 0xf7, 0x46, 0xfa, 0x01, 0xab, 0x5c, 0x80, 0x09, 0x4f, 0xf8, 0x6d, 
-0xc0, 0x46, 0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x7c, 0xf9, 
-0xf8, 0x6d, 0xc0, 0x07, 0xc0, 0x0f, 0x05, 0x49, 0xc0, 0x46, 0x88, 0x62, 
+0x09, 0x0c, 0x78, 0x78, 0x88, 0x42, 0xf1, 0xdc, 0x0a, 0x48, 0xff, 0xf7, 
+0x83, 0xf9, 0x07, 0x1c, 0x09, 0x4a, 0x20, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 
+0x7f, 0xf9, 0x08, 0x49, 0x38, 0x1c, 0xff, 0xf7, 0x7a, 0xf9, 0x68, 0x46, 
+0x00, 0x21, 0xff, 0xf7, 0xd1, 0xfa, 0x28, 0x1c, 0x46, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x51, 0xbf, 0x21, 0x40, 
+0x3c, 0x02, 0xff, 0xff, 0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x00, 0x27, 
+0xe6, 0x88, 0xa2, 0x68, 0x47, 0x49, 0x08, 0x79, 0x00, 0x28, 0x08, 0xd0, 
+0x00, 0x2e, 0x01, 0xd0, 0x01, 0x2e, 0x01, 0xd1, 0x01, 0x27, 0x01, 0xe0, 
+0x04, 0x2e, 0x00, 0xd1, 0x03, 0x26, 0x01, 0x25, 0x41, 0x48, 0x05, 0x2e, 
+0x66, 0xd2, 0x02, 0xa3, 0x9b, 0x5d, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c, 
+0x03, 0x06, 0x08, 0x0c, 0x10, 0x00, 0x05, 0x80, 0x00, 0x23, 0x03, 0xe0, 
+0x05, 0x80, 0x05, 0xe0, 0x00, 0x23, 0x03, 0x80, 0x43, 0x80, 0x06, 0xe0, 
+0x00, 0x23, 0x03, 0x80, 0x45, 0x80, 0x02, 0xe0, 
+0xff, 0x23, 0x01, 0x33, 0x03, 0x80, 0xcb, 0x1d, 0x79, 0x33, 0x9e, 0x89, 
+0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 0x02, 0xdb, 0xd2, 0x07, 0xd2, 0x0f, 
+0x00, 0xe0, 0x01, 0x22, 0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x89, 0x88, 
+0xff, 0x23, 0xe1, 0x33, 0x99, 0x43, 0x01, 0x23, 0x19, 0x43, 0x06, 0x88, 
+0xff, 0x33, 0x9e, 0x42, 0x0d, 0xd1, 0xff, 0x20, 0xe1, 0x30, 0x08, 0x43, 
+0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0x9b, 0x02, 0x98, 0x43, 0x01, 0x1c, 
+0x20, 0xe0, 0x01, 0x21, 0x89, 0x02, 0x01, 0x43, 0x1c, 0xe0, 0x01, 0x2e, 
+0x0a, 0xd1, 0x40, 0x88, 0x01, 0x28, 0x04, 0xd1, 0x60, 0x23, 0x19, 0x43, 
+0x00, 0x2a, 0x13, 0xd0, 0x0c, 0xe0, 0x20, 0x23, 0x19, 0x43, 0x0f, 0xe0, 
+0x00, 0x2e, 0x0d, 0xd1, 0x40, 0x88, 0x01, 0x28, 0x08, 0xd1, 0xff, 0x23, 
+0x81, 0x33, 0x19, 0x43, 0x00, 0x2a, 0x05, 0xd0, 0x01, 0x23, 0x9b, 0x02, 
+0x19, 0x43, 0x01, 0xe0, 0x80, 0x23, 0x19, 0x43, 0x04, 0x20, 0x03, 0xf0, 
+0x2d, 0xf8, 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0x03, 0xf0, 0x28, 0xf8, 
+0x00, 0x2f, 0x02, 0xd1, 0x00, 0x20, 0x12, 0xe0, 0xff, 0xe7, 0x69, 0x46, 
+0x20, 0x1c, 0xff, 0xf7, 0x03, 0xfb, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
+0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0x36, 0xfa, 0x28, 0x1c, 0x04, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x88, 0x1c, 0x00, 0x80, 0xc0, 0x88, 0x51, 0x21, 0x89, 0x03, 0x08, 0x62, 
+0x00, 0x20, 0x70, 0x47, 0x80, 0xb5, 0x16, 0x4f, 0xf8, 0x68, 0x01, 0x28, 
+0x07, 0xd1, 0x37, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x40, 0x8a, 0x80, 0x21, 
+0x01, 0x43, 0x1b, 0x20, 0x07, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 0xf8, 0x18, 
+0x80, 0x8b, 0x01, 0x21, 0x49, 0x03, 0x01, 0x43, 0x10, 0x20, 0x02, 0xf0, 
+0xeb, 0xff, 0x01, 0x20, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 0x08, 0x80, 
+0x48, 0x80, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18, 0x80, 0x8b, 0x01, 0x23, 
+0x1b, 0x03, 0x98, 0x43, 0x41, 0x21, 0x09, 0x02, 0x01, 0x43, 0x00, 0x20, 
+0x02, 0xf0, 0xd8, 0xff, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x17, 0x4f, 0xf8, 0x68, 0x01, 0x28, 
+0x08, 0xd1, 0x37, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x40, 0x8a, 0x80, 0x23, 
+0x98, 0x43, 0x01, 0x1c, 0x1b, 0x20, 0x08, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 
+0xf8, 0x18, 0x80, 0x8b, 0x01, 0x23, 0x5b, 0x03, 0x98, 0x43, 0x01, 0x1c, 
+0x10, 0x20, 0x02, 0xf0, 0xb9, 0xff, 0xff, 0x20, 0x71, 0x23, 0x5b, 0x01, 
+0xf9, 0x18, 0x01, 0x30, 0x08, 0x80, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18, 
+0x80, 0x8b, 0x41, 0x23, 0x1b, 0x02, 0x98, 0x43, 0x09, 0x21, 0x49, 0x02, 
+0x01, 0x43, 0x00, 0x20, 0x02, 0xf0, 0xa6, 0xff, 0x00, 0x20, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 
+0x08, 0x49, 0xcf, 0x6a, 0x69, 0x46, 0xff, 0xf7, 0x7d, 0xfa, 0xb8, 0x05, 
+0x80, 0x0d, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
+0xb5, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x40, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x9f, 0x23, 0x18, 0x40, 0x05, 0x49, 
+0xc9, 0x6a, 0x1b, 0x23, 0x5b, 0x01, 0x19, 0x40, 0x08, 0x43, 0x03, 0x49, 
+0xc0, 0x46, 0xc8, 0x62, 0x00, 0x20, 0x70, 0x47, 0x40, 0x00, 0x14, 0x40, 
+0x40, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 
+0x0d, 0x49, 0x0f, 0x6a, 0x01, 0x2f, 0x01, 0xd1, 0xff, 0x03, 0x07, 0xe0, 
+0x02, 0x2f, 0x01, 0xd1, 0x3f, 0x03, 0x03, 0xe0, 0x00, 0x2f, 0x01, 0xd1, 
+0x01, 0x27, 0xff, 0x02, 0x69, 0x46, 0xff, 0xf7, 0x49, 0xfa, 0x01, 0xab, 
+0x5f, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x83, 0xf9, 0x01, 0x20, 
+0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x14, 0x40, 
+0xc2, 0x88, 0xa1, 0x20, 0x40, 0x03, 0x00, 0x21, 0x01, 0x23, 0x5b, 0x03, 
+0x9a, 0x42, 0x01, 0xd1, 0x02, 0x22, 0x04, 0xe0, 0x01, 0x23, 0xdb, 0x03, 
+0x9a, 0x42, 0x02, 0xd1, 0x01, 0x22, 0x02, 0x62, 0x00, 0xe0, 0x01, 0x62, 
+0x08, 0x1c, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x02, 0xf0, 
+0x57, 0xff, 0x69, 0x46, 0x04, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x1e, 0xfa, 
+0x01, 0xab, 0x5c, 0x80, 0x09, 0x4f, 0xf8, 0x6d, 0xc0, 0x46, 0x02, 0x90, 
+0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x54, 0xf9, 0xf8, 0x6d, 0xc0, 0x07, 
+0xc0, 0x0f, 0x05, 0x49, 0xc0, 0x46, 0xc8, 0x62, 0x01, 0x20, 0x04, 0xb0, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 
+0x68, 0x1c, 0x00, 0x80, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x48, 0x61, 
+0x00, 0x20, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 
+0x69, 0x46, 0xff, 0xf7, 0xf7, 0xf9, 0x06, 0x48, 0xc0, 0x68, 0x01, 0xab, 
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x2f, 0xf9, 0x01, 0x20, 
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x40, 
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x70, 0x47, 
+0x80, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0x87, 0x68, 
+0xff, 0xf7, 0xda, 0xf9, 0x20, 0x2f, 0x07, 0xd2, 0x78, 0x00, 0x0c, 0x49, 
+0x40, 0x18, 0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x80, 0x8b, 0x06, 0xe0, 
+0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 
+0x02, 0x20, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
+0x03, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x82, 0x68, 
+0x20, 0x2a, 0x04, 0xd2, 0x10, 0x1c, 0x02, 0xf0, 0xcf, 0xfe, 0x00, 0x20, 
+0x10, 0xe0, 0x69, 0x46, 0xff, 0xf7, 0xae, 0xf9, 0x00, 0xa8, 0x00, 0x78, 
+0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 
+0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0xe1, 0xf8, 0x01, 0x20, 
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0xc7, 0x88, 
+0x69, 0x46, 0xff, 0xf7, 0x97, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0x78, 0xff, 
+0x02, 0x20, 0x39, 0x1c, 0x03, 0xf0, 0x3c, 0xfe, 0x00, 0x28, 0x06, 0xd0, 
+0x02, 0x20, 0x39, 0x1c, 0x03, 0xf0, 0x8c, 0xfd, 0x01, 0xab, 0x58, 0x80, 
+0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x07, 0x49, 0x20, 0x1c, 
+0xfe, 0xf7, 0x65, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xbc, 0xf8, 
 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x10, 0x2a, 0x00, 0x80, 0xe8, 0x1b, 0x00, 0x80, 0xc0, 0x88, 0x02, 0x49, 
-0xc0, 0x46, 0x48, 0x61, 0x00, 0x20, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 
-0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 0x1f, 0xfa, 0x06, 0x48, 
-0xc0, 0x68, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xff, 0xf7, 0x57, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 
-0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 
-0x80, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0x87, 0x68, 0xff, 0xf7, 0x02, 0xfa, 
-0x20, 0x2f, 0x07, 0xd2, 0x78, 0x00, 0x0c, 0x49, 0x40, 0x18, 0x1b, 0x23, 
-0xdb, 0x01, 0xc0, 0x18, 0x00, 0x8b, 0x06, 0xe0, 0x00, 0xa8, 0x00, 0x78, 
-0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x2b, 0xf9, 0x01, 0x20, 
-0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x82, 0x68, 0x20, 0x2a, 0x04, 0xd2, 
-0x10, 0x1c, 0x02, 0xf0, 0x2f, 0xfb, 0x00, 0x20, 0x10, 0xe0, 0x69, 0x46, 
-0xff, 0xf7, 0xd6, 0xf9, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 
-0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 
-0x04, 0x33, 0xff, 0xf7, 0x09, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0xc7, 0x88, 0x69, 0x46, 0xff, 0xf7, 
-0xbf, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0xa0, 0xff, 0x02, 0x20, 0x39, 0x1c, 
-0x03, 0xf0, 0x5a, 0xfa, 0x00, 0x28, 0x06, 0xd0, 0x02, 0x20, 0x39, 0x1c, 
-0x03, 0xf0, 0x94, 0xf9, 0x01, 0xab, 0x58, 0x80, 0x02, 0xe0, 0x45, 0x20, 
-0x00, 0xab, 0x18, 0x70, 0x07, 0x49, 0x20, 0x1c, 0xfe, 0xf7, 0x8d, 0xff, 
-0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xe4, 0xf8, 0x01, 0x20, 0x04, 0xb0, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 
-0x3c, 0x02, 0xff, 0xff, 0xb0, 0xb5, 0x84, 0xb0, 0xc7, 0x88, 0x69, 0x46, 
-0x84, 0x68, 0xff, 0xf7, 0x93, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0x74, 0xff, 
-0x0f, 0x4a, 0x02, 0x20, 0x39, 0x1c, 0xfe, 0xf7, 0x71, 0xff, 0x00, 0x28, 
-0x06, 0xd0, 0x0d, 0x4b, 0x02, 0x20, 0x39, 0x1c, 0x22, 0x1c, 0xfe, 0xf7, 
-0x6a, 0xff, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49, 
-0x28, 0x1c, 0xfe, 0xf7, 0x60, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0xb7, 0xf8, 0x01, 0x20, 0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x24, 0x02, 0xff, 0xff, 0xb9, 0xb8, 0x21, 0x40, 0x7b, 0xb7, 0x21, 0x40, 
-0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 0x7f, 0xf9, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x20, 0x70, 0x47, 0x80, 0xb4, 0xc2, 0x88, 0x19, 0x4b, 
-0xa1, 0x21, 0x49, 0x03, 0x00, 0x2a, 0x03, 0xd1, 0x18, 0x6b, 0x10, 0x23, 
-0x98, 0x43, 0x04, 0xe0, 0x01, 0x2a, 0x04, 0xd1, 0x18, 0x6b, 0x10, 0x23, 
-0x18, 0x43, 0x48, 0x61, 0x1f, 0xe0, 0x02, 0x2a, 0x1d, 0xd1, 0xc2, 0x68, 
-0x87, 0x68, 0x00, 0x20, 0x3b, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 
-0x9b, 0x02, 0x03, 0x43, 0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 
-0x20, 0x28, 0xf3, 0xdb, 0x00, 0x20, 0x13, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 
-0xdb, 0x0f, 0x9b, 0x02, 0xc7, 0x1d, 0x19, 0x37, 0x3b, 0x43, 0x0b, 0x61, 
-0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 0xf1, 0xdb, 0x00, 0x20, 
-0x80, 0xbc, 0x70, 0x47, 0x80, 0x00, 0x14, 0x40, 0x90, 0xb4, 0xc2, 0x88, 
-0x81, 0x68, 0x10, 0x02, 0x12, 0x0a, 0x10, 0x43, 0x02, 0x04, 0x12, 0x0c, 
-0x0f, 0x48, 0xc0, 0x46, 0x02, 0x60, 0x0f, 0x4f, 0x65, 0x23, 0x5b, 0x01, 
-0xfb, 0x18, 0x9a, 0x83, 0x0a, 0x0c, 0x14, 0x02, 
-0x12, 0x12, 0x22, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x42, 0x60, 0xda, 0x83, 
+0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 0xb0, 0xb5, 0x84, 0xb0, 
+0xc7, 0x88, 0x69, 0x46, 0x84, 0x68, 0xff, 0xf7, 0x6b, 0xf9, 0x10, 0x48, 
+0xfe, 0xf7, 0x4c, 0xff, 0x0f, 0x4a, 0x02, 0x20, 0x39, 0x1c, 0xfe, 0xf7, 
+0x49, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x0d, 0x4b, 0x02, 0x20, 0x39, 0x1c, 
+0x22, 0x1c, 0xfe, 0xf7, 0x42, 0xff, 0x02, 0xe0, 
+0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49, 0x28, 0x1c, 0xfe, 0xf7, 
+0x38, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x8f, 0xf8, 0x01, 0x20, 
+0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 
+0xcd, 0xc0, 0x21, 0x40, 0xd9, 0xbf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 
+0x00, 0xb5, 0xff, 0xf7, 0x57, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 
+0x70, 0x47, 0x80, 0xb4, 0xc2, 0x88, 0x19, 0x4b, 0xa1, 0x21, 0x49, 0x03, 
+0x00, 0x2a, 0x03, 0xd1, 0x18, 0x6b, 0x10, 0x23, 0x98, 0x43, 0x04, 0xe0, 
+0x01, 0x2a, 0x04, 0xd1, 0x18, 0x6b, 0x10, 0x23, 0x18, 0x43, 0x48, 0x61, 
+0x1f, 0xe0, 0x02, 0x2a, 0x1d, 0xd1, 0xc2, 0x68, 0x87, 0x68, 0x00, 0x20, 
+0x3b, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0x03, 0x43, 
+0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 0xf3, 0xdb, 
+0x00, 0x20, 0x13, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 
+0xc7, 0x1d, 0x19, 0x37, 0x3b, 0x43, 0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 
+0x00, 0x0c, 0x20, 0x28, 0xf1, 0xdb, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 
+0x80, 0x00, 0x14, 0x40, 0x80, 0xb4, 0xc2, 0x88, 0x81, 0x68, 0x10, 0x02, 
+0x12, 0x0a, 0x10, 0x43, 0x02, 0x04, 0x12, 0x0c, 0x0c, 0x48, 0xc0, 0x46, 
+0x02, 0x60, 0x0c, 0x4b, 0xc0, 0x46, 0x1a, 0x80, 0x0a, 0x0c, 0x17, 0x02, 
+0x12, 0x12, 0x3a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x42, 0x60, 0x5a, 0x80, 
 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 0x09, 0x0a, 0x11, 0x43, 0x09, 0x04, 
-0x09, 0x0c, 0x81, 0x60, 0x33, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x01, 0x80, 
-0x00, 0x20, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 
-0xe8, 0x0d, 0x00, 0x80, 0xb0, 0xb5, 0x84, 0xb0, 0x13, 0x49, 0x0a, 0x68, 
-0x12, 0x04, 0x12, 0x0c, 0x13, 0x02, 0x12, 0x12, 0x13, 0x43, 0x4a, 0x68, 
-0x12, 0x04, 0x12, 0x0c, 0x1f, 0x1c, 0x13, 0x02, 0x12, 0x12, 0x13, 0x43, 
-0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 0x09, 0x12, 0x11, 0x43, 
-0x0c, 0x04, 0x24, 0x0c, 0x69, 0x46, 0x1d, 0x1c, 0xff, 0xf7, 0xe4, 0xf8, 
-0x01, 0xab, 0x5f, 0x80, 0x28, 0x04, 0x20, 0x43, 0x02, 0x90, 0x68, 0x46, 
-0x00, 0x21, 0xff, 0xf7, 0x1b, 0xf8, 0x01, 0x20, 0x04, 0xb0, 0xb0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x40, 0x00, 0x14, 0x40, 0xc1, 0x88, 0x82, 0x68, 
-0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x0a, 0x49, 
-0xc0, 0x46, 0xc8, 0x60, 0x10, 0x0c, 0x03, 0x02, 0x00, 0x12, 0x18, 0x43, 
-0x00, 0x04, 0x00, 0x0c, 0x08, 0x61, 0x10, 0x04, 0x00, 0x0c, 0x02, 0x02, 
-0x00, 0x0a, 0x10, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x48, 0x61, 0x00, 0x20, 
-0x70, 0x47, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 0x90, 0xb5, 0x84, 0xb0, 
-0x16, 0x4b, 0xd9, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 0x09, 0x12, 
-0x11, 0x43, 0x1a, 0x69, 0x12, 0x04, 0x12, 0x0c, 0x17, 0x02, 0x12, 0x12, 
-0x3a, 0x43, 0x5b, 0x69, 0x1b, 0x04, 0x1b, 0x0c, 0x1f, 0x02, 0x1b, 0x12, 
-0x3b, 0x43, 0x1f, 0x04, 0x3f, 0x0c, 0x05, 0x23, 0x00, 0x93, 0x84, 0x88, 
-0x01, 0xab, 0x1c, 0x80, 0x00, 0x24, 0x04, 0x3b, 0x5c, 0x70, 0x40, 0x88, 
-0x00, 0xab, 0x58, 0x80, 0xd9, 0x80, 0x10, 0x04, 0x38, 0x43, 0x02, 0x90, 
-0x03, 0x94, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xcb, 0xff, 0x01, 0x20, 
-0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0x00, 0x14, 0x40, 
-0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x8a, 0x6a, 0x05, 0x21, 0x00, 0x91, 
-0x81, 0x88, 0x01, 0xab, 0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 
-0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 
-0x68, 0x46, 0xfe, 0xf7, 0xaf, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 
-0xc0, 0x46, 0x88, 0x62, 0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 
-0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x0a, 0x6a, 0x05, 0x21, 0x00, 0x91, 
-0x81, 0x88, 0x01, 0xab, 0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 
-0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 
-0x68, 0x46, 0xfe, 0xf7, 0x8b, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 
-0xc0, 0x46, 0x08, 0x62, 0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 
-0x00, 0xb5, 0xc0, 0x88, 0x02, 0x49, 0xfe, 0xf7, 0x1c, 0xfe, 0x00, 0x20, 
-0x08, 0xbc, 0x18, 0x47, 0x75, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 
-0x69, 0x46, 0xff, 0xf7, 0x2d, 0xf8, 0x06, 0x48, 0x00, 0x6b, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x65, 0xff, 0x01, 0x20, 
-0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0xb5, 0xff, 0xf7, 0x33, 0xf8, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x2e, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xff, 0xf7, 0x29, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 
-0x01, 0x20, 0x14, 0x4f, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 0x08, 0x71, 
-0x12, 0x48, 0xfe, 0xf7, 0xe9, 0xfd, 0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 
-0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0xf9, 0x1d, 0xb9, 0x31, 0x08, 0x70, 
-0x0d, 0x4a, 0x01, 0x23, 0x1b, 0x04, 0x11, 0x68, 0x0b, 0x40, 0x12, 0x21, 
-0x00, 0x2b, 0x05, 0xd1, 0x13, 0x68, 0x1b, 0x0c, 0x08, 0xd1, 0x12, 0x68, 
-0x92, 0x0a, 0x05, 0xd3, 0x07, 0x4a, 0xc0, 0x46, 0xd1, 0x60, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x05, 0x4a, 0xc0, 0x46, 0x11, 0x64, 0xf8, 0xe7, 
-0xe8, 0x0d, 0x00, 0x80, 0xa9, 0x9d, 0x21, 0x40, 0x00, 0x00, 0x10, 0x40, 
-0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x02, 0xf0, 
-0x83, 0xfb, 0x01, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 
-0x07, 0x1c, 0xf8, 0x88, 0x02, 0xf0, 0x88, 0xfc, 0x00, 0x28, 0x0c, 0xd1, 
-0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0xc8, 0xff, 0x06, 0x48, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x01, 0xff, 0x01, 0x20, 
+0x09, 0x0c, 0x81, 0x60, 0x99, 0x80, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 
+0x40, 0x00, 0x14, 0x00, 0x28, 0x1b, 0x00, 0x80, 0xb0, 0xb5, 0x84, 0xb0, 
+0x13, 0x49, 0x0a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x13, 0x02, 0x12, 0x12, 
+0x13, 0x43, 0x4a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x1f, 0x1c, 0x13, 0x02, 
+0x12, 0x12, 0x13, 0x43, 0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 
+0x09, 0x12, 0x11, 0x43, 0x0c, 0x04, 0x24, 0x0c, 0x69, 0x46, 0x1d, 0x1c, 
+0xff, 0xf7, 0xc2, 0xf8, 0x01, 0xab, 0x5f, 0x80, 0x28, 0x04, 0x20, 0x43, 
+0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xf9, 0xff, 0x01, 0x20, 
+0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0x00, 0x14, 0x40, 
+0xc1, 0x88, 0x82, 0x68, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x00, 0x04, 
+0x00, 0x0c, 0x0a, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x10, 0x0c, 0x03, 0x02, 
+0x00, 0x12, 0x18, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x08, 0x61, 0x10, 0x04, 
+0x00, 0x0c, 0x02, 0x02, 0x00, 0x0a, 0x10, 0x43, 0x00, 0x04, 0x00, 0x0c, 
+0x48, 0x61, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 
+0x90, 0xb5, 0x84, 0xb0, 0x16, 0x4b, 0xd9, 0x68, 0x09, 0x04, 0x09, 0x0c, 
+0x0a, 0x02, 0x09, 0x12, 0x11, 0x43, 0x1a, 0x69, 0x12, 0x04, 0x12, 0x0c, 
+0x17, 0x02, 0x12, 0x12, 0x3a, 0x43, 0x5b, 0x69, 0x1b, 0x04, 0x1b, 0x0c, 
+0x1f, 0x02, 0x1b, 0x12, 0x3b, 0x43, 0x1f, 0x04, 0x3f, 0x0c, 0x05, 0x23, 
+0x00, 0x93, 0x84, 0x88, 0x01, 0xab, 0x1c, 0x80, 0x00, 0x24, 0x04, 0x3b, 
+0x5c, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xd9, 0x80, 0x10, 0x04, 
+0x38, 0x43, 0x02, 0x90, 0x03, 0x94, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 
+0xa9, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x40, 0x00, 0x14, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x8a, 0x6a, 
+0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 
+0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 
+0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 
+0x8d, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x88, 0x62, 
+0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 
+0x0b, 0x49, 0x0a, 0x6a, 0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 
+0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 
+0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 
+0x69, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x62, 
+0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0xc0, 0x88, 
+0x02, 0x49, 0xfe, 0xf7, 0xfa, 0xfd, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 
+0x75, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 
+0x0b, 0xf8, 0x06, 0x48, 0x00, 0x6b, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xfe, 0xf7, 0x43, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7, 
+0x11, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x0c, 0xf8, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x07, 0xf8, 0x08, 0xbc, 
+0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 0x10, 0x48, 0xfe, 0xf7, 0xcc, 0xfd, 
+0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x21, 
+0x0c, 0x48, 0xc0, 0x46, 0x01, 0x71, 0x0c, 0x48, 0x02, 0x68, 0x52, 0x0c, 
+0x05, 0xd2, 0x02, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 
+0x03, 0xd3, 0x08, 0x48, 0xc0, 0x46, 0xc7, 0x60, 0x02, 0xe0, 0x07, 0x48, 
+0xc0, 0x46, 0x07, 0x64, 0x08, 0x1c, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x21, 0xa5, 0x21, 0x40, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
+0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x20, 
+0x03, 0x49, 0xc0, 0x46, 0x08, 0x72, 0x12, 0x20, 0xff, 0xf7, 0xcb, 0xff, 
+0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x20, 
+0x03, 0x49, 0xc0, 0x46, 0x48, 0x72, 0x15, 0x20, 0xff, 0xf7, 0xbf, 0xff, 
+0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x02, 0xf0, 
+0xf3, 0xfe, 0x01, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 
+0x07, 0x1c, 0xf8, 0x88, 0x02, 0xf0, 0xf8, 0xff, 0x00, 0x28, 0x0c, 0xd1, 
+0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x96, 0xff, 0x06, 0x48, 0x01, 0xab, 
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xcf, 0xfe, 0x01, 0x20, 
 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0xff, 0xff, 0x00, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 
-0xb3, 0xff, 0x03, 0xf0, 0x71, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x09, 0x48, 
+0x81, 0xff, 0x04, 0xf0, 0x47, 0xfa, 0x01, 0xab, 0x58, 0x80, 0x09, 0x48, 
 0x81, 0x89, 0x09, 0x04, 0xc2, 0x89, 0x11, 0x43, 0x02, 0x91, 0x81, 0x88, 
 0x09, 0x04, 0xc0, 0x88, 0x08, 0x43, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 
-0xfe, 0xf7, 0xe0, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 
-0xc8, 0x29, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0xaf, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xaa, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0xa5, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xfe, 0xf7, 0xa0, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
-0x9b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x96, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x91, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x8c, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0x87, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xfe, 0xf7, 0x82, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
-0x7d, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x78, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x73, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0x8c, 0xb0, 0x08, 0xa9, 0xfe, 0xf7, 0x54, 0xff, 
-0x69, 0x46, 0x08, 0xa8, 0x03, 0xf0, 0xba, 0xfe, 0x02, 0x20, 0x08, 0xab, 
-0x58, 0x70, 0x69, 0x46, 0x08, 0xa8, 0xfe, 0xf7, 0x89, 0xfe, 0x01, 0x20, 
-0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x5a, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
-0x38, 0x1c, 0xfe, 0xf7, 0x39, 0xff, 0xf9, 0x88, 0x10, 0x48, 0x01, 0x24, 
-0x00, 0x29, 0x0e, 0xd0, 0x04, 0x73, 0x44, 0x73, 0xb9, 0x68, 0x09, 0x0c, 
-0x41, 0x82, 0xb9, 0x68, 0xc0, 0x46, 0x81, 0x82, 0xf9, 0x68, 0x09, 0x0c, 
-0xc1, 0x82, 0xf9, 0x68, 0xc0, 0x46, 0x01, 0x83, 0x02, 0xe0, 0x00, 0x21, 
-0x01, 0x73, 0x41, 0x73, 0x06, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xfe, 0xf7, 0x5b, 0xfe, 0x20, 0x1c, 
-0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
-0xff, 0xff, 0x00, 0x00, 0x00, 0xb5, 0xfe, 0xf7, 0x27, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x22, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0x1d, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xfe, 0xf7, 0x18, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
-0x13, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 
-0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0xf2, 0xfe, 0xf8, 0x88, 0x03, 0x24, 
-0xe4, 0x04, 0x04, 0x43, 0x03, 0x23, 0xdb, 0x04, 0x9c, 0x42, 0x02, 0xd3, 
-0x0f, 0x4b, 0x9c, 0x42, 0x06, 0xd9, 0x0f, 0x48, 0x01, 0xab, 0x58, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x20, 0xfe, 0x01, 0x20, 0x80, 0x07, 
-0x20, 0x43, 0x00, 0x68, 0x00, 0x21, 0x00, 0xab, 0x59, 0x70, 0xfa, 0x88, 
-0xc0, 0x46, 0xda, 0x80, 0x02, 0x90, 0x03, 0x91, 0x68, 0x46, 0x04, 0x33, 
-0xfe, 0xf7, 0x10, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 
+0xfe, 0xf7, 0xae, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0x7d, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x78, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xfe, 0xf7, 0x73, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x6e, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xfe, 0xf7, 0x69, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0xfe, 0xf7, 0x64, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0x5f, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x5a, 0xff, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x55, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x50, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xfe, 0xf7, 0x4b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0xfe, 0xf7, 0x46, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x8c, 0xb0, 
+0x08, 0xa9, 0xfe, 0xf7, 0x27, 0xff, 0x69, 0x46, 0x08, 0xa8, 0x04, 0xf0, 
+0x75, 0xfa, 0x02, 0x20, 0x08, 0xab, 0x58, 0x70, 0x69, 0x46, 0x08, 0xa8, 
+0xfe, 0xf7, 0x5c, 0xfe, 0x01, 0x20, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xfe, 0xf7, 0x2d, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 
+0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x0c, 0xff, 
+0xfa, 0x88, 0x12, 0x49, 0x01, 0x24, 0xc8, 0x1d, 0x89, 0x30, 0x00, 0x2a, 
+0x0f, 0xd0, 0x04, 0x70, 0x44, 0x70, 0xb8, 0x68, 0x00, 0x0c, 0x80, 0x31, 
+0xc8, 0x82, 0xb8, 0x68, 0xc0, 0x46, 0x08, 0x83, 0xf8, 0x68, 0x00, 0x0c, 
+0x48, 0x83, 0xf8, 0x68, 0xc0, 0x46, 0x88, 0x83, 0x02, 0xe0, 0x00, 0x21, 
+0x01, 0x70, 0x41, 0x70, 0x06, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xfe, 0xf7, 0x2b, 0xfe, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
+0x00, 0xb5, 0xfe, 0xf7, 0xf7, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0xfe, 0xf7, 0xf2, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0xed, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xe8, 0xfe, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xe3, 0xfe, 0x08, 0xbc, 
+0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 
+0xfe, 0xf7, 0xc2, 0xfe, 0xf8, 0x88, 0x03, 0x24, 0xe4, 0x04, 0x04, 0x43, 
+0x03, 0x23, 0xdb, 0x04, 0x9c, 0x42, 0x02, 0xd3, 0x0f, 0x4b, 0x9c, 0x42, 
+0x06, 0xd9, 0x0f, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 
+0xfe, 0xf7, 0xf0, 0xfd, 0x01, 0x20, 0x80, 0x07, 0x20, 0x43, 0x00, 0x68, 
+0x00, 0x21, 0x00, 0xab, 0x59, 0x70, 0xfa, 0x88, 0xc0, 0x46, 0xda, 0x80, 
+0x02, 0x90, 0x03, 0x91, 0x68, 0x46, 0x04, 0x33, 0xfe, 0xf7, 0xe0, 0xfd, 
+0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xe0, 0x00, 0x18, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xb5, 0x84, 0xb0, 
+0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x8f, 0xfe, 0xf8, 0x88, 
+0x03, 0x23, 0xdb, 0x04, 0x18, 0x43, 0x98, 0x42, 0x02, 0xd3, 0x0a, 0x4b, 
+0x98, 0x42, 0x08, 0xd9, 0x09, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xfe, 0xf7, 0xbf, 0xfd, 0x01, 0x20, 0x03, 0xe0, 0xb9, 0x68, 
+0xc0, 0x46, 0x01, 0x60, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 
 0x18, 0x47, 0x00, 0x00, 0xe0, 0x00, 0x18, 0x00, 0xff, 0xff, 0x00, 0x00, 
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 
-0xbf, 0xfe, 0xf8, 0x88, 0x03, 0x23, 0xdb, 0x04, 0x18, 0x43, 0x98, 0x42, 
-0x02, 0xd3, 0x0a, 0x4b, 0x98, 0x42, 0x08, 0xd9, 0x09, 0x48, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xef, 0xfd, 0x01, 0x20, 
-0x03, 0xe0, 0xb9, 0x68, 0xc0, 0x46, 0x01, 0x60, 0x00, 0x20, 0x04, 0xb0, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe0, 0x00, 0x18, 0x00, 
-0xff, 0xff, 0x00, 0x00, 0x80, 0xb5, 0x86, 0xb0, 0x07, 0x1c, 0x03, 0xf0, 
-0x5b, 0xfd, 0x38, 0x1c, 0x02, 0xa9, 0xfe, 0xf7, 0x97, 0xfe, 0x01, 0x27, 
-0x02, 0xab, 0x5f, 0x70, 0x00, 0x20, 0xd8, 0x80, 0x0a, 0x48, 0x01, 0x68, 
-0xc0, 0x46, 0x04, 0x91, 0x41, 0x68, 0xc0, 0x46, 0x05, 0x91, 0x81, 0x68, 
-0xc0, 0x46, 0x00, 0x91, 0x00, 0x69, 0xc0, 0x46, 0x01, 0x90, 0x69, 0x46, 
-0x02, 0xa8, 0xfe, 0xf7, 0xc1, 0xfd, 0x38, 0x1c, 0x06, 0xb0, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x18, 0x00, 0x80, 0x00, 0xb5, 0xc1, 0x68, 
-0x80, 0x68, 0xfe, 0xf7, 0x79, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0xb5, 0x86, 0xb0, 0x07, 0x1c, 0x04, 0xf0, 0x33, 0xf9, 0x38, 0x1c, 
+0x02, 0xa9, 0xfe, 0xf7, 0x67, 0xfe, 0x01, 0x27, 0x02, 0xab, 0x5f, 0x70, 
+0x00, 0x20, 0xd8, 0x80, 0x0a, 0x48, 0x41, 0x68, 0xc0, 0x46, 0x04, 0x91, 
+0x81, 0x68, 0xc0, 0x46, 0x05, 0x91, 0xc1, 0x68, 
+0xc0, 0x46, 0x00, 0x91, 0x40, 0x69, 0xc0, 0x46, 0x01, 0x90, 0x69, 0x46, 
+0x02, 0xa8, 0xfe, 0xf7, 0x91, 0xfd, 0x38, 0x1c, 0x06, 0xb0, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x19, 0x00, 0x80, 0x00, 0xb5, 0xc1, 0x68, 
+0x80, 0x68, 0xfe, 0xf7, 0x49, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 
 0x00, 0x20, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 
-0x68, 0x46, 0x50, 0x21, 0xfe, 0xf7, 0x76, 0xfe, 0x01, 0xab, 0x5c, 0x80, 
-0x02, 0x97, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xa1, 0xfd, 0x04, 0xb0, 
+0x68, 0x46, 0x50, 0x21, 0xfe, 0xf7, 0x46, 0xfe, 0x01, 0xab, 0x5c, 0x80, 
+0x02, 0x97, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x71, 0xfd, 0x04, 0xb0, 
 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 
-0x68, 0x46, 0x51, 0x21, 0xfe, 0xf7, 0x64, 0xfe, 0x01, 0xab, 0x5f, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x90, 0xfd, 0x04, 0xb0, 0x80, 0xbc, 
+0x68, 0x46, 0x51, 0x21, 0xfe, 0xf7, 0x34, 0xfe, 0x01, 0xab, 0x5f, 0x80, 
+0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x60, 0xfd, 0x04, 0xb0, 0x80, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
 0x90, 0xb5, 0x84, 0xb0, 0x00, 0x27, 0x12, 0x49, 0x09, 0x68, 0x12, 0x4a, 
 0x12, 0x6b, 0x10, 0x23, 0x1a, 0x40, 0x01, 0x24, 0x00, 0x2a, 0x00, 0xd0, 
 0x01, 0x27, 0x8a, 0x0c, 0x03, 0xd3, 0x3a, 0x04, 0x12, 0x0c, 0x02, 0x27, 
 0x17, 0x43, 0xc9, 0x0c, 0x03, 0xd3, 0x39, 0x04, 0x09, 0x0c, 0x04, 0x27, 
-0x0f, 0x43, 0x69, 0x46, 0xfe, 0xf7, 0x2c, 0xfe, 0x01, 0xab, 0x5f, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x66, 0xfd, 0x20, 0x1c, 0x04, 0xb0, 
+0x0f, 0x43, 0x69, 0x46, 0xfe, 0xf7, 0xfc, 0xfd, 0x01, 0xab, 0x5f, 0x80, 
+0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x36, 0xfd, 0x20, 0x1c, 0x04, 0xb0, 
 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
-0xc0, 0x00, 0x18, 0x40, 0x00, 0xb5, 0x84, 0xb0, 
-0x69, 0x46, 0xfe, 0xf7, 0x17, 0xfe, 0x06, 0x48, 0xc0, 0x6d, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x4f, 0xfd, 0x01, 0x20, 
-0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x10, 0x2a, 0x00, 0x80, 
-0x00, 0xb5, 0xfe, 0xf7, 0x1d, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x47, 
-0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
-0x80, 0xb5, 0x01, 0x20, 0x14, 0x4f, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 
-0x48, 0x71, 0x13, 0x48, 0xfe, 0xf7, 0xd6, 0xfb, 0x01, 0x20, 0x40, 0x02, 
-0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0xf9, 0x1d, 0xb9, 0x31, 
-0x08, 0x70, 0x0e, 0x4a, 0x01, 0x23, 0x1b, 0x04, 0x11, 0x68, 0x0b, 0x40, 
-0x15, 0x21, 0x00, 0x2b, 0x05, 0xd1, 0x13, 0x68, 0x1b, 0x0c, 0x08, 0xd1, 
-0x12, 0x68, 0x92, 0x0a, 0x05, 0xd3, 0x08, 0x4a, 0xc0, 0x46, 0xd1, 0x60, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x06, 0x4a, 0xc0, 0x46, 0x11, 0x64, 
-0xf8, 0xe7, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0xa9, 0x9d, 0x21, 0x40, 
-0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 
+0xc0, 0x00, 0x18, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 
+0xe7, 0xfd, 0x06, 0x48, 0xc0, 0x6d, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xfe, 0xf7, 0x1f, 0xfd, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 
+0xed, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
-0x80, 0xb5, 0x85, 0xb0, 0x01, 0xa9, 0xfe, 0xf7, 0xbb, 0xfd, 0x00, 0x20, 
-0x01, 0xab, 0x58, 0x70, 0x10, 0x49, 0xc9, 0x68, 0x01, 0x27, 0x01, 0x29, 
-0x0a, 0xd1, 0x03, 0xf0, 0xb9, 0xfc, 0x03, 0x90, 0x04, 0x97, 0x03, 0x98, 
-0x00, 0x28, 0x06, 0xd0, 0x68, 0x46, 0x02, 0xf0, 0x15, 0xf8, 0x04, 0xe0, 
-0x03, 0x97, 0x04, 0x90, 0xf8, 0xe7, 0x00, 0x20, 0x00, 0x90, 0x02, 0xab, 
-0x00, 0x98, 0xc0, 0x46, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfe, 0xf7, 
-0xdb, 0xfc, 0x38, 0x1c, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xe8, 0x0d, 0x00, 0x80, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
-0x38, 0x1c, 0xfe, 0xf7, 0x8d, 0xfd, 0x00, 0x20, 0x00, 0xab, 0x58, 0x70, 
-0x01, 0x24, 0x20, 0x1c, 0x12, 0x49, 0xc9, 0x68, 0x01, 0x29, 0x00, 0xd0, 
-0x00, 0x20, 0x00, 0x06, 0x00, 0x0e, 0x13, 0xd0, 0xf8, 0x88, 0x0f, 0x4a, 
-0x90, 0x42, 0x02, 0xd0, 0x0e, 0x4b, 0x98, 0x42, 0x08, 0xd1, 0xb9, 0x68, 
-0x27, 0x1c, 0x90, 0x42, 0x00, 0xd0, 0x00, 0x27, 0x38, 0x06, 0x00, 0x0e, 
-0x03, 0xf0, 0xa0, 0xfc, 0x03, 0xf0, 0x76, 0xfc, 0x02, 0x90, 0x00, 0xe0, 
-0x02, 0x94, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xa7, 0xfc, 0x20, 0x1c, 
-0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0xed, 0xfe, 0x00, 0x00, 0xfe, 0xca, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c, 
-0x00, 0x24, 0x00, 0x2f, 0x04, 0xd3, 0x04, 0xf0, 0x9b, 0xf8, 0x01, 0x34, 
-0xbc, 0x42, 0xfa, 0xd9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
-0x14, 0x1c, 0x0d, 0x1c, 0x06, 0x1c, 0x1f, 0x1c, 0x1b, 0x4b, 0x32, 0x04, 
-0x12, 0x0c, 0x3c, 0x21, 0x02, 0x20, 0xfe, 0xf7, 0x2a, 0xfb, 0x32, 0x0c, 
-0x17, 0x4b, 0x3e, 0x21, 0x02, 0x20, 0xfe, 0xf7, 0x24, 0xfb, 0x15, 0x4b, 
-0x2a, 0x04, 0x12, 0x0c, 0x40, 0x21, 0x02, 0x20, 0xfe, 0xf7, 0x1d, 0xfb, 
-0x2a, 0x0c, 0x11, 0x4b, 0x42, 0x21, 0x02, 0x20, 0xfe, 0xf7, 0x17, 0xfb, 
-0x0e, 0x4b, 0x22, 0x04, 0x12, 0x0c, 0x44, 0x21, 0x02, 0x20, 0xfe, 0xf7, 
-0x10, 0xfb, 0x22, 0x0c, 0x0a, 0x4b, 0x46, 0x21, 0x02, 0x20, 0xfe, 0xf7, 
-0x0a, 0xfb, 0x08, 0x4b, 0x3a, 0x04, 0x12, 0x0c, 0x48, 0x21, 0x02, 0x20, 
-0xfe, 0xf7, 0x03, 0xfb, 0x3a, 0x0c, 0x04, 0x4b, 
-0x4a, 0x21, 0x02, 0x20, 0xfe, 0xf7, 0xfd, 0xfa, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x7b, 0xb7, 0x21, 0x40, 0x88, 0xb5, 0x11, 0x27, 
-0x3f, 0x04, 0x38, 0x62, 0x79, 0x62, 0xba, 0x62, 0xfb, 0x62, 0x04, 0x20, 
-0xff, 0xf7, 0xaa, 0xff, 0x07, 0x48, 0x40, 0x6b, 0xc0, 0x46, 0x00, 0x90, 
-0x00, 0x98, 0x80, 0x07, 0x80, 0x0f, 0x03, 0x28, 0x01, 0xd1, 0x01, 0x20, 
-0x00, 0xe0, 0x00, 0x20, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x11, 0x40, 0xf0, 0xb5, 0x8a, 0xb0, 0x00, 0x24, 0x05, 0x94, 
-0x69, 0x49, 0xc9, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x68, 0x4a, 0x11, 0x68, 
-0x01, 0x22, 0x12, 0x04, 0x0a, 0x40, 0x17, 0x21, 0x66, 0x4e, 0x00, 0x2a, 
-0x06, 0xd1, 0x64, 0x4a, 0x13, 0x68, 0x1b, 0x0c, 0x04, 0xd1, 0x12, 0x68, 
-0x92, 0x0a, 0x01, 0xd3, 0xf1, 0x60, 0x02, 0xe0, 0x61, 0x4a, 0xc0, 0x46, 
-0x11, 0x64, 0x61, 0x49, 0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x03, 0x29, 
-0x54, 0xd1, 0xe9, 0x21, 0x01, 0x91, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60, 
-0x06, 0x94, 0x06, 0x99, 0x8a, 0x00, 0x5b, 0x49, 0x8a, 0x58, 0x00, 0x2a, 
-0x73, 0xd0, 0x80, 0x20, 0x02, 0x90, 0x06, 0x98, 0x81, 0x00, 0x57, 0x48, 
-0x41, 0x58, 0x02, 0x9a, 0x11, 0x43, 0x02, 0x91, 0x00, 0x24, 0x00, 0x27, 
-0x25, 0x02, 0x28, 0x1c, 0x38, 0x43, 0x09, 0x90, 0x09, 0x98, 0x00, 0x04, 
-0x51, 0x4b, 0x18, 0x43, 0x04, 0x90, 0x09, 0x98, 0xef, 0x23, 0xdb, 0x05, 
-0x18, 0x43, 0x03, 0x90, 0x06, 0x98, 0x80, 0x00, 0x4b, 0x49, 0x08, 0x58, 
-0x00, 0x04, 0x03, 0x99, 0x08, 0x43, 0x03, 0x90, 0x00, 0x2f, 0x02, 0xd1, 
-0x03, 0x98, 0xc0, 0x46, 0x70, 0x60, 0x01, 0x9b, 0x03, 0x9a, 0x02, 0x99, 
-0x04, 0x98, 0xff, 0xf7, 0x89, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x02, 0x99, 
-0xc0, 0x46, 0xb1, 0x60, 0x03, 0x99, 0xc0, 0x46, 0x71, 0x60, 0x5c, 0xe0, 
-0x79, 0x1c, 0x0f, 0x04, 0x3f, 0x0c, 0x17, 0x2f, 0xd1, 0xdd, 0x61, 0x1c, 
-0x0c, 0x04, 0x24, 0x0c, 0x16, 0x2c, 0xca, 0xdd, 0x06, 0x99, 0x01, 0x31, 
-0x06, 0x91, 0x06, 0x99, 0x89, 0x00, 0x37, 0x4a, 0x51, 0x58, 0x00, 0x29, 
-0xb7, 0xd1, 0x48, 0xe0, 0xbf, 0x21, 0xc9, 0x43, 0x04, 0x91, 0xff, 0x21, 
-0x02, 0x91, 0x97, 0x21, 0x01, 0x91, 0x06, 0x94, 0x06, 0x99, 0x89, 0x00, 
-0x31, 0x4f, 0x79, 0x58, 0x00, 0x29, 0x1c, 0xd0, 0x09, 0x94, 0x08, 0x94, 
-0x06, 0x98, 0x80, 0x00, 0x38, 0x58, 0xc0, 0x46, 0x07, 0x90, 0x07, 0x98, 
-0x00, 0x04, 0x26, 0xe0, 0x05, 0x98, 0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 
-0x03, 0x90, 0x01, 0x9b, 0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7, 
-0x49, 0xff, 0x00, 0x28, 0x23, 0xd1, 0x09, 0x99, 0x01, 0x31, 0x09, 0x91, 
-0x17, 0x29, 0x06, 0xd8, 0x00, 0xe0, 0x1c, 0xe0, 0x08, 0x98, 0x00, 0x02, 
-0x09, 0x99, 0x08, 0x43, 0x07, 0xe0, 0x08, 0x99, 0x01, 0x31, 0x08, 0x91, 
-0x17, 0x29, 0x0a, 0xd8, 0x09, 0x94, 0x08, 0x98, 0x00, 0x02, 0x07, 0x99, 
-0x09, 0x04, 0x08, 0x43, 0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x05, 0x90, 
-0xd6, 0xe7, 0x06, 0x99, 0x01, 0x31, 0x06, 0x91, 0x06, 0x99, 0x89, 0x00, 
-0x79, 0x58, 0x00, 0x29, 0xc4, 0xd1, 0x0c, 0x4a, 0x11, 0x68, 0x49, 0x0c, 
-0x05, 0xd2, 0x11, 0x68, 0x09, 0x0c, 0x06, 0xd1, 0x11, 0x68, 0x89, 0x0a, 
-0x03, 0xd3, 0x00, 0x99, 0xc0, 0x46, 0xf1, 0x60, 0x03, 0xe0, 0x00, 0x99, 
-0x06, 0x4a, 0xc0, 0x46, 0x11, 0x64, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x40, 0x01, 0x18, 0x40, 
-0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 
-0x00, 0x00, 0x18, 0x40, 0x30, 0x6e, 0x21, 0x40, 0x43, 0xff, 0x00, 0x00, 
-0x0c, 0x6e, 0x21, 0x40, 0x80, 0xb5, 0x82, 0xb0, 0x00, 0x20, 0x01, 0x90, 
-0x1e, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x1b, 0xd1, 0x40, 0x88, 0x00, 0x28, 
-0x18, 0xd1, 0x68, 0x46, 0x01, 0xf0, 0x6a, 0xfe, 0x00, 0x28, 0x13, 0xd1, 
-0xa8, 0x20, 0x01, 0xf0, 0xab, 0xfe, 0x18, 0x4f, 0x00, 0x28, 0x11, 0xd0, 
-0x04, 0x20, 0xff, 0xf7, 0x97, 0xfe, 0x78, 0x6b, 0xc0, 0x46, 0x01, 0x90, 
-0x01, 0x98, 0x80, 0x07, 0x80, 0x0f, 0x03, 0x28, 0x06, 0xd1, 0x00, 0x20, 
-0x01, 0xf0, 0x9a, 0xfe, 0x02, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0xff, 0xf7, 0x8f, 0xfe, 
-0x00, 0x23, 0xdb, 0x43, 0x18, 0x1c, 0x19, 0x1c, 0x1a, 0x1c, 0xff, 0xf7, 
-0xc7, 0xfe, 0x00, 0x28, 0x03, 0xd1, 0xff, 0xf7, 0xdf, 0xfe, 0x00, 0x28, 
-0xe5, 0xd0, 0x38, 0x6a, 0x79, 0x6a, 0xba, 0x6a, 0xfb, 0x6a, 0xff, 0xf7, 
-0x7c, 0xfe, 0xde, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x00, 0x11, 0x40, 
-0xff, 0xb5, 0x85, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 
-0x01, 0x23, 0x5b, 0x04, 0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x82, 0xe0, 
-0x26, 0x1c, 0x43, 0x4d, 0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 
-0x09, 0x05, 0x41, 0x48, 0x41, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 
-0x06, 0x1c, 0x80, 0x2f, 0x00, 0xd8, 0x3d, 0x1c, 0x3e, 0x4a, 0x51, 0x69, 
-0xc0, 0x46, 0x03, 0x91, 0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0xff, 0x23, 
-0x01, 0x33, 0x19, 0x43, 0x39, 0x4b, 0xc0, 0x46, 0x59, 0x61, 0xff, 0x23, 
-0x01, 0x33, 0x9a, 0x43, 0x36, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 
-0x12, 0x05, 0xd1, 0x60, 0x33, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 
-0x11, 0x61, 0x31, 0x4a, 0xff, 0x23, 0x01, 0x33, 0x91, 0x69, 0x19, 0x43, 
-0x91, 0x61, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x85, 0x21, 0x89, 0x04, 
-0x04, 0x91, 0x00, 0x2f, 0x34, 0xd0, 0x28, 0x48, 0x86, 0x42, 0x04, 0xd1, 
-0x30, 0x1c, 0x21, 0x1c, 0x2a, 0x1c, 0x03, 0xf0, 0xd5, 0xfe, 0x2a, 0x1c, 
-0x04, 0x98, 0x02, 0x43, 0x00, 0x92, 0x01, 0x20, 0x06, 0x99, 0x05, 0x9a, 
-0x33, 0x1c, 0xfe, 0xf7, 0x5d, 0xf9, 0x22, 0x48, 0x22, 0x49, 0x4a, 0x68, 
-0x52, 0x0a, 0x09, 0xd3, 0xff, 0x21, 0x01, 0x31, 0x20, 0x4a, 0xc0, 0x46, 
-0x11, 0x60, 0x00, 0x28, 0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x13, 0xe0, 
-0x01, 0x38, 0xf0, 0xd1, 0xf9, 0xe7, 0x7f, 0x1b, 0x0e, 0xd0, 0x15, 0x48, 
-0x86, 0x42, 0x01, 0xd1, 0x64, 0x19, 0x00, 0xe0, 0x76, 0x19, 0x06, 0x99, 
-0x49, 0x19, 0x06, 0x91, 0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3, 0x28, 0x1c, 
-0x05, 0x1c, 0xca, 0xe7, 0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b, 0x19, 0x43, 
-0x41, 0x61, 0x82, 0x69, 0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 
-0x12, 0x05, 0xd1, 0x60, 0x81, 0x69, 0xc0, 0x46, 0x11, 0x61, 0x81, 0x69, 
-0x02, 0x9b, 0x19, 0x43, 0x81, 0x61, 0x11, 0x61, 0x01, 0x98, 0x09, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 
-0x50, 0xab, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 0xe8, 0x0d, 0x00, 0x80, 
+0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0xdb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x85, 0xb0, 
+0x01, 0xa9, 0xfe, 0xf7, 0xbb, 0xfd, 0x00, 0x20, 0x01, 0xab, 0x58, 0x70, 
+0x10, 0x49, 0xc9, 0x68, 0x01, 0x27, 0x01, 0x29, 0x0a, 0xd1, 0x04, 0xf0, 
+0xc7, 0xf8, 0x03, 0x90, 0x04, 0x97, 0x03, 0x98, 0x00, 0x28, 0x06, 0xd0, 
+0x68, 0x46, 0x02, 0xf0, 0xe5, 0xfb, 0x04, 0xe0, 0x03, 0x97, 0x04, 0x90, 
+0xf8, 0xe7, 0x00, 0x20, 0x00, 0x90, 0x02, 0xab, 0x00, 0x98, 0xc0, 0x46, 
+0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfe, 0xf7, 0xdb, 0xfc, 0x38, 0x1c, 
+0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 
+0x8d, 0xfd, 0x00, 0x20, 0x00, 0xab, 0x58, 0x70, 0x01, 0x24, 0x20, 0x1c, 
+0x12, 0x49, 0xc9, 0x68, 0x01, 0x29, 0x00, 0xd0, 0x00, 0x20, 0x00, 0x06, 
+0x00, 0x0e, 0x13, 0xd0, 0xf8, 0x88, 0x0f, 0x4a, 0x90, 0x42, 0x02, 0xd0, 
+0x0e, 0x4b, 0x98, 0x42, 0x08, 0xd1, 0xb9, 0x68, 0x27, 0x1c, 0x90, 0x42, 
+0x00, 0xd0, 0x00, 0x27, 0x38, 0x06, 0x00, 0x0e, 0x04, 0xf0, 0x88, 0xf8, 
+0x04, 0xf0, 0x84, 0xf8, 0x02, 0x90, 0x00, 0xe0, 0x02, 0x94, 0x68, 0x46, 
+0x00, 0x21, 0xfe, 0xf7, 0xa7, 0xfc, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xed, 0xfe, 0x00, 0x00, 
+0xfe, 0xca, 0x00, 0x00, 0xf1, 0xb5, 0xd6, 0xb0, 
+0x00, 0x20, 0x81, 0x00, 0x56, 0x9c, 0x0a, 0x19, 0x12, 0x6a, 0x6b, 0x46, 
+0x5a, 0x50, 0x01, 0x30, 0x10, 0x28, 0xf6, 0xdb, 0x10, 0x20, 0x82, 0x00, 
+0x11, 0x1c, 0x69, 0x44, 0x40, 0x39, 0x4b, 0x6b, 0x0f, 0x6a, 0x7b, 0x40, 
+0x8f, 0x68, 0x7b, 0x40, 0x09, 0x68, 0x59, 0x40, 0x4b, 0x00, 0xc9, 0x0f, 
+0x19, 0x43, 0x6b, 0x46, 0x99, 0x50, 0x01, 0x30, 0x50, 0x28, 0xec, 0xdb, 
+0x56, 0x98, 0x01, 0x68, 0xc0, 0x46, 0x55, 0x91, 0x42, 0x68, 0xc0, 0x46, 
+0x54, 0x92, 0x86, 0x68, 0xc0, 0x46, 0x53, 0x96, 0xc5, 0x68, 0xc0, 0x46, 
+0x52, 0x95, 0x04, 0x69, 0xc0, 0x46, 0x51, 0x94, 0x48, 0x01, 0xcb, 0x0e, 
+0x18, 0x43, 0x13, 0x1c, 0x33, 0x40, 0x07, 0x1c, 0x28, 0x1c, 0x90, 0x43, 
+0x18, 0x43, 0x38, 0x18, 0x00, 0x19, 0x00, 0x9b, 0xc0, 0x18, 0xcf, 0x4b, 
+0xc0, 0x18, 0x93, 0x07, 0x92, 0x08, 0x13, 0x43, 0x42, 0x01, 0x1f, 0x1c, 
+0xc3, 0x0e, 0x1a, 0x43, 0x0b, 0x1c, 0x3b, 0x40, 0x14, 0x1c, 0x32, 0x1c, 
+0x8a, 0x43, 0x1a, 0x43, 0xa2, 0x18, 0x52, 0x19, 0x01, 0x9b, 0xd2, 0x18, 
+0xc5, 0x4b, 0xd4, 0x18, 0x8a, 0x07, 0x89, 0x08, 0x11, 0x43, 0x62, 0x01, 
+0xe3, 0x0e, 0x1a, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x15, 0x1c, 0x3a, 0x1c, 
+0x82, 0x43, 0x1a, 0x43, 0xaa, 0x18, 0x92, 0x19, 0x02, 0x9b, 0xd2, 0x18, 
+0xbc, 0x4b, 0xd2, 0x18, 0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 
+0x57, 0x01, 0xd5, 0x0e, 0x3d, 0x43, 0x27, 0x1c, 0x07, 0x40, 0x0e, 0x1c, 
+0xa6, 0x43, 0x37, 0x43, 0xed, 0x19, 0xeb, 0x18, 0x03, 0x9f, 0xdf, 0x19, 
+0xb3, 0x4b, 0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 
+0xfd, 0x0e, 0x2b, 0x43, 0x15, 0x1c, 0x25, 0x40, 0x1e, 0x1c, 0x03, 0x1c, 
+0x93, 0x43, 0x2b, 0x43, 0xf3, 0x18, 0x59, 0x18, 0x04, 0x9b, 0xc9, 0x18, 
+0xaa, 0x4b, 0xc9, 0x18, 0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 
+0xcd, 0x0e, 0x1d, 0x43, 0x3e, 0x1c, 0x16, 0x40, 0x23, 0x1c, 0xbb, 0x43, 
+0x33, 0x43, 0xeb, 0x18, 0x18, 0x18, 0x05, 0x9b, 0xc0, 0x18, 0xa2, 0x4b, 
+0xc0, 0x18, 0xbb, 0x07, 0xbf, 0x08, 0x1f, 0x43, 0x43, 0x01, 0xc5, 0x0e, 
+0x2b, 0x43, 0x0d, 0x1c, 0x3d, 0x40, 0x1e, 0x1c, 0x13, 0x1c, 0x8b, 0x43, 
+0x2b, 0x43, 0xf3, 0x18, 0x1b, 0x19, 0x06, 0x9c, 0x1c, 0x19, 0x99, 0x4b, 
+0xe4, 0x18, 0x8b, 0x07, 0x89, 0x08, 0x19, 0x43, 0x63, 0x01, 0xe5, 0x0e, 
+0x1d, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x3e, 0x1c, 0x86, 0x43, 0x33, 0x43, 
+0xeb, 0x18, 0x9a, 0x18, 0x07, 0x9b, 0xd2, 0x18, 0x90, 0x4b, 0xd2, 0x18, 
+0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 0x57, 0x01, 0xd5, 0x0e, 
+0x2f, 0x43, 0x25, 0x1c, 0x05, 0x40, 0x3e, 0x1c, 0x0f, 0x1c, 0xa7, 0x43, 
+0x2f, 0x43, 0xf5, 0x19, 0xeb, 0x18, 0x08, 0x9f, 0xdf, 0x19, 0x87, 0x4b, 
+0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 0xfd, 0x0e, 
+0x1d, 0x43, 0x16, 0x1c, 0x26, 0x40, 0x03, 0x1c, 0x93, 0x43, 0x33, 0x43, 
+0xeb, 0x18, 0x59, 0x18, 0x09, 0x9b, 0xc9, 0x18, 0x7e, 0x4b, 0xc9, 0x18, 
+0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 0xcd, 0x0e, 0x1d, 0x43, 
+0x3b, 0x1c, 0x13, 0x40, 0x26, 0x1c, 0xbe, 0x43, 0x33, 0x43, 0xeb, 0x18, 
+0x18, 0x18, 0x0a, 0x9b, 0xc0, 0x18, 0x76, 0x4b, 0xc0, 0x18, 0x23, 0x1c, 
+0xbc, 0x07, 0xbf, 0x08, 0x27, 0x43, 0x44, 0x01, 0xc5, 0x0e, 0x2c, 0x43, 
+0x0d, 0x1c, 0x3d, 0x40, 0x26, 0x1c, 0x14, 0x1c, 0x8c, 0x43, 0x2c, 0x43, 
+0x35, 0x19, 0xeb, 0x18, 0x0b, 0x9c, 0x1c, 0x19, 
+0x6c, 0x4b, 0xe4, 0x18, 0x8b, 0x07, 0x89, 0x08, 0x19, 0x43, 0x63, 0x01, 
+0xe5, 0x0e, 0x1d, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x3e, 0x1c, 0x86, 0x43, 
+0x33, 0x43, 0xeb, 0x18, 0x9a, 0x18, 0x0c, 0x9b, 0xd2, 0x18, 0x64, 0x4b, 
+0xd2, 0x18, 0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 0x57, 0x01, 
+0xd5, 0x0e, 0x3d, 0x43, 0x27, 0x1c, 0x07, 0x40, 0x0e, 0x1c, 0xa6, 0x43, 
+0x37, 0x43, 0xed, 0x19, 0xeb, 0x18, 0x0d, 0x9f, 0xdf, 0x19, 0x5b, 0x4b, 
+0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 0xfd, 0x0e, 
+0x1d, 0x43, 0x13, 0x1c, 0x23, 0x40, 0x06, 0x1c, 0x96, 0x43, 0x33, 0x43, 
+0xeb, 0x18, 0x59, 0x18, 0x0e, 0x9b, 0xc9, 0x18, 0x52, 0x4b, 0xc9, 0x18, 
+0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 0xcd, 0x0e, 0x2b, 0x43, 
+0x3d, 0x1c, 0x15, 0x40, 0x1e, 0x1c, 0x23, 0x1c, 0xbb, 0x43, 0x2b, 0x43, 
+0xf3, 0x18, 0x18, 0x18, 0x0f, 0x9b, 0xc0, 0x18, 0x49, 0x4b, 0xc0, 0x18, 
+0x23, 0x1c, 0xbc, 0x07, 0xbf, 0x08, 0x27, 0x43, 0x10, 0x24, 0x50, 0x94, 
+0x44, 0x01, 0xc5, 0x0e, 0x25, 0x43, 0x0e, 0x1c, 0x3e, 0x40, 0x14, 0x1c, 
+0x8c, 0x43, 0x34, 0x43, 0x2c, 0x19, 0xe3, 0x18, 0x50, 0x9c, 0xa5, 0x00, 
+0x6c, 0x46, 0x64, 0x59, 0x1c, 0x19, 0x3e, 0x4b, 0xe4, 0x18, 0x13, 0x1c, 
+0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 0x0f, 0x43, 0x01, 0x1c, 0x20, 0x1c, 
+0x50, 0x9c, 0x01, 0x34, 0x50, 0x94, 0x14, 0x2c, 0xe2, 0xdb, 0x14, 0x24, 
+0x45, 0x01, 0xc6, 0x0e, 0x2e, 0x43, 0x0d, 0x1c, 0x7d, 0x40, 0x55, 0x40, 
+0x75, 0x19, 0xeb, 0x18, 0xa5, 0x00, 0x6e, 0x46, 0x75, 0x59, 0x5d, 0x19, 
+0x31, 0x4b, 0xed, 0x18, 0x13, 0x1c, 0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 
+0x0f, 0x43, 0x01, 0x1c, 0x28, 0x1c, 0x01, 0x34, 0x28, 0x2c, 0xe7, 0xdb, 
+0x28, 0x24, 0x50, 0x94, 0x44, 0x01, 0xc5, 0x0e, 0x25, 0x43, 0x3c, 0x1c, 
+0x14, 0x43, 0x0c, 0x40, 0x3e, 0x1c, 0x16, 0x40, 0x34, 0x43, 0x2c, 0x19, 
+0xe3, 0x18, 0x50, 0x9c, 0xa5, 0x00, 0x6c, 0x46, 0x64, 0x59, 0x1c, 0x19, 
+0x23, 0x4b, 0xe4, 0x18, 0x13, 0x1c, 0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 
+0x0f, 0x43, 0x01, 0x1c, 0x20, 0x1c, 0x50, 0x9c, 0x01, 0x34, 0x50, 0x94, 
+0x3c, 0x2c, 0xe1, 0xdb, 0x3c, 0x24, 0x45, 0x01, 0xc6, 0x0e, 0x2e, 0x43, 
+0x0d, 0x1c, 0x7d, 0x40, 0x55, 0x40, 0x75, 0x19, 0xeb, 0x18, 0xa6, 0x00, 
+0x6d, 0x46, 0xad, 0x59, 0x5d, 0x19, 0x17, 0x4b, 0xed, 0x18, 0x13, 0x1c, 
+0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 0x0f, 0x43, 0x01, 0x1c, 0x28, 0x1c, 
+0x01, 0x34, 0x50, 0x2c, 0xe7, 0xdb, 0x55, 0x9c, 0x20, 0x18, 0x56, 0x9c, 
+0xc0, 0x46, 0x20, 0x60, 0x54, 0x98, 0x40, 0x18, 0x56, 0x9c, 0xc0, 0x46, 
+0x60, 0x60, 0x53, 0x9e, 0xf0, 0x19, 0x56, 0x9c, 0xc0, 0x46, 0xa0, 0x60, 
+0x52, 0x9d, 0xa8, 0x18, 0x56, 0x9c, 0xc0, 0x46, 0xe0, 0x60, 0x51, 0x9c, 
+0xe0, 0x18, 0x56, 0x9c, 0xc0, 0x46, 0x20, 0x61, 0x57, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x99, 0x79, 0x82, 0x5a, 0xa1, 0xeb, 0xd9, 0x6e, 
+0xdc, 0xbc, 0x1b, 0x8f, 0xd6, 0xc1, 0x62, 0xca, 0x88, 0xb4, 0x8a, 0x08, 
+0x89, 0x07, 0x00, 0xd0, 0x01, 0x32, 0x00, 0x21, 0x00, 0x2a, 0x1e, 0xdd, 
+0x07, 0x78, 0x00, 0xab, 0x1f, 0x70, 0x47, 0x78, 0xc0, 0x46, 0x5f, 0x70, 
+0x87, 0x78, 0xc0, 0x46, 0x9f, 0x70, 0xc7, 0x78, 0xc0, 0x46, 0xdf, 0x70, 
+0xdb, 0x78, 0xc0, 0x46, 0x03, 0x70, 0x00, 0xab, 0x9b, 0x78, 0xc0, 0x46, 
+0x43, 0x70, 0x00, 0xab, 0x5b, 0x78, 0xc0, 0x46, 
+0x83, 0x70, 0x00, 0xab, 0x1b, 0x78, 0xc0, 0x46, 0xc3, 0x70, 0x04, 0x30, 
+0x01, 0x31, 0x91, 0x42, 0xe0, 0xdb, 0x88, 0xbc, 0x70, 0x47, 0x00, 0x21, 
+0xc1, 0x61, 0x09, 0x4a, 0xc0, 0x46, 0x02, 0x60, 0x08, 0x4a, 0xc0, 0x46, 
+0x42, 0x60, 0x08, 0x4a, 0xc0, 0x46, 0x82, 0x60, 0x07, 0x4a, 0xc0, 0x46, 
+0xc2, 0x60, 0x07, 0x4a, 0xc0, 0x46, 0x02, 0x61, 0x41, 0x61, 0x81, 0x61, 
+0x70, 0x47, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 
+0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf0, 0xe1, 0xd2, 0xc3, 
+0xf0, 0xb5, 0x14, 0x1c, 0x0d, 0x1c, 0x07, 0x1c, 0xe1, 0x00, 0x78, 0x69, 
+0x41, 0x18, 0x81, 0x42, 0x02, 0xd2, 0xb8, 0x69, 0x01, 0x30, 0xb8, 0x61, 
+0x79, 0x61, 0x61, 0x0f, 0xb8, 0x69, 0x40, 0x18, 0xb8, 0x61, 0x40, 0x2c, 
+0x14, 0xdb, 0xfe, 0x1d, 0x19, 0x36, 0x00, 0x20, 0x29, 0x78, 0x3a, 0x18, 
+0x20, 0x32, 0x11, 0x70, 0x01, 0x35, 0x01, 0x30, 0x40, 0x28, 0xf7, 0xd3, 
+0x40, 0x21, 0x30, 0x1c, 0xff, 0xf7, 0x96, 0xff, 0x38, 0x1c, 0xff, 0xf7, 
+0xaf, 0xfd, 0x40, 0x3c, 0x40, 0x2c, 0xec, 0xda, 0x00, 0x20, 0x00, 0x2c, 
+0x07, 0xd9, 0x29, 0x78, 0x3a, 0x18, 0x20, 0x32, 0x11, 0x70, 0x01, 0x35, 
+0x01, 0x30, 0xa0, 0x42, 0xf7, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xf8, 0xb5, 0x07, 0x1c, 0xd3, 0x00, 0x78, 0x69, 0xc6, 0x18, 0x86, 0x42, 
+0x02, 0xd2, 0xb8, 0x69, 0x01, 0x30, 0xb8, 0x61, 0x7e, 0x61, 0x53, 0x0f, 
+0xb8, 0x69, 0xc0, 0x18, 0xb8, 0x61, 0x00, 0x90, 0x00, 0x20, 0x00, 0x2a, 
+0x07, 0xdd, 0x0b, 0x78, 0x3c, 0x18, 0x20, 0x34, 0x23, 0x70, 0x01, 0x31, 
+0x01, 0x30, 0x90, 0x42, 0xf7, 0xdb, 0x80, 0x20, 0xd1, 0x19, 0x20, 0x31, 
+0x08, 0x70, 0x54, 0x1c, 0xfd, 0x1d, 0x19, 0x35, 0x38, 0x2c, 0x1c, 0xdd, 
+0x38, 0x19, 0x20, 0x30, 0x00, 0x21, 0x40, 0x22, 0x12, 0x1b, 0x00, 0x2a, 
+0x05, 0xdd, 0x00, 0x23, 0x03, 0x70, 0x01, 0x30, 0x01, 0x31, 0x8a, 0x42, 
+0xfa, 0xdc, 0x28, 0x1c, 0x21, 0x1c, 0xff, 0xf7, 0x4d, 0xff, 0x38, 0x1c, 
+0xff, 0xf7, 0x66, 0xfd, 0x28, 0x1c, 0x00, 0x21, 0x00, 0x23, 0x03, 0x70, 
+0x01, 0x30, 0x01, 0x31, 0x38, 0x29, 0xfa, 0xdb, 0x0c, 0xe0, 0x38, 0x19, 
+0x20, 0x30, 0x00, 0x21, 0x38, 0x22, 0x12, 0x1b, 0x00, 0x2a, 0x05, 0xdd, 
+0x00, 0x23, 0x03, 0x70, 0x01, 0x30, 0x01, 0x31, 0x8a, 0x42, 0xfa, 0xdc, 
+0x28, 0x1c, 0x21, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x00, 0x98, 0xc0, 0x46, 
+0xb8, 0x65, 0xfe, 0x65, 0x38, 0x1c, 0xff, 0xf7, 0x45, 0xfd, 0x01, 0x20, 
+0xf8, 0x61, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x0c, 0x1c, 
+0x05, 0x1c, 0x17, 0x1c, 0x38, 0x1c, 0x00, 0x2f, 0x04, 0xda, 0x40, 0x42, 
+0x80, 0x06, 0x80, 0x0e, 0x40, 0x42, 0x01, 0xe0, 0x80, 0x06, 0x80, 0x0e, 
+0x00, 0x28, 0x07, 0xd1, 0x28, 0x1c, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 
+0x57, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0x00, 0x2f, 
+0x00, 0xda, 0x3f, 0x30, 0x80, 0x11, 0x00, 0x28, 0x07, 0xdd, 0x86, 0x01, 
+0x28, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 0xff, 0xf7, 0x47, 0xff, 0xa4, 0x19, 
+0xbf, 0x1b, 0x00, 0x2f, 0xeb, 0xd0, 0x28, 0x1c, 0x21, 0x1c, 0x3a, 0x1c, 
+0xff, 0xf7, 0x74, 0xff, 0xe5, 0xe7, 0x98, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 
+0x30, 0x20, 0x00, 0xab, 0x18, 0x70, 0xf8, 0x69, 0x00, 0x28, 0x04, 0xd1, 
+0x69, 0x46, 0x00, 0x22, 0x38, 0x1c, 0xff, 0xf7, 0x65, 0xff, 0x14, 0x21, 
+0x38, 0x1c, 0xff, 0xf7, 0xe3, 0xfe, 0x00, 0x20, 
+0x81, 0x00, 0x79, 0x58, 0x02, 0xc4, 0x01, 0x30, 0x05, 0x28, 0xf9, 0xdb, 
+0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0x98, 0xb0, 0x07, 0x1c, 
+0x78, 0x68, 0x40, 0x28, 0x10, 0xd9, 0x68, 0x46, 0xff, 0xf7, 0xf9, 0xfe, 
+0x68, 0x46, 0x06, 0xcf, 0x08, 0x3f, 0xff, 0xf7, 0xa7, 0xff, 0xf8, 0x1d, 
+0xc5, 0x30, 0x69, 0x46, 0x04, 0x1c, 0xff, 0xf7, 0xd0, 0xff, 0x14, 0x20, 
+0x78, 0x60, 0x3c, 0x60, 0x00, 0x20, 0x00, 0x24, 0x39, 0x18, 0xca, 0x1d, 
+0x39, 0x32, 0x14, 0x72, 0x80, 0x31, 0x4c, 0x72, 0x7b, 0x68, 0x83, 0x42, 
+0x06, 0xd9, 0x3b, 0x68, 0x5d, 0x1c, 0x3d, 0x60, 0x1b, 0x78, 0xc0, 0x46, 
+0x13, 0x72, 0x4b, 0x72, 0x15, 0x7a, 0x36, 0x23, 0x6b, 0x40, 0x13, 0x72, 
+0x4a, 0x7a, 0x5c, 0x23, 0x5a, 0x40, 0x4a, 0x72, 0x01, 0x30, 0x40, 0x28, 
+0xe4, 0xd3, 0x18, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf7, 0xb5, 
+0xe0, 0xb0, 0x14, 0x1c, 0x0f, 0x1c, 0x00, 0x25, 0xae, 0x00, 0x01, 0x20, 
+0xf1, 0x1d, 0x1d, 0x31, 0x02, 0xf0, 0x10, 0xfe, 0x01, 0x04, 0x00, 0x91, 
+0x01, 0x20, 0xf1, 0x1d, 0x1b, 0x31, 0x02, 0xf0, 0x09, 0xfe, 0x00, 0x99, 
+0x08, 0x43, 0x19, 0xa9, 0x71, 0x18, 0x88, 0x60, 0x01, 0x35, 0x10, 0x2d, 
+0xea, 0xd3, 0x1b, 0xa8, 0x19, 0x90, 0x40, 0x20, 0x1a, 0x90, 0x19, 0xa8, 
+0xff, 0xf7, 0xa7, 0xff, 0x01, 0xa8, 0xff, 0xf7, 0xa6, 0xfe, 0x40, 0x22, 
+0x01, 0xa8, 0x2b, 0xa9, 0xff, 0xf7, 0x54, 0xff, 0x00, 0x2f, 0x0b, 0xd0, 
+0x40, 0x2f, 0x01, 0xd9, 0x40, 0x25, 0x00, 0xe0, 0x3d, 0x1c, 0x60, 0x99, 
+0x01, 0xa8, 0x2a, 0x1c, 0xff, 0xf7, 0x48, 0xff, 0x7f, 0x1b, 0xf3, 0xd1, 
+0x51, 0xa8, 0x01, 0xa9, 0x07, 0x1c, 0xff, 0xf7, 0x70, 0xff, 0x01, 0xa8, 
+0xff, 0xf7, 0x8b, 0xfe, 0x40, 0x22, 0x01, 0xa8, 0x3b, 0xa9, 0x01, 0x31, 
+0xff, 0xf7, 0x38, 0xff, 0x14, 0x22, 0x01, 0xa8, 0x39, 0x1c, 0xff, 0xf7, 
+0x33, 0xff, 0x56, 0xa8, 0x01, 0xa9, 0xff, 0xf7, 0x5e, 0xff, 0x00, 0x20, 
+0x82, 0x00, 0x19, 0xa9, 0x51, 0x18, 0xc0, 0x31, 0x49, 0x6b, 0x02, 0xc4, 
+0x01, 0x30, 0x05, 0x28, 0xf6, 0xd3, 0x63, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c, 0x00, 0x24, 0x00, 0x2f, 
+0x04, 0xd3, 0x04, 0xf0, 0x15, 0xf9, 0x01, 0x34, 0xbc, 0x42, 0xfa, 0xd9, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x14, 0x1c, 0x0d, 0x1c, 
+0x06, 0x1c, 0x1f, 0x1c, 0x1b, 0x4b, 0x32, 0x04, 0x12, 0x0c, 0x3c, 0x21, 
+0x02, 0x20, 0xfd, 0xf7, 0x8a, 0xff, 0x32, 0x0c, 0x17, 0x4b, 0x3e, 0x21, 
+0x02, 0x20, 0xfd, 0xf7, 0x84, 0xff, 0x15, 0x4b, 0x2a, 0x04, 0x12, 0x0c, 
+0x40, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x7d, 0xff, 0x2a, 0x0c, 0x11, 0x4b, 
+0x42, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x77, 0xff, 0x0e, 0x4b, 0x22, 0x04, 
+0x12, 0x0c, 0x44, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x70, 0xff, 0x22, 0x0c, 
+0x0a, 0x4b, 0x46, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x6a, 0xff, 0x08, 0x4b, 
+0x3a, 0x04, 0x12, 0x0c, 0x48, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x63, 0xff, 
+0x3a, 0x0c, 0x04, 0x4b, 0x4a, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x5d, 0xff, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xd9, 0xbf, 0x21, 0x40, 
+0x88, 0xb5, 0x11, 0x27, 0x3f, 0x04, 0x38, 0x62, 0x79, 0x62, 0xba, 0x62, 
+0xfb, 0x62, 0x04, 0x20, 0xff, 0xf7, 0xaa, 0xff, 0x07, 0x48, 0x40, 0x6b, 
+0xc0, 0x46, 0x00, 0x90, 0x00, 0x98, 0x80, 0x07, 0x80, 0x0f, 0x03, 0x28, 
+0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 
+0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 
+0xf0, 0xb5, 0x8a, 0xb0, 0x00, 0x24, 0x05, 0x94, 0x69, 0x49, 0xc9, 0x68, 
+0xc0, 0x46, 0x00, 0x91, 0x68, 0x4a, 0x11, 0x68, 0x01, 0x22, 0x12, 0x04, 
+0x0a, 0x40, 0x17, 0x21, 0x66, 0x4e, 0x00, 0x2a, 0x06, 0xd1, 0x64, 0x4a, 
+0x13, 0x68, 0x1b, 0x0c, 0x04, 0xd1, 0x12, 0x68, 0x92, 0x0a, 0x01, 0xd3, 
+0xf1, 0x60, 0x02, 0xe0, 0x61, 0x4a, 0xc0, 0x46, 0x11, 0x64, 0x61, 0x49, 
+0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x03, 0x29, 0x54, 0xd1, 0xe9, 0x21, 
+0x01, 0x91, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60, 0x06, 0x94, 0x06, 0x99, 
+0x8a, 0x00, 0x5b, 0x49, 0x8a, 0x58, 0x00, 0x2a, 0x73, 0xd0, 0x80, 0x20, 
+0x02, 0x90, 0x06, 0x98, 0x81, 0x00, 0x57, 0x48, 0x41, 0x58, 0x02, 0x9a, 
+0x11, 0x43, 0x02, 0x91, 0x00, 0x24, 0x00, 0x27, 0x25, 0x02, 0x28, 0x1c, 
+0x38, 0x43, 0x09, 0x90, 0x09, 0x98, 0x00, 0x04, 0x51, 0x4b, 0x18, 0x43, 
+0x04, 0x90, 0x09, 0x98, 0xef, 0x23, 0xdb, 0x05, 0x18, 0x43, 0x03, 0x90, 
+0x06, 0x98, 0x80, 0x00, 0x4b, 0x49, 0x08, 0x58, 0x00, 0x04, 0x03, 0x99, 
+0x08, 0x43, 0x03, 0x90, 0x00, 0x2f, 0x02, 0xd1, 0x03, 0x98, 0xc0, 0x46, 
+0x70, 0x60, 0x01, 0x9b, 0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7, 
+0x89, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60, 
+0x03, 0x99, 0xc0, 0x46, 0x71, 0x60, 0x5c, 0xe0, 0x79, 0x1c, 0x0f, 0x04, 
+0x3f, 0x0c, 0x17, 0x2f, 0xd1, 0xdd, 0x61, 0x1c, 0x0c, 0x04, 0x24, 0x0c, 
+0x16, 0x2c, 0xca, 0xdd, 0x06, 0x99, 0x01, 0x31, 0x06, 0x91, 0x06, 0x99, 
+0x89, 0x00, 0x37, 0x4a, 0x51, 0x58, 0x00, 0x29, 0xb7, 0xd1, 0x48, 0xe0, 
+0xbf, 0x21, 0xc9, 0x43, 0x04, 0x91, 0xff, 0x21, 0x02, 0x91, 0x97, 0x21, 
+0x01, 0x91, 0x06, 0x94, 0x06, 0x99, 0x89, 0x00, 0x31, 0x4f, 0x79, 0x58, 
+0x00, 0x29, 0x1c, 0xd0, 0x09, 0x94, 0x08, 0x94, 0x06, 0x98, 0x80, 0x00, 
+0x38, 0x58, 0xc0, 0x46, 0x07, 0x90, 0x07, 0x98, 0x00, 0x04, 0x26, 0xe0, 
+0x05, 0x98, 0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x03, 0x90, 0x01, 0x9b, 
+0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7, 0x49, 0xff, 0x00, 0x28, 
+0x23, 0xd1, 0x09, 0x99, 0x01, 0x31, 0x09, 0x91, 0x17, 0x29, 0x06, 0xd8, 
+0x00, 0xe0, 0x1c, 0xe0, 0x08, 0x98, 0x00, 0x02, 0x09, 0x99, 0x08, 0x43, 
+0x07, 0xe0, 0x08, 0x99, 0x01, 0x31, 0x08, 0x91, 0x17, 0x29, 0x0a, 0xd8, 
+0x09, 0x94, 0x08, 0x98, 0x00, 0x02, 0x07, 0x99, 0x09, 0x04, 0x08, 0x43, 
+0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x05, 0x90, 0xd6, 0xe7, 0x06, 0x99, 
+0x01, 0x31, 0x06, 0x91, 0x06, 0x99, 0x89, 0x00, 0x79, 0x58, 0x00, 0x29, 
+0xc4, 0xd1, 0x0c, 0x4a, 0x11, 0x68, 0x49, 0x0c, 0x05, 0xd2, 0x11, 0x68, 
+0x09, 0x0c, 0x06, 0xd1, 0x11, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x00, 0x99, 
+0xc0, 0x46, 0xf1, 0x60, 0x03, 0xe0, 0x00, 0x99, 0x06, 0x4a, 0xc0, 0x46, 
+0x11, 0x64, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x40, 0x01, 0x18, 0x40, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x18, 0x40, 0x30, 0x6e, 0x21, 0x40, 
+0x43, 0xff, 0x00, 0x00, 0x0c, 0x6e, 0x21, 0x40, 0x80, 0xb5, 0x82, 0xb0, 
+0x00, 0x20, 0x01, 0x90, 0x1e, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x1b, 0xd1, 
+0x40, 0x88, 0x00, 0x28, 0x18, 0xd1, 0x68, 0x46, 0x01, 0xf0, 0x9a, 0xfe, 
+0x00, 0x28, 0x13, 0xd1, 0xa8, 0x20, 0x01, 0xf0, 
+0xdb, 0xfe, 0x18, 0x4f, 0x00, 0x28, 0x11, 0xd0, 0x04, 0x20, 0xff, 0xf7, 
+0x97, 0xfe, 0x78, 0x6b, 0xc0, 0x46, 0x01, 0x90, 0x01, 0x98, 0x80, 0x07, 
+0x80, 0x0f, 0x03, 0x28, 0x06, 0xd1, 0x00, 0x20, 0x01, 0xf0, 0xca, 0xfe, 
+0x02, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x23, 0x00, 0x22, 
+0x00, 0x21, 0x00, 0x20, 0xff, 0xf7, 0x8f, 0xfe, 0x00, 0x23, 0xdb, 0x43, 
+0x18, 0x1c, 0x19, 0x1c, 0x1a, 0x1c, 0xff, 0xf7, 0xc7, 0xfe, 0x00, 0x28, 
+0x03, 0xd1, 0xff, 0xf7, 0xdf, 0xfe, 0x00, 0x28, 0xe5, 0xd0, 0x38, 0x6a, 
+0x79, 0x6a, 0xba, 0x6a, 0xfb, 0x6a, 0xff, 0xf7, 0x7c, 0xfe, 0xde, 0xe7, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x11, 0x40, 0xff, 0xb5, 0x85, 0xb0, 
+0x14, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x01, 0x23, 0x5b, 0x04, 
+0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x82, 0xe0, 0x26, 0x1c, 0x43, 0x4d, 
+0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x41, 0x48, 
+0x41, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f, 
+0x00, 0xd8, 0x3d, 0x1c, 0x3e, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91, 
+0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0xff, 0x23, 0x01, 0x33, 0x19, 0x43, 
+0x39, 0x4b, 0xc0, 0x46, 0x59, 0x61, 0xff, 0x23, 0x01, 0x33, 0x9a, 0x43, 
+0x36, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 
+0x33, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x31, 0x4a, 
+0xff, 0x23, 0x01, 0x33, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 0x01, 0x22, 
+0x12, 0x05, 0x11, 0x61, 0x85, 0x21, 0x89, 0x04, 0x04, 0x91, 0x00, 0x2f, 
+0x34, 0xd0, 0x28, 0x48, 0x86, 0x42, 0x04, 0xd1, 0x30, 0x1c, 0x21, 0x1c, 
+0x2a, 0x1c, 0x03, 0xf0, 0x4f, 0xff, 0x2a, 0x1c, 0x04, 0x98, 0x02, 0x43, 
+0x00, 0x92, 0x01, 0x20, 0x06, 0x99, 0x05, 0x9a, 0x33, 0x1c, 0xfd, 0xf7, 
+0xbd, 0xfd, 0x22, 0x48, 0x22, 0x49, 0x4a, 0x68, 0x52, 0x0a, 0x09, 0xd3, 
+0xff, 0x21, 0x01, 0x31, 0x20, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x00, 0x28, 
+0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x13, 0xe0, 0x01, 0x38, 0xf0, 0xd1, 
+0xf9, 0xe7, 0x7f, 0x1b, 0x0e, 0xd0, 0x15, 0x48, 0x86, 0x42, 0x01, 0xd1, 
+0x64, 0x19, 0x00, 0xe0, 0x76, 0x19, 0x06, 0x99, 0x49, 0x19, 0x06, 0x91, 
+0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3, 0x28, 0x1c, 0x05, 0x1c, 0xca, 0xe7, 
+0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 
+0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 
+0x81, 0x69, 0xc0, 0x46, 0x11, 0x61, 0x81, 0x69, 0x02, 0x9b, 0x19, 0x43, 
+0x81, 0x61, 0x11, 0x61, 0x01, 0x98, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x50, 0xab, 0x20, 0x40, 
+0x00, 0x00, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
+0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0xb0, 0xff, 0xb5, 0x85, 0xb0, 
+0x04, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x01, 0x23, 0x5b, 0x04, 
+0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x7d, 0xe0, 0x26, 0x1c, 0x40, 0x4d, 
+0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x3e, 0x48, 
+0x3e, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f, 
+0x00, 0xd8, 0x3d, 0x1c, 0x3b, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91, 
+0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0x10, 0x23, 0x19, 0x43, 0x37, 0x4b, 
+0xc0, 0x46, 0x59, 0x61, 0x10, 0x23, 0x9a, 0x43, 
+0x34, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 
+0x31, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x2f, 0x4a, 
+0x10, 0x23, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 0x1a, 0x04, 0x11, 0x61, 
+0x21, 0x21, 0x09, 0x05, 0x04, 0x91, 0x00, 0x2f, 0x33, 0xd0, 0x2a, 0x1c, 
+0x04, 0x98, 0x02, 0x43, 0x00, 0x92, 0x00, 0x20, 0x06, 0x99, 0x07, 0x9a, 
+0x33, 0x1c, 0xfd, 0xf7, 0x27, 0xfd, 0x25, 0x48, 0x25, 0x49, 0x4a, 0x68, 
+0x52, 0x09, 0x08, 0xd3, 0x10, 0x21, 0x24, 0x4a, 0xc0, 0x46, 0x11, 0x60, 
+0x00, 0x28, 0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x1b, 0xe0, 0x01, 0x38, 
+0xf1, 0xd1, 0xf9, 0xe7, 0x19, 0x48, 0x86, 0x42, 0x04, 0xd1, 0x20, 0x1c, 
+0x31, 0x1c, 0x2a, 0x1c, 0x03, 0xf0, 0x96, 0xfe, 0x7f, 0x1b, 0x0e, 0xd0, 
+0x14, 0x48, 0x86, 0x42, 0x01, 0xd0, 0x76, 0x19, 0x00, 0xe0, 0x64, 0x19, 
+0x06, 0x99, 0x49, 0x19, 0x06, 0x91, 0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3, 
+0x28, 0x1c, 0x05, 0x1c, 0xcb, 0xe7, 0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b, 
+0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61, 
+0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x81, 0x69, 0xc0, 0x46, 0x11, 0x61, 
+0x81, 0x69, 0x02, 0x9b, 0x19, 0x43, 0x81, 0x61, 0x11, 0x61, 0x01, 0x98, 
+0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xff, 0x00, 0x00, 
+0x50, 0xab, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 
 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0xb0, 
-0xff, 0xb5, 0x85, 0xb0, 0x04, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 
-0x01, 0x23, 0x5b, 0x04, 0x9f, 0x42, 0x01, 0xd9, 
-0x0f, 0x20, 0x7d, 0xe0, 0x26, 0x1c, 0x40, 0x4d, 0xaf, 0x42, 0x00, 0xd2, 
-0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x3e, 0x48, 0x3e, 0x4b, 0x99, 0x42, 
-0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f, 0x00, 0xd8, 0x3d, 0x1c, 
-0x3b, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91, 0x92, 0x69, 0xc0, 0x46, 
-0x02, 0x92, 0x10, 0x23, 0x19, 0x43, 0x37, 0x4b, 0xc0, 0x46, 0x59, 0x61, 
-0x10, 0x23, 0x9a, 0x43, 0x34, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 
-0x12, 0x05, 0xd1, 0x60, 0x31, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 
-0x11, 0x61, 0x2f, 0x4a, 0x10, 0x23, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 
-0x1a, 0x04, 0x11, 0x61, 0x21, 0x21, 0x09, 0x05, 0x04, 0x91, 0x00, 0x2f, 
-0x33, 0xd0, 0x2a, 0x1c, 0x04, 0x98, 0x02, 0x43, 0x00, 0x92, 0x00, 0x20, 
-0x06, 0x99, 0x07, 0x9a, 0x33, 0x1c, 0xfe, 0xf7, 0xc7, 0xf8, 0x25, 0x48, 
-0x25, 0x49, 0x4a, 0x68, 0x52, 0x09, 0x08, 0xd3, 0x10, 0x21, 0x24, 0x4a, 
-0xc0, 0x46, 0x11, 0x60, 0x00, 0x28, 0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 
-0x1b, 0xe0, 0x01, 0x38, 0xf1, 0xd1, 0xf9, 0xe7, 0x19, 0x48, 0x86, 0x42, 
-0x04, 0xd1, 0x20, 0x1c, 0x31, 0x1c, 0x2a, 0x1c, 0x03, 0xf0, 0x1c, 0xfe, 
-0x7f, 0x1b, 0x0e, 0xd0, 0x14, 0x48, 0x86, 0x42, 0x01, 0xd0, 0x76, 0x19, 
-0x00, 0xe0, 0x64, 0x19, 0x06, 0x99, 0x49, 0x19, 0x06, 0x91, 0x38, 0x1c, 
-0xaf, 0x42, 0x00, 0xd3, 0x28, 0x1c, 0x05, 0x1c, 0xcb, 0xe7, 0x0f, 0x48, 
-0x41, 0x69, 0x03, 0x9b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 0x03, 0x9b, 
-0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x81, 0x69, 
-0xc0, 0x46, 0x11, 0x61, 0x81, 0x69, 0x02, 0x9b, 0x19, 0x43, 0x81, 0x61, 
-0x11, 0x61, 0x01, 0x98, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xf0, 0xff, 0x00, 0x00, 0x50, 0xab, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
-0x00, 0x00, 0x00, 0xb0, 0x70, 0x47, 0x04, 0x49, 0x00, 0x20, 0x00, 0x22, 
-0x0a, 0x70, 0x01, 0x30, 0x01, 0x31, 0x68, 0x28, 0xfa, 0xd3, 0x70, 0x47, 
-0xa0, 0x82, 0x20, 0x40, 0x00, 0x22, 0x88, 0x42, 0x03, 0xd3, 0x40, 0x1a, 
-0x01, 0x32, 0x88, 0x42, 0xfb, 0xd2, 0x10, 0x1c, 0x70, 0x47, 0x88, 0x42, 
-0x02, 0xd3, 0x40, 0x1a, 0x88, 0x42, 0xfc, 0xd2, 0x70, 0x47, 0x90, 0xb4, 
-0x01, 0x1c, 0xff, 0x27, 0x04, 0x29, 0x27, 0xda, 0x00, 0x20, 0x14, 0x4a, 
-0x43, 0x00, 0x1b, 0x18, 0xdb, 0x00, 0xd4, 0x58, 0x63, 0x0c, 0x1a, 0xd2, 
-0x4b, 0x00, 0x59, 0x18, 0xc9, 0x00, 0x57, 0x58, 0x43, 0x00, 0x1b, 0x18, 
-0xdb, 0x00, 0xd7, 0x50, 0x89, 0x18, 0x9a, 0x18, 0x4f, 0x68, 0xc0, 0x46, 
-0x57, 0x60, 0x8b, 0x68, 0xc0, 0x46, 0x93, 0x60, 0x0b, 0x69, 0xc0, 0x46, 
-0x13, 0x61, 0x4b, 0x69, 0xc0, 0x46, 0x53, 0x61, 0xc9, 0x68, 0xc0, 0x46, 
-0xd1, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 
-0x04, 0x28, 0xd9, 0xdb, 0x38, 0x1c, 0xf6, 0xe7, 0xd0, 0xab, 0x20, 0x40, 
-0xf7, 0xb5, 0xc5, 0xb0, 0x14, 0x1c, 0x00, 0x20, 0x11, 0x21, 0x21, 0x40, 
-0x5f, 0xd0, 0x00, 0x27, 0x79, 0x00, 0xc9, 0x19, 0xc9, 0x00, 0x5b, 0x4a, 
-0x51, 0x58, 0x49, 0x0c, 0x03, 0xd2, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 
-0x04, 0xe0, 0x79, 0x1c, 0x0f, 0x06, 0x3f, 0x0e, 0x04, 0x2f, 0xef, 0xdb, 
-0x00, 0x28, 0x4c, 0xd0, 0x00, 0x22, 0x01, 0x92, 0x00, 0x92, 0x40, 0x23, 
-0x00, 0x21, 0x00, 0x20, 0x03, 0xaa, 0x00, 0xf0, 
-0x8f, 0xfa, 0x05, 0xa9, 0x00, 0x20, 0x82, 0x00, 0x8a, 0x58, 0x12, 0x06, 
-0x12, 0x0e, 0x45, 0x9b, 0x9a, 0x42, 0x05, 0xd1, 0x01, 0x9a, 0x01, 0x32, 
-0x12, 0x06, 0x12, 0x0e, 0x01, 0x92, 0x04, 0xe0, 0x01, 0x30, 0x00, 0x06, 
-0x00, 0x0e, 0x10, 0x28, 0xed, 0xdb, 0x01, 0x9a, 0x00, 0x2a, 0x4f, 0xd0, 
-0x45, 0x9b, 0x04, 0x2b, 0x3e, 0xd1, 0x80, 0x00, 0x08, 0x58, 0x40, 0x01, 
-0x80, 0x0d, 0x00, 0x22, 0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x03, 0xaa, 
-0x00, 0xf0, 0x6a, 0xfa, 0x00, 0x21, 0x01, 0x91, 0x03, 0xa8, 0x06, 0x99, 
-0x49, 0x0c, 0x89, 0x05, 0x2a, 0xd0, 0xc1, 0x68, 0x0a, 0x06, 0x12, 0x0e, 
-0x46, 0x9b, 0x9a, 0x42, 0x12, 0xd1, 0xc0, 0x68, 0x40, 0x01, 0x86, 0x0d, 
-0x00, 0x22, 0x00, 0x92, 0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x03, 0xaa, 
-0x00, 0xf0, 0x52, 0xfa, 0x01, 0x99, 0x03, 0x9d, 0x48, 0x1c, 0x01, 0x06, 
-0x09, 0x0e, 0x01, 0x91, 0x0f, 0xe0, 0x57, 0xe0, 0x48, 0x01, 0x86, 0x0d, 
-0x00, 0x22, 0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x03, 0xaa, 
-0x00, 0xf0, 0x40, 0xfa, 0x03, 0xa8, 0x06, 0x99, 0x49, 0x0c, 0x89, 0x05, 
-0xd7, 0xd1, 0x01, 0x99, 0x00, 0x29, 0x11, 0xd1, 0xff, 0x20, 0x3f, 0xe0, 
+0x70, 0x47, 0x04, 0x49, 0x00, 0x20, 0x00, 0x22, 0x0a, 0x70, 0x01, 0x30, 
+0x01, 0x31, 0x68, 0x28, 0xfa, 0xd3, 0x70, 0x47, 0xa0, 0x82, 0x20, 0x40, 
+0x00, 0x22, 0x88, 0x42, 0x03, 0xd3, 0x40, 0x1a, 0x01, 0x32, 0x88, 0x42, 
+0xfb, 0xd2, 0x10, 0x1c, 0x70, 0x47, 0x88, 0x42, 0x02, 0xd3, 0x40, 0x1a, 
+0x88, 0x42, 0xfc, 0xd2, 0x70, 0x47, 0x90, 0xb4, 0x01, 0x1c, 0xff, 0x27, 
+0x04, 0x29, 0x27, 0xda, 0x00, 0x20, 0x14, 0x4a, 0x43, 0x00, 0x1b, 0x18, 
+0xdb, 0x00, 0xd4, 0x58, 0x63, 0x0c, 0x1a, 0xd2, 0x4b, 0x00, 0x59, 0x18, 
+0xc9, 0x00, 0x57, 0x58, 0x43, 0x00, 0x1b, 0x18, 0xdb, 0x00, 0xd7, 0x50, 
+0x89, 0x18, 0x9a, 0x18, 0x4f, 0x68, 0xc0, 0x46, 0x57, 0x60, 0x8b, 0x68, 
+0xc0, 0x46, 0x93, 0x60, 0x0b, 0x69, 0xc0, 0x46, 0x13, 0x61, 0x4b, 0x69, 
+0xc0, 0x46, 0x53, 0x61, 0xc9, 0x68, 0xc0, 0x46, 0xd1, 0x60, 0x90, 0xbc, 
+0x70, 0x47, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x04, 0x28, 0xd9, 0xdb, 
+0x38, 0x1c, 0xf6, 0xe7, 0xd0, 0xab, 0x20, 0x40, 0xf7, 0xb5, 0xc4, 0xb0, 
+0x04, 0x1c, 0x00, 0x20, 0x46, 0x9a, 0x11, 0x21, 0x11, 0x40, 0x6e, 0xd0, 
+0x00, 0x27, 0x79, 0x00, 0xc9, 0x19, 0xc9, 0x00, 0x57, 0x4a, 0x51, 0x58, 
+0x49, 0x0c, 0x03, 0xd2, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x04, 0xe0, 
+0x79, 0x1c, 0x0f, 0x06, 0x3f, 0x0e, 0x04, 0x2f, 0xef, 0xdb, 0x00, 0x28, 
+0x5b, 0xd0, 0x00, 0x26, 0x00, 0x22, 0x00, 0x92, 0x40, 0x23, 0x00, 0x21, 
+0x00, 0x20, 0x02, 0xaa, 0x00, 0xf0, 0x88, 0xfa, 0x04, 0xa9, 0x00, 0x20, 
+0x82, 0x00, 0x8a, 0x58, 0x12, 0x06, 0x12, 0x0e, 0xa2, 0x42, 0x03, 0xd1, 
+0x72, 0x1c, 0x16, 0x06, 0x36, 0x0e, 0x04, 0xe0, 0x01, 0x30, 0x00, 0x06, 
+0x00, 0x0e, 0x10, 0x28, 0xf0, 0xdb, 0x00, 0x2e, 0x3d, 0xd0, 0x04, 0x2c, 
+0x3e, 0xd1, 0x80, 0x00, 0x08, 0x58, 0x40, 0x01, 0x80, 0x0d, 0x00, 0x22, 
+0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x02, 0xaa, 
+0x00, 0xf0, 0x68, 0xfa, 0x00, 0x21, 0x01, 0x91, 0x02, 0xa8, 0x05, 0x99, 
+0x49, 0x0c, 0x89, 0x05, 0x29, 0xd0, 0xc1, 0x68, 0x0a, 0x06, 0x12, 0x0e, 
+0x45, 0x9b, 0x9a, 0x42, 0x11, 0xd1, 0xc0, 0x68, 0x40, 0x01, 0x86, 0x0d, 
+0x00, 0x22, 0x00, 0x92, 0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 
+0x00, 0xf0, 0x50, 0xfa, 0x01, 0x99, 0x02, 0x9d, 0x48, 0x1c, 0x01, 0x06, 
+0x09, 0x0e, 0x01, 0x91, 0x0e, 0xe0, 0x48, 0x01, 0x86, 0x0d, 0x00, 0x22, 
+0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 0x00, 0xf0, 
+0x3f, 0xfa, 0x02, 0xa8, 0x05, 0x99, 0x49, 0x0c, 0x89, 0x05, 0xd8, 0xd1, 
+0x01, 0x99, 0x00, 0x29, 0x0f, 0xd1, 0xff, 0x20, 0x3d, 0xe0, 0x40, 0xe0, 
 0x80, 0x00, 0x08, 0x58, 0x40, 0x01, 0x86, 0x0d, 0x00, 0x22, 0x00, 0x92, 
-0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x03, 0xaa, 0x00, 0xf0, 0x2a, 0xfa, 
-0x03, 0x9d, 0x01, 0xe0, 0x20, 0x0a, 0xed, 0xd2, 0x01, 0x20, 0x00, 0x04, 
-0x20, 0x43, 0x79, 0x00, 0xc9, 0x19, 0xc9, 0x00, 0x17, 0x4a, 0xc0, 0x46, 
-0x50, 0x50, 0x30, 0x1c, 0x8e, 0x18, 0x70, 0x60, 0x10, 0x20, 0x45, 0x9b, 
-0x04, 0x2b, 0x00, 0xd0, 0x0c, 0x20, 0x02, 0x90, 0xb0, 0x60, 0x00, 0x20, 
-0x20, 0x21, 0x21, 0x40, 0x20, 0x29, 0x00, 0xd0, 0x28, 0x1c, 0x30, 0x61, 
-0x02, 0x98, 0x28, 0x18, 0xff, 0x21, 0xff, 0x30, 0x08, 0x30, 0x09, 0x31, 
-0xff, 0xf7, 0x12, 0xff, 0x43, 0x01, 0x18, 0x18, 0xc0, 0x00, 0x02, 0x99, 
-0x40, 0x1a, 0x70, 0x61, 0x00, 0x20, 0x50, 0x21, 0x21, 0x40, 0x50, 0x29, 
-0x00, 0xd1, 0x28, 0x1c, 0xf0, 0x60, 0x38, 0x1c, 0x48, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xff, 0x20, 0xf9, 0xe7, 0xd0, 0xab, 0x20, 0x40, 
-0x80, 0xb4, 0x00, 0x23, 0x00, 0x22, 0x00, 0x29, 0x06, 0xd9, 0x87, 0x5c, 
-0x7b, 0x40, 0x1b, 0x06, 0x1b, 0x0e, 0x01, 0x32, 0x8a, 0x42, 0xf8, 0xd3, 
-0xd8, 0x43, 0x00, 0x06, 0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 
-0xc6, 0xb0, 0x04, 0x28, 0x07, 0xda, 0x41, 0x00, 0x09, 0x18, 0xc9, 0x00, 
-0x45, 0x91, 0x41, 0x4a, 0x51, 0x58, 0x4b, 0x0c, 0x02, 0xd2, 0x00, 0x20, 
-0xc0, 0x43, 0x76, 0xe0, 0x01, 0x23, 0x5b, 0x04, 0x19, 0x40, 0x43, 0x00, 
-0x18, 0x18, 0xc0, 0x00, 0x3a, 0x4a, 0x14, 0x18, 0x00, 0x29, 0x61, 0xd0, 
-0x00, 0x21, 0x02, 0x91, 0x20, 0x69, 0xa1, 0x68, 0x45, 0x18, 0x30, 0xd0, 
-0xff, 0x21, 0x68, 0x1e, 0x09, 0x31, 0xff, 0xf7, 0xc7, 0xfe, 0x61, 0x68, 
-0x40, 0x18, 0x01, 0x90, 0x01, 0x98, 0x81, 0x42, 0x02, 0xd1, 0xa6, 0x68, 
-0xaf, 0x1b, 0x09, 0xe0, 0x00, 0x26, 0xff, 0x21, 0x28, 0x1c, 0x09, 0x31, 
-0xff, 0xf7, 0xc1, 0xfe, 0x07, 0x1c, 0x01, 0xd1, 0xff, 0x27, 0x09, 0x37, 
-0x00, 0x22, 0x00, 0x92, 0x01, 0x98, 0x31, 0x1c, 0x03, 0xaa, 0x3b, 0x1c, 
-0x00, 0xf0, 0x9e, 0xf9, 0x03, 0xa8, 0x39, 0x1c, 0xff, 0xf7, 0xac, 0xff, 
-0xc0, 0x43, 0x02, 0x99, 0x48, 0x40, 0x01, 0x06, 0x09, 0x0e, 0x02, 0x91, 
-0xed, 0x1b, 0xa0, 0x68, 0xa8, 0x42, 0x00, 0xd1, 
-0x00, 0x25, 0x00, 0x2d, 0xce, 0xd8, 0x02, 0x99, 0xcf, 0x43, 0x00, 0x22, 
-0x00, 0x92, 0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 0x03, 0xaa, 0x00, 0xf0, 
-0x83, 0xf9, 0x20, 0x69, 0xc0, 0x46, 0x03, 0x90, 0x05, 0x98, 0x00, 0x0a, 
-0x00, 0x02, 0x39, 0x06, 0x09, 0x0e, 0x08, 0x43, 0x05, 0x90, 0xff, 0x23, 
-0x1b, 0x02, 0x98, 0x43, 0x05, 0x90, 0x0c, 0x21, 0x03, 0xa8, 0xff, 0xf7, 
-0x83, 0xff, 0xff, 0x23, 0x1b, 0x02, 0x05, 0x99, 0x99, 0x43, 0x00, 0x06, 
-0x00, 0x0e, 0x00, 0x02, 0x08, 0x43, 0x05, 0x90, 0x0c, 0x23, 0x00, 0x21, 
-0x60, 0x68, 0x03, 0xaa, 0x00, 0xf0, 0xbb, 0xf9, 0x00, 0x20, 0x45, 0x99, 
-0x06, 0x4a, 0xc0, 0x46, 0x50, 0x50, 0xc1, 0x43, 0x61, 0x60, 0xa1, 0x60, 
-0xe1, 0x60, 0x21, 0x61, 0x61, 0x61, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb4, 0x4c, 0x42, 
-0x00, 0x29, 0x00, 0xdb, 0x0c, 0x1c, 0x00, 0x27, 0xff, 0x43, 0x04, 0x28, 
-0x21, 0xda, 0x12, 0x4d, 0x43, 0x00, 0x18, 0x18, 0xc0, 0x00, 0x40, 0x19, 
-0x01, 0x2a, 0x05, 0xd0, 0x02, 0x2a, 0x09, 0xd0, 0x03, 0x2a, 0x16, 0xd1, 
-0x01, 0x69, 0x0b, 0xe0, 0x00, 0x29, 0x12, 0xdb, 0x02, 0x69, 0x8a, 0x42, 
-0x0f, 0xd3, 0x05, 0xe0, 0x00, 0x29, 0x07, 0xda, 0xc1, 0x68, 0xa1, 0x42, 
-0x09, 0xd3, 0x09, 0x1b, 0xc1, 0x60, 0xc0, 0x68, 0xb0, 0xbc, 0x70, 0x47, 
-0xc1, 0x68, 0x09, 0x19, 0x02, 0x69, 0x91, 0x42, 0xf6, 0xd9, 0x38, 0x1c, 
-0xf6, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 
-0x17, 0x1c, 0x0d, 0x1c, 0x00, 0x21, 0x02, 0x91, 0x42, 0x00, 0x12, 0x18, 
-0xd2, 0x00, 0x2c, 0x49, 0x8b, 0x58, 0x1b, 0x06, 0x1b, 0x0e, 0x01, 0x93, 
-0x00, 0x23, 0xdb, 0x43, 0x04, 0x28, 0x02, 0xda, 0x01, 0x98, 0x40, 0x08, 
-0x01, 0xd2, 0x18, 0x1c, 0x46, 0xe0, 0x54, 0x18, 0xe0, 0x68, 0xc2, 0x19, 
-0x21, 0x69, 0x8a, 0x42, 0x00, 0xd9, 0x0f, 0x1a, 0x00, 0x2f, 0x3c, 0xd9, 
-0xa0, 0x68, 0xe1, 0x68, 0x40, 0x18, 0xff, 0x21, 0x09, 0x31, 0xff, 0xf7, 
-0x07, 0xfe, 0x61, 0x68, 0x46, 0x18, 0xa0, 0x68, 0xe1, 0x68, 0x40, 0x18, 
-0xff, 0x21, 0x09, 0x31, 0xff, 0xf7, 0x07, 0xfe, 0xc2, 0x19, 0xff, 0x21, 
-0x09, 0x31, 0x8a, 0x42, 0x14, 0xd9, 0x01, 0x9a, 0xc0, 0x46, 0x00, 0x92, 
-0x0b, 0x1a, 0x03, 0x93, 0x01, 0x1c, 0x30, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 
-0xe1, 0xf8, 0xe0, 0x68, 0x03, 0x9b, 0xc0, 0x18, 0xe0, 0x60, 0x03, 0x9b, 
-0x5d, 0x19, 0xff, 0x1a, 0x02, 0x98, 0x18, 0x18, 0x02, 0x90, 0x10, 0xe0, 
-0x01, 0x9a, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x1c, 0x30, 0x1c, 0x2a, 0x1c, 
-0x3b, 0x1c, 0x00, 0xf0, 0xcd, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 
-0xe0, 0x60, 0x02, 0x98, 0xc0, 0x19, 0x02, 0x90, 0x00, 0x27, 0x00, 0x2f, 
-0xc2, 0xd8, 0x02, 0x98, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xd0, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x83, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 
-0x00, 0x21, 0x01, 0x91, 0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x02, 0x92, 
-0x30, 0x49, 0x8a, 0x58, 0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0xe4, 0x43, 
-0x04, 0x28, 0x01, 0xda, 0x50, 0x09, 0x01, 0xd2, 0x20, 0x1c, 0x51, 0xe0, 
-0x02, 0x9a, 0x54, 0x18, 0xe0, 0x68, 0xc2, 0x19, 0x60, 0x69, 0x82, 0x42, 
-0x01, 0xd9, 0x22, 0x69, 0x87, 0x1a, 0x00, 0x2f, 0x45, 0xd9, 0x25, 0x4e, 
-0xa0, 0x68, 0xe1, 0x68, 0x40, 0x18, 0xff, 0x21, 0x09, 0x31, 0xff, 0xf7, 
-0xa1, 0xfd, 0x61, 0x68, 0x40, 0x18, 0x00, 0x90, 
-0xa0, 0x68, 0xe1, 0x68, 0x40, 0x18, 0xff, 0x21, 0x09, 0x31, 0xff, 0xf7, 
-0xa0, 0xfd, 0x02, 0x9a, 0xb1, 0x58, 0x01, 0x23, 0x5b, 0x04, 0x19, 0x43, 
-0xb1, 0x50, 0xc1, 0x19, 0xff, 0x22, 0x09, 0x32, 0x91, 0x42, 0x13, 0xd9, 
-0x13, 0x1a, 0x01, 0x1c, 0x00, 0x98, 0x2a, 0x1c, 0x1e, 0x1c, 0x00, 0xf0, 
-0xd0, 0xf8, 0xe0, 0x68, 0x80, 0x19, 0x75, 0x19, 0xe0, 0x60, 0x21, 0x69, 
-0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0xbf, 0x1b, 0x01, 0x98, 0x30, 0x18, 
-0x01, 0x90, 0x12, 0xe0, 0x01, 0x1c, 0x00, 0x9e, 0x30, 0x1c, 0x2a, 0x1c, 
-0x3b, 0x1c, 0x00, 0xf0, 0xbc, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 
-0xe0, 0x60, 0x21, 0x69, 0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0x01, 0x98, 
-0xc0, 0x19, 0x01, 0x90, 0x00, 0x27, 0x00, 0x2f, 0xb9, 0xd8, 0x01, 0x98, 
-0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40, 
-0xb0, 0xb5, 0xc3, 0xb0, 0x0c, 0x1c, 0x00, 0x27, 0xfa, 0x43, 0x04, 0x28, 
-0x06, 0xda, 0x41, 0x00, 0x09, 0x18, 0xc9, 0x00, 0x14, 0x48, 0x45, 0x58, 
-0x6b, 0x0c, 0x04, 0xd2, 0x10, 0x1c, 0x43, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x62, 0x09, 0x1b, 0xd3, 0x00, 0x22, 0x00, 0x92, 0x08, 0x18, 
-0x40, 0x68, 0x0c, 0x23, 0x00, 0x21, 0x01, 0xaa, 0x00, 0xf0, 0x30, 0xf8, 
-0x11, 0x2c, 0x0d, 0xd0, 0x12, 0x2c, 0x0d, 0xd0, 0x13, 0x2c, 0x05, 0xd0, 
-0x14, 0x2c, 0x0a, 0xd1, 0x03, 0x98, 0x00, 0x04, 0x07, 0x0e, 0x06, 0xe0, 
-0x03, 0x98, 0x07, 0x06, 0x3f, 0x0e, 0x02, 0xe0, 0x01, 0x9f, 0x00, 0xe0, 
-0x02, 0x9f, 0x38, 0x1c, 0xdb, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 
-0x03, 0x49, 0x00, 0x20, 0x00, 0x22, 0x0a, 0x54, 0x01, 0x30, 0x60, 0x28, 
-0xfb, 0xd3, 0x70, 0x47, 0xd0, 0xab, 0x20, 0x40, 0x00, 0xb5, 0x02, 0xf0, 
-0x9f, 0xf9, 0x57, 0x20, 0x02, 0xf0, 0xfc, 0xf8, 0x02, 0xf0, 0x70, 0xf8, 
-0x00, 0x0a, 0xfb, 0xd3, 0x02, 0xf0, 0x7e, 0xf9, 0x08, 0xbc, 0x18, 0x47, 
-0xf0, 0xb5, 0x82, 0xb0, 0x14, 0x1c, 0x07, 0x9a, 0x1f, 0x1c, 0xff, 0x23, 
-0x01, 0x33, 0x1a, 0x40, 0x40, 0x02, 0x08, 0x43, 0x05, 0x0a, 0x06, 0x1c, 
-0x00, 0x0c, 0x01, 0x90, 0x00, 0x2a, 0x20, 0xd0, 0x02, 0xf0, 0x82, 0xf9, 
-0x53, 0x20, 0x02, 0xf0, 0xdf, 0xf8, 0x01, 0x98, 0xc0, 0x46, 0x00, 0x90, 
-0x02, 0xf0, 0xda, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 0xd7, 0xf8, 0x30, 0x1c, 
-0x02, 0xf0, 0xd4, 0xf8, 0x02, 0xf0, 0x5a, 0xf9, 0xff, 0xf7, 0xce, 0xff, 
-0x02, 0xf0, 0x6e, 0xf9, 0x54, 0x20, 0x02, 0xf0, 0xcb, 0xf8, 0x00, 0x98, 
-0x02, 0xf0, 0xc8, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 0xc5, 0xf8, 0x30, 0x1c, 
-0x14, 0xe0, 0x02, 0xf0, 0x61, 0xf9, 0x52, 0x20, 0x02, 0xf0, 0xbe, 0xf8, 
-0x01, 0x98, 0x02, 0xf0, 0xbb, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 0xb8, 0xf8, 
-0x30, 0x1c, 0x02, 0xf0, 0xb5, 0xf8, 0x00, 0x20, 0x02, 0xf0, 0xb2, 0xf8, 
-0x00, 0x20, 0x02, 0xf0, 0xaf, 0xf8, 0x00, 0x20, 0x02, 0xf0, 0xac, 0xf8, 
-0x00, 0x20, 0x02, 0xf0, 0xa9, 0xf8, 0x00, 0x2f, 0x05, 0xd9, 0x02, 0xf0, 
-0x1b, 0xf8, 0x20, 0x70, 0x01, 0x34, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 
-0x27, 0xf9, 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
-0x82, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x40, 0x02, 0x08, 0x43, 0x05, 0x1c, 
-0x02, 0xf0, 0x32, 0xf9, 0x53, 0x20, 0x02, 0xf0, 0x8f, 0xf8, 0x28, 0x0c, 
-0x06, 0x1c, 0x02, 0xf0, 0x8b, 0xf8, 0x28, 0x0a, 0x01, 0x90, 0x00, 0x90, 
-0x02, 0xf0, 0x86, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
-0x83, 0xf8, 0x02, 0xf0, 0x09, 0xf9, 0xff, 0xf7, 0x7d, 0xff, 0x02, 0xf0, 
-0x1d, 0xf9, 0x84, 0x20, 0x02, 0xf0, 0x7a, 0xf8, 0x30, 0x1c, 0x02, 0xf0, 
-0x77, 0xf8, 0x00, 0x98, 0x02, 0xf0, 0x74, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
-0x71, 0xf8, 0x00, 0x2f, 0x05, 0xd9, 0x20, 0x78, 0x01, 0x34, 0x02, 0xf0, 
-0x6b, 0xf8, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0xef, 0xf8, 0x02, 0xf0, 
-0x05, 0xf9, 0x83, 0x20, 0x02, 0xf0, 0x62, 0xf8, 0x30, 0x1c, 0x02, 0xf0, 
-0x5f, 0xf8, 0x01, 0x98, 0x02, 0xf0, 0x5c, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
-0x59, 0xf8, 0x02, 0xf0, 0xdf, 0xf8, 0xff, 0xf7, 0x53, 0xff, 0x02, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
-0x80, 0xb5, 0x01, 0xf0, 0x89, 0xf8, 0x06, 0x4f, 0xc0, 0x46, 0xf8, 0x60, 
-0x01, 0xf0, 0xe4, 0xf8, 0x78, 0x80, 0x01, 0xf0, 0xa5, 0xf8, 0x38, 0x71, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0xb5, 0x01, 0xf0, 0xf7, 0xf8, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x80, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0x0b, 0x48, 0xc1, 0x68, 
-0x01, 0x29, 0x11, 0xd1, 0x02, 0x22, 0xc1, 0x6f, 0x0a, 0x43, 0xc2, 0x67, 
-0x08, 0x49, 0xc0, 0x46, 0x0a, 0x60, 0x80, 0x23, 0xc2, 0x6f, 0x1a, 0x43, 
-0xc2, 0x67, 0x0a, 0x60, 0x82, 0x22, 0x80, 0x30, 0x02, 0x60, 0x4a, 0x60, 
-0x00, 0x21, 0x81, 0x80, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0x01, 0x11, 0x00, 0xf0, 0xb4, 0x49, 0x49, 0xca, 0x1d, 0x99, 0x32, 
-0x00, 0x20, 0x00, 0x27, 0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x17, 0x28, 
-0xfa, 0xd3, 0x45, 0x4c, 0x00, 0x20, 0x82, 0x00, 0xa7, 0x50, 0x01, 0x30, 
-0x20, 0x28, 0xfa, 0xd3, 0x42, 0x4a, 0x00, 0x20, 0x83, 0x00, 0xd7, 0x50, 
-0x01, 0x30, 0x20, 0x28, 0xfa, 0xd3, 0xa7, 0x61, 0x97, 0x61, 0x4f, 0x65, 
-0x8f, 0x65, 0x3e, 0x4d, 0xc0, 0x46, 0x2f, 0x60, 0x6f, 0x60, 0xaf, 0x60, 
-0xaf, 0x61, 0xef, 0x60, 0x2f, 0x61, 0x6f, 0x61, 0x00, 0x20, 0xc1, 0x00, 
-0x09, 0x18, 0x49, 0x01, 0x34, 0x4b, 0xc9, 0x18, 0x86, 0x00, 0xcb, 0x1d, 
-0xf5, 0x33, 0x33, 0x4c, 0x34, 0x19, 0xe3, 0x63, 0x87, 0x23, 0x9b, 0x00, 
-0xcb, 0x18, 0x63, 0x63, 0xcf, 0x23, 0x9b, 0x00, 0xcb, 0x18, 0xb4, 0x18, 
-0xe3, 0x63, 0x30, 0x4b, 0xc9, 0x18, 0x61, 0x63, 0x01, 0x30, 0x02, 0x28, 
-0xe5, 0xdb, 0x29, 0x48, 0xc1, 0x1d, 0xf5, 0x31, 0x28, 0x4c, 0xc0, 0x46, 
-0xa1, 0x62, 0x61, 0x6b, 0xcf, 0x23, 0x9b, 0x00, 0xe1, 0x62, 0xc1, 0x18, 
-0x91, 0x62, 0x51, 0x6b, 0xc0, 0x46, 0xd1, 0x62, 0x08, 0x21, 0xe1, 0x64, 
-0x25, 0x49, 0xc0, 0x46, 0x21, 0x65, 0x25, 0x49, 0x0b, 0x69, 0xc0, 0x46, 
-0x63, 0x65, 0xc3, 0x1d, 0x4d, 0x33, 0xe3, 0x65, 0x25, 0x66, 0x8b, 0x68, 
-0xc0, 0x46, 0x63, 0x66, 0xcb, 0x68, 0xc0, 0x46, 0xa3, 0x66, 0x1f, 0x4b, 
-0xc0, 0x46, 0xe3, 0x66, 0x27, 0x67, 0x67, 0x67, 0x1d, 0x4b, 0xc3, 0x18, 
-0x01, 0x26, 0xa3, 0x67, 0x66, 0x61, 0xe7, 0x61, 0xe3, 0x1d, 0x69, 0x33, 
-0x1f, 0x73, 0x02, 0x23, 0xd3, 0x64, 0x19, 0x4b, 0xc0, 0x46, 0x13, 0x65, 
+0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 0x00, 0xf0, 0x28, 0xfa, 
+0x02, 0x9d, 0x01, 0x20, 0x00, 0x04, 0x46, 0x9a, 0x10, 0x43, 0x79, 0x00, 
+0xc9, 0x19, 0xc9, 0x00, 0x17, 0x4a, 0xc0, 0x46, 0x50, 0x50, 0x30, 0x1c, 
+0x8e, 0x18, 0x70, 0x60, 0x10, 0x20, 0x04, 0x2c, 0x00, 0xd0, 0x0c, 0x20, 
+0x04, 0x1c, 0xb0, 0x60, 0x00, 0x20, 0x20, 0x21, 0x46, 0x9a, 0x11, 0x40, 
+0x20, 0x29, 0x00, 0xd0, 0x28, 0x1c, 0x30, 0x61, 0x28, 0x19, 0xff, 0x21, 
+0xff, 0x30, 0x08, 0x30, 0x09, 0x31, 0xff, 0xf7, 0x19, 0xff, 0x43, 0x01, 
+0x18, 0x18, 0xc0, 0x00, 0x00, 0x1b, 0x70, 0x61, 0x00, 0x20, 0x50, 0x21, 
+0x46, 0x9a, 0x11, 0x40, 0x50, 0x29, 0x00, 0xd1, 0x28, 0x1c, 0xf0, 0x60, 
+0x38, 0x1c, 0x47, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0x20, 
+0xf9, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0x80, 0xb4, 0x00, 0x23, 
+0x00, 0x22, 0x00, 0x29, 0x06, 0xd9, 0x87, 0x5c, 0x7b, 0x40, 0x1b, 0x06, 
+0x1b, 0x0e, 0x01, 0x32, 0x8a, 0x42, 0xf8, 0xd3, 0xd8, 0x43, 0x00, 0x06, 
+0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0xc6, 0xb0, 0x04, 0x28, 
+0x07, 0xda, 0x41, 0x00, 0x09, 0x18, 0xc9, 0x00, 0x45, 0x91, 0x41, 0x4a, 
+0x51, 0x58, 0x4b, 0x0c, 0x02, 0xd2, 0x00, 0x20, 0xc0, 0x43, 0x76, 0xe0, 
+0x01, 0x23, 0x5b, 0x04, 0x19, 0x40, 0x43, 0x00, 0x18, 0x18, 0xc0, 0x00, 
+0x3a, 0x4a, 0x14, 0x18, 0x00, 0x29, 0x61, 0xd0, 0x00, 0x21, 0x02, 0x91, 
+0x20, 0x69, 0xa1, 0x68, 0x45, 0x18, 0x30, 0xd0, 0xff, 0x21, 0x68, 0x1e, 
+0x09, 0x31, 0xff, 0xf7, 0xcd, 0xfe, 0x61, 0x68, 0x40, 0x18, 0x01, 0x90, 
+0x01, 0x98, 0x81, 0x42, 0x02, 0xd1, 0xa6, 0x68, 0xaf, 0x1b, 0x09, 0xe0, 
+0x00, 0x26, 0xff, 0x21, 0x28, 0x1c, 0x09, 0x31, 0xff, 0xf7, 0xc7, 0xfe, 
+0x07, 0x1c, 0x01, 0xd1, 0xff, 0x27, 0x09, 0x37, 0x00, 0x22, 0x00, 0x92, 
+0x01, 0x98, 0x31, 0x1c, 0x03, 0xaa, 0x3b, 0x1c, 0x00, 0xf0, 0x9e, 0xf9, 
+0x03, 0xa8, 0x39, 0x1c, 0xff, 0xf7, 0xac, 0xff, 0xc0, 0x43, 0x02, 0x99, 
+0x48, 0x40, 0x01, 0x06, 0x09, 0x0e, 0x02, 0x91, 0xed, 0x1b, 0xa0, 0x68, 
+0xa8, 0x42, 0x00, 0xd1, 0x00, 0x25, 0x00, 0x2d, 0xce, 0xd8, 0x02, 0x99, 
+0xcf, 0x43, 0x00, 0x22, 0x00, 0x92, 0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 
+0x03, 0xaa, 0x00, 0xf0, 0x83, 0xf9, 0x20, 0x69, 0xc0, 0x46, 0x03, 0x90, 
+0x05, 0x98, 0x00, 0x0a, 0x00, 0x02, 0x39, 0x06, 0x09, 0x0e, 0x08, 0x43, 
+0x05, 0x90, 0xff, 0x23, 0x1b, 0x02, 0x98, 0x43, 0x05, 0x90, 0x0c, 0x21, 
+0x03, 0xa8, 0xff, 0xf7, 0x83, 0xff, 0xff, 0x23, 0x1b, 0x02, 0x05, 0x99, 
+0x99, 0x43, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x02, 
+0x08, 0x43, 0x05, 0x90, 0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 0x03, 0xaa, 
+0x00, 0xf0, 0xca, 0xf9, 0x00, 0x20, 0x45, 0x99, 0x06, 0x4a, 0xc0, 0x46, 
+0x50, 0x50, 0xc1, 0x43, 0x61, 0x60, 0xa1, 0x60, 0xe1, 0x60, 0x21, 0x61, 
+0x61, 0x61, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb4, 0x4c, 0x42, 0x00, 0x29, 0x00, 0xdb, 
+0x0c, 0x1c, 0x00, 0x27, 0xff, 0x43, 0x04, 0x28, 0x21, 0xda, 0x12, 0x4d, 
+0x43, 0x00, 0x18, 0x18, 0xc0, 0x00, 0x40, 0x19, 0x01, 0x2a, 0x05, 0xd0, 
+0x02, 0x2a, 0x09, 0xd0, 0x03, 0x2a, 0x16, 0xd1, 0x01, 0x69, 0x0b, 0xe0, 
+0x00, 0x29, 0x12, 0xdb, 0x02, 0x69, 0x8a, 0x42, 0x0f, 0xd3, 0x05, 0xe0, 
+0x00, 0x29, 0x07, 0xda, 0xc1, 0x68, 0xa1, 0x42, 0x09, 0xd3, 0x09, 0x1b, 
+0xc1, 0x60, 0xc0, 0x68, 0xb0, 0xbc, 0x70, 0x47, 0xc1, 0x68, 0x09, 0x19, 
+0x02, 0x69, 0x91, 0x42, 0xf6, 0xd9, 0x38, 0x1c, 0xf6, 0xe7, 0x00, 0x00, 
+0xd0, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 
+0x00, 0x21, 0x02, 0x91, 0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x2c, 0x49, 
+0x8b, 0x58, 0x1b, 0x06, 0x1b, 0x0e, 0x01, 0x93, 0x00, 0x23, 0xdb, 0x43, 
+0x04, 0x28, 0x02, 0xda, 0x01, 0x98, 0x40, 0x08, 0x01, 0xd2, 0x18, 0x1c, 
+0x46, 0xe0, 0x54, 0x18, 0xe0, 0x68, 0xc2, 0x19, 0x21, 0x69, 0x8a, 0x42, 
+0x00, 0xd9, 0x0f, 0x1a, 0x00, 0x2f, 0x3c, 0xd9, 0xa0, 0x68, 0xe1, 0x68, 
+0x40, 0x18, 0xff, 0x21, 0x09, 0x31, 0xff, 0xf7, 0x0d, 0xfe, 0x61, 0x68, 
+0x46, 0x18, 0xa0, 0x68, 0xe1, 0x68, 0x40, 0x18, 0xff, 0x21, 0x09, 0x31, 
+0xff, 0xf7, 0x0d, 0xfe, 0xc2, 0x19, 0xff, 0x21, 0x09, 0x31, 0x8a, 0x42, 
+0x14, 0xd9, 0x01, 0x9a, 0xc0, 0x46, 0x00, 0x92, 0x0b, 0x1a, 0x03, 0x93, 
+0x01, 0x1c, 0x30, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 0xe1, 0xf8, 0xe0, 0x68, 
+0x03, 0x9b, 0xc0, 0x18, 0xe0, 0x60, 0x03, 0x9b, 0x5d, 0x19, 0xff, 0x1a, 
+0x02, 0x98, 0x18, 0x18, 0x02, 0x90, 0x10, 0xe0, 0x01, 0x9a, 0xc0, 0x46, 
+0x00, 0x92, 0x01, 0x1c, 0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0, 
+0xcd, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x02, 0x98, 
+0xc0, 0x19, 0x02, 0x90, 0x00, 0x27, 0x00, 0x2f, 0xc2, 0xd8, 0x02, 0x98, 
+0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40, 
+0xf0, 0xb5, 0x83, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 0x00, 0x21, 0x01, 0x91, 
+0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x02, 0x92, 0x30, 0x49, 0x8a, 0x58, 
+0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0xe4, 0x43, 0x04, 0x28, 0x01, 0xda, 
+0x50, 0x09, 0x01, 0xd2, 0x20, 0x1c, 0x51, 0xe0, 0x02, 0x9a, 0x54, 0x18, 
+0xe0, 0x68, 0xc2, 0x19, 0x60, 0x69, 0x82, 0x42, 0x01, 0xd9, 0x22, 0x69, 
+0x87, 0x1a, 0x00, 0x2f, 0x45, 0xd9, 0x25, 0x4e, 0xa0, 0x68, 0xe1, 0x68, 
+0x40, 0x18, 0xff, 0x21, 0x09, 0x31, 0xff, 0xf7, 0xa7, 0xfd, 0x61, 0x68, 
+0x40, 0x18, 0x00, 0x90, 0xa0, 0x68, 0xe1, 0x68, 0x40, 0x18, 0xff, 0x21, 
+0x09, 0x31, 0xff, 0xf7, 0xa6, 0xfd, 0x02, 0x9a, 0xb1, 0x58, 0x01, 0x23, 
+0x5b, 0x04, 0x19, 0x43, 0xb1, 0x50, 0xc1, 0x19, 0xff, 0x22, 0x09, 0x32, 
+0x91, 0x42, 0x13, 0xd9, 0x13, 0x1a, 0x01, 0x1c, 0x00, 0x98, 0x2a, 0x1c, 
+0x1e, 0x1c, 0x00, 0xf0, 0xdf, 0xf8, 0xe0, 0x68, 0x80, 0x19, 0x75, 0x19, 
+0xe0, 0x60, 0x21, 0x69, 0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0xbf, 0x1b, 
+0x01, 0x98, 0x30, 0x18, 0x01, 0x90, 0x12, 0xe0, 
+0x01, 0x1c, 0x00, 0x9e, 0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0, 
+0xcb, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x21, 0x69, 
+0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0x01, 0x98, 0xc0, 0x19, 0x01, 0x90, 
+0x00, 0x27, 0x00, 0x2f, 0xb9, 0xd8, 0x01, 0x98, 0x03, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb5, 0xc3, 0xb0, 
+0x0c, 0x1c, 0x00, 0x27, 0xfa, 0x43, 0x04, 0x28, 0x06, 0xda, 0x41, 0x00, 
+0x09, 0x18, 0xc9, 0x00, 0x14, 0x48, 0x45, 0x58, 0x6b, 0x0c, 0x04, 0xd2, 
+0x10, 0x1c, 0x43, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x62, 0x09, 
+0x1b, 0xd3, 0x00, 0x22, 0x00, 0x92, 0x08, 0x18, 0x40, 0x68, 0x0c, 0x23, 
+0x00, 0x21, 0x01, 0xaa, 0x00, 0xf0, 0x30, 0xf8, 0x11, 0x2c, 0x0d, 0xd0, 
+0x12, 0x2c, 0x0d, 0xd0, 0x13, 0x2c, 0x05, 0xd0, 0x14, 0x2c, 0x0a, 0xd1, 
+0x03, 0x98, 0x00, 0x04, 0x07, 0x0e, 0x06, 0xe0, 0x03, 0x98, 0x07, 0x06, 
+0x3f, 0x0e, 0x02, 0xe0, 0x01, 0x9f, 0x00, 0xe0, 0x02, 0x9f, 0x38, 0x1c, 
+0xdb, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0x03, 0x49, 0x00, 0x20, 
+0x00, 0x22, 0x0a, 0x54, 0x01, 0x30, 0x60, 0x28, 0xfb, 0xd3, 0x70, 0x47, 
+0xd0, 0xab, 0x20, 0x40, 0x00, 0xb5, 0x02, 0xf0, 0x01, 0xfa, 0x57, 0x20, 
+0x02, 0xf0, 0x5e, 0xf9, 0x02, 0xf0, 0xd2, 0xf8, 0x00, 0x0a, 0xfb, 0xd3, 
+0x02, 0xf0, 0xe0, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x82, 0xb0, 
+0x07, 0x9d, 0x14, 0x1c, 0x1f, 0x1c, 0x30, 0x4a, 0xd2, 0x6f, 0x20, 0x23, 
+0x16, 0x68, 0x9e, 0x43, 0x16, 0x60, 0x33, 0x1c, 0xff, 0x22, 0x01, 0x32, 
+0x2a, 0x40, 0x40, 0x02, 0x08, 0x43, 0x05, 0x0a, 0x06, 0x1c, 0x00, 0x0c, 
+0x01, 0x90, 0x00, 0x2a, 0x20, 0xd0, 0x02, 0xf0, 0xdd, 0xf9, 0x53, 0x20, 
+0x02, 0xf0, 0x3a, 0xf9, 0x01, 0x98, 0xc0, 0x46, 0x00, 0x90, 0x02, 0xf0, 
+0x35, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x32, 0xf9, 0x30, 0x1c, 0x02, 0xf0, 
+0x2f, 0xf9, 0x02, 0xf0, 0xb5, 0xf9, 0xff, 0xf7, 0xc7, 0xff, 0x02, 0xf0, 
+0xc9, 0xf9, 0x54, 0x20, 0x02, 0xf0, 0x26, 0xf9, 0x00, 0x98, 0x02, 0xf0, 
+0x23, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x20, 0xf9, 0x30, 0x1c, 0x14, 0xe0, 
+0x02, 0xf0, 0xbc, 0xf9, 0x52, 0x20, 0x02, 0xf0, 0x19, 0xf9, 0x01, 0x98, 
+0x02, 0xf0, 0x16, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x13, 0xf9, 0x30, 0x1c, 
+0x02, 0xf0, 0x10, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x0d, 0xf9, 0x00, 0x20, 
+0x02, 0xf0, 0x0a, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x07, 0xf9, 0x00, 0x20, 
+0x02, 0xf0, 0x04, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x02, 0xf0, 0x76, 0xf8, 
+0x20, 0x70, 0x01, 0x34, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0x82, 0xf9, 
+0x04, 0x4a, 0xd0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0xf0, 0xb5, 0x82, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x40, 0x02, 0x08, 0x43, 
+0x05, 0x1c, 0x2c, 0x49, 0xc8, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 
+0x02, 0x60, 0xc8, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0x02, 0xf0, 0x7a, 0xf9, 0x53, 0x20, 0x02, 0xf0, 0xd7, 0xf8, 0x28, 0x0c, 
+0x06, 0x1c, 0x02, 0xf0, 0xd3, 0xf8, 0x28, 0x0a, 0x01, 0x90, 0x00, 0x90, 
+0x02, 0xf0, 0xce, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 0xcb, 0xf8, 0x02, 0xf0, 
+0x51, 0xf9, 0xff, 0xf7, 0x63, 0xff, 0x02, 0xf0, 0x65, 0xf9, 0x84, 0x20, 
+0x02, 0xf0, 0xc2, 0xf8, 0x30, 0x1c, 0x02, 0xf0, 
+0xbf, 0xf8, 0x00, 0x98, 0x02, 0xf0, 0xbc, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
+0xb9, 0xf8, 0x00, 0x2f, 0x05, 0xd9, 0x20, 0x78, 0x01, 0x34, 0x02, 0xf0, 
+0xb3, 0xf8, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0x37, 0xf9, 0x02, 0xf0, 
+0x4d, 0xf9, 0x83, 0x20, 0x02, 0xf0, 0xaa, 0xf8, 0x30, 0x1c, 0x02, 0xf0, 
+0xa7, 0xf8, 0x01, 0x98, 0x02, 0xf0, 0xa4, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
+0xa1, 0xf8, 0x02, 0xf0, 0x27, 0xf9, 0xff, 0xf7, 0x39, 0xff, 0x07, 0x49, 
+0xc8, 0x6f, 0x40, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0xc8, 0x6f, 
+0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x02, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 
+0x80, 0xb5, 0x01, 0xf0, 0x91, 0xf8, 0x06, 0x4f, 0xc0, 0x46, 0xf8, 0x60, 
+0x01, 0xf0, 0xf4, 0xf8, 0x78, 0x80, 0x01, 0xf0, 0xb3, 0xf8, 0x38, 0x71, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0xb5, 0x01, 0xf0, 0x07, 0xf9, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x80, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x0b, 0x48, 0xc1, 0x68, 
+0x01, 0x29, 0x11, 0xd1, 0xc1, 0x6f, 0x02, 0x23, 0x0a, 0x68, 0x1a, 0x43, 
+0x0a, 0x60, 0xc1, 0x6f, 0x80, 0x23, 0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 
+0xc1, 0x18, 0x08, 0x68, 0x82, 0x23, 0x02, 0x68, 0x1a, 0x43, 0x02, 0x60, 
+0x00, 0x20, 0x08, 0x81, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0xf0, 0xb4, 0x4a, 0x49, 0xca, 0x1d, 0x9d, 0x32, 0x00, 0x20, 0x00, 0x27, 
+0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x17, 0x28, 0xfa, 0xd3, 0x46, 0x4c, 
+0x00, 0x20, 0x82, 0x00, 0xa7, 0x50, 0x01, 0x30, 0x20, 0x28, 0xfa, 0xd3, 
+0x43, 0x4a, 0x00, 0x20, 0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x20, 0x28, 
+0xfa, 0xd3, 0xa7, 0x61, 0x97, 0x61, 0x4f, 0x65, 0x8f, 0x65, 0x3f, 0x4d, 
+0xc0, 0x46, 0x2f, 0x60, 0x6f, 0x60, 0xaf, 0x60, 0xaf, 0x61, 0xef, 0x60, 
+0x2f, 0x61, 0x6f, 0x61, 0x00, 0x20, 0xc1, 0x00, 0x09, 0x18, 0x49, 0x01, 
+0x35, 0x4b, 0xc9, 0x18, 0x86, 0x00, 0xcb, 0x1d, 0xf9, 0x33, 0x34, 0x4c, 
+0x34, 0x19, 0xe3, 0x63, 0x11, 0x23, 0x5b, 0x01, 0xcb, 0x18, 0x63, 0x63, 
+0x0d, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0xb4, 0x18, 0xe3, 0x63, 0x23, 0x23, 
+0x5b, 0x01, 0xc9, 0x18, 0x61, 0x63, 0x01, 0x30, 0x02, 0x28, 0xe4, 0xdb, 
+0x29, 0x48, 0xc1, 0x1d, 0xf9, 0x31, 0x29, 0x4c, 0xc0, 0x46, 0xa1, 0x62, 
+0x61, 0x6b, 0x0d, 0x23, 0x9b, 0x01, 0xe1, 0x62, 0xc1, 0x18, 0x91, 0x62, 
+0x51, 0x6b, 0xc0, 0x46, 0xd1, 0x62, 0x08, 0x21, 0xe1, 0x64, 0x25, 0x49, 
+0xc0, 0x46, 0x21, 0x65, 0x24, 0x49, 0x0b, 0x69, 0xc0, 0x46, 0x63, 0x65, 
+0xc3, 0x1d, 0x4d, 0x33, 0xe3, 0x65, 0x25, 0x66, 0x8b, 0x68, 0xc0, 0x46, 
+0x63, 0x66, 0xcb, 0x68, 0xc0, 0x46, 0xa3, 0x66, 0x1e, 0x4b, 0xc0, 0x46, 
+0xe3, 0x66, 0x27, 0x67, 0x0b, 0x23, 0xdb, 0x01, 0xc3, 0x18, 0xa3, 0x67, 
+0x67, 0x67, 0x01, 0x26, 0xe3, 0x1d, 0x69, 0x33, 0x66, 0x61, 0xe7, 0x61, 
+0x1f, 0x73, 0x02, 0x23, 0xd3, 0x64, 0x17, 0x4b, 0xc0, 0x46, 0x13, 0x65, 
 0xcb, 0x69, 0xc0, 0x46, 0x53, 0x65, 0xc3, 0x1d, 0x51, 0x33, 0xd3, 0x65, 
 0x2b, 0x1d, 0x13, 0x66, 0x4b, 0x69, 0xc0, 0x46, 0x53, 0x66, 0x89, 0x69, 
-0xc0, 0x46, 0x91, 0x66, 0x11, 0x49, 0xc0, 0x46, 0xd1, 0x66, 0x16, 0x67, 
-0x56, 0x67, 0x10, 0x4b, 0xc0, 0x18, 0x90, 0x67, 0x56, 0x61, 0xd7, 0x61, 
-0xd0, 0x1d, 0x69, 0x30, 0x07, 0x73, 0xf0, 0xbc, 
-0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0x50, 0x2c, 0x00, 0x80, 
-0xd0, 0x2c, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x5c, 0x04, 0x00, 0x00, 
-0x30, 0x01, 0x18, 0x00, 0xf8, 0x28, 0x00, 0x80, 0x80, 0x54, 0xff, 0xff, 
-0x7c, 0x05, 0x00, 0x00, 0x38, 0x01, 0x18, 0x00, 0x90, 0x54, 0xff, 0xff, 
-0x7c, 0x07, 0x00, 0x00, 0x90, 0xb4, 0x00, 0x21, 0x1c, 0x4a, 0xbb, 0x23, 
-0x1b, 0x01, 0xd7, 0x18, 0xf9, 0x72, 0x19, 0x23, 0xdb, 0x01, 0xd0, 0x18, 
-0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x81, 0x61, 0x59, 0x60, 0xb9, 0x72, 
-0x01, 0x27, 0x1f, 0x73, 0x19, 0x61, 0x17, 0x23, 0xdb, 0x01, 0xd3, 0x18, 
-0xd9, 0x63, 0x13, 0x4b, 0x51, 0x27, 0xbf, 0x03, 0xc3, 0x62, 0x3b, 0x60, 
-0x44, 0x69, 0xe4, 0x18, 0x04, 0x63, 0x04, 0x3c, 0x7c, 0x60, 0x01, 0x24, 
-0xe4, 0x02, 0x44, 0x63, 0x0d, 0x4c, 0xc0, 0x46, 0xbc, 0x60, 0xc4, 0x6a, 
-0xc0, 0x46, 0x04, 0x62, 0x44, 0x69, 0xe4, 0x18, 0x0a, 0x4b, 0xe3, 0x18, 
-0xfb, 0x60, 0xc3, 0x6a, 0xc0, 0x46, 0x43, 0x62, 0x03, 0x6a, 0xc0, 0x46, 
-0xc3, 0x61, 0x81, 0x63, 0x51, 0x64, 0x91, 0x64, 0xd1, 0x65, 0xd1, 0x66, 
-0x90, 0xbc, 0x70, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 
-0xfc, 0x07, 0x00, 0x00, 0xfc, 0xf7, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x22, 
-0x1c, 0x49, 0xc9, 0x23, 0x1b, 0x01, 0xc8, 0x18, 0x02, 0x70, 0x01, 0x20, 
-0xbb, 0x23, 0x1b, 0x01, 0xcb, 0x18, 0x58, 0x72, 0x18, 0x48, 0x03, 0x1c, 
-0x00, 0x27, 0xdc, 0x1d, 0xc1, 0x34, 0x1c, 0x65, 0x23, 0x1c, 0x01, 0x37, 
-0x3f, 0x2f, 0xf8, 0xd3, 0x1a, 0x65, 0x19, 0x23, 0xdb, 0x01, 0xcf, 0x18, 
-0x33, 0x23, 0x9b, 0x01, 0xcc, 0x18, 0xfa, 0x60, 0x60, 0x61, 0x40, 0x20, 
-0xb8, 0x60, 0xa2, 0x61, 0xe2, 0x61, 0xca, 0x64, 0x0a, 0x66, 0x0d, 0x48, 
-0xc0, 0x46, 0xc2, 0x60, 0x0c, 0x48, 0x00, 0x6b, 0xc0, 0x06, 0xc0, 0x0e, 
-0xb8, 0x63, 0x0b, 0x48, 0x65, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x02, 0x68, 
-0xc0, 0x46, 0x8a, 0x83, 0x42, 0x68, 0xc0, 0x46, 0xca, 0x83, 0x80, 0x68, 
-0xc0, 0x46, 0x20, 0x80, 0x90, 0xbc, 0x70, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0x3c, 0xbd, 0x20, 0x40, 0x3c, 0xef, 0x20, 0x40, 0x80, 0x00, 0x14, 0x40, 
-0x40, 0x00, 0x14, 0x40, 0x00, 0x20, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x73, 
-0xcb, 0x1d, 0xff, 0x33, 0x3a, 0x33, 0x88, 0x61, 0xc8, 0x61, 0x18, 0x70, 
-0x06, 0x4a, 0xc0, 0x46, 0x10, 0x65, 0x50, 0x66, 0x90, 0x66, 0x08, 0x70, 
-0x58, 0x70, 0xbb, 0x23, 0x1b, 0x01, 0xd1, 0x18, 0x08, 0x72, 0x70, 0x47, 
-0xa8, 0x04, 0x00, 0x80, 0xe8, 0x0d, 0x00, 0x80, 0xf0, 0xb4, 0x2f, 0x49, 
-0x2f, 0x4a, 0xc0, 0x46, 0x11, 0x61, 0x01, 0x23, 0x9b, 0x02, 0xc8, 0x18, 
-0x50, 0x61, 0x2d, 0x48, 0xc0, 0x46, 0x10, 0x62, 0xdb, 0x00, 0xc3, 0x18, 
-0x53, 0x62, 0x00, 0x23, 0x13, 0x63, 0x53, 0x63, 0x29, 0x4a, 0x2a, 0x4f, 
-0xd4, 0x1d, 0xff, 0x34, 0xfa, 0x34, 0x14, 0xc7, 0x08, 0x3f, 0x3b, 0x61, 
-0x1c, 0x1f, 0x7c, 0x61, 0x26, 0x4f, 0xc0, 0x46, 0x39, 0x60, 0xb8, 0x61, 
-0x79, 0x61, 0xf8, 0x62, 0x3b, 0x63, 0x7b, 0x64, 0xba, 0x64, 0xfa, 0x65, 
-0x22, 0x4f, 0xfe, 0x1d, 0xf9, 0x36, 0x22, 0x4d, 0xec, 0x1d, 0x79, 0x34, 
-0xe6, 0x61, 0x51, 0x26, 0xb6, 0x03, 0x37, 0x61, 0xe4, 0x69, 0xc0, 0x46, 
-0x74, 0x61, 0x2f, 0x67, 0x1d, 0x4d, 0x09, 0x27, 0x7f, 0x04, 0xec, 0x1d, 
-0x75, 0x34, 0x7c, 0x60, 0x3d, 0x60, 0x1b, 0x4c, 0xc0, 0x46, 0x3c, 0x61, 
-0xe6, 0x1d, 0x75, 0x36, 0x7e, 0x61, 0x19, 0x4f, 
-0xc0, 0x46, 0x7c, 0x60, 0x3d, 0x60, 0x0f, 0x1c, 0x00, 0x21, 0xff, 0x24, 
-0x01, 0x34, 0x1d, 0x1c, 0x8b, 0x00, 0xfd, 0x50, 0x01, 0x31, 0xa1, 0x42, 
-0xfa, 0xd3, 0x01, 0x1c, 0x00, 0x20, 0x01, 0x27, 0xff, 0x02, 0x83, 0x00, 
-0xcd, 0x50, 0x01, 0x30, 0xb8, 0x42, 0xfa, 0xd3, 0x00, 0x20, 0x81, 0x00, 
-0x55, 0x50, 0x01, 0x30, 0x80, 0x28, 0xfa, 0xd3, 0xf0, 0xbc, 0x70, 0x47, 
-0x24, 0xa3, 0x20, 0x40, 0x40, 0x01, 0x18, 0x00, 0x24, 0x83, 0x20, 0x40, 
-0x24, 0xa9, 0x20, 0x40, 0x80, 0x01, 0x18, 0x00, 0x28, 0x03, 0x00, 0x80, 
-0x24, 0xa7, 0x20, 0x40, 0xe8, 0x0d, 0x00, 0x80, 0x24, 0xa8, 0x20, 0x40, 
-0xa4, 0xa8, 0x20, 0x40, 0x88, 0x03, 0x00, 0x80, 0xb8, 0xb5, 0x2d, 0x48, 
-0xfd, 0xf7, 0xc6, 0xfa, 0x01, 0x20, 0x2c, 0x49, 0x0a, 0x68, 0x52, 0x0c, 
-0x06, 0xd2, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1, 0x0a, 0x68, 0x92, 0x0a, 
-0x00, 0xd2, 0x00, 0x20, 0x04, 0x06, 0x24, 0x0e, 0x26, 0x4a, 0xd7, 0x1d, 
-0x0d, 0x37, 0x00, 0x23, 0x00, 0x20, 0x9d, 0x00, 0x78, 0x51, 0x01, 0x33, 
-0x04, 0x2b, 0xfa, 0xd3, 0x01, 0x27, 0x3f, 0x05, 0x50, 0x61, 0xf8, 0x60, 
-0xd0, 0x61, 0xf8, 0x61, 0x00, 0x23, 0xdb, 0x43, 0x93, 0x61, 0x3b, 0x61, 
-0x13, 0x62, 0x3b, 0x62, 0x00, 0x27, 0x1c, 0x4b, 0x8d, 0x68, 0xc0, 0x46, 
-0x00, 0x95, 0x8d, 0x69, 0xc0, 0x46, 0x00, 0x95, 0x00, 0x2c, 0x0b, 0xd0, 
-0xdd, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x9d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 
-0x5d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x1d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 
-0x01, 0x37, 0x40, 0x2f, 0xe8, 0xd3, 0x00, 0x27, 0x6c, 0x46, 0x01, 0x23, 
-0x5b, 0x07, 0x1c, 0x43, 0x01, 0xe0, 0x20, 0x60, 0x01, 0x37, 0x0d, 0x68, 
-0x2b, 0x09, 0x02, 0xd2, 0x80, 0x2f, 0xf8, 0xd3, 0x01, 0xe0, 0x80, 0x2f, 
-0x03, 0xd3, 0x09, 0x49, 0x4b, 0x6e, 0x01, 0x33, 0x4b, 0x66, 0xd0, 0x62, 
-0x07, 0x48, 0xfd, 0xf7, 0x71, 0xfa, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xf4, 0x01, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0x01, 0x18, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x04, 0x02, 0xff, 0xff, 
-0x90, 0xb4, 0x00, 0x21, 0x0e, 0x4f, 0x0f, 0x4a, 0x00, 0x20, 0x4c, 0x01, 
-0x64, 0x1a, 0xa4, 0x00, 0xa3, 0x18, 0x58, 0x60, 0x98, 0x60, 0x18, 0x64, 
-0x58, 0x64, 0x10, 0x53, 0x58, 0x80, 0xcc, 0x00, 0xe4, 0x19, 0x98, 0x67, 
-0xdc, 0x62, 0x01, 0x31, 0x03, 0x29, 0xee, 0xd3, 0x06, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x48, 0x60, 0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0xbc, 
-0x70, 0x47, 0x00, 0x00, 0x58, 0x67, 0x21, 0x40, 0xc8, 0x2a, 0x00, 0x80, 
-0x3c, 0x2c, 0x00, 0x80, 0x00, 0xb5, 0x64, 0x21, 0x07, 0x48, 0xc0, 0x46, 
-0x01, 0x63, 0x00, 0x21, 0xc9, 0x43, 0x41, 0x63, 0x81, 0x63, 0x00, 0x21, 
-0xc1, 0x63, 0x01, 0x64, 0x03, 0x48, 0x28, 0x22, 0x02, 0xf0, 0x06, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0x59, 0x03, 0xff, 0xff, 
-0x80, 0xb4, 0x01, 0x20, 0x40, 0x02, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x60, 
-0x3c, 0x20, 0x48, 0x60, 0x88, 0x60, 0x08, 0x48, 0xc0, 0x46, 0xc8, 0x60, 
-0x00, 0x20, 0x07, 0x4a, 0x87, 0x00, 0xcb, 0x68, 0xc0, 0x46, 0xda, 0x51, 
-0x01, 0x30, 0x10, 0x28, 0xf8, 0xd3, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 
-0x50, 0x2d, 0x00, 0x80, 0x60, 0x2d, 0x00, 0x80, 0xd5, 0x4b, 0xff, 0xff, 
-0x12, 0x49, 0x13, 0x48, 0x67, 0x23, 0x9b, 0x01, 0xca, 0x18, 0x06, 0xc0, 
-0x08, 0x38, 0x11, 0x4b, 0xca, 0x18, 0xc1, 0x60, 
+0xc0, 0x46, 0x91, 0x66, 0x0f, 0x49, 0xc0, 0x46, 0xd1, 0x66, 0x16, 0x67, 
+0x0f, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x90, 0x67, 0x56, 0x67, 0xd7, 0x61, 
+0xd0, 0x1d, 0x69, 0x30, 0x56, 0x61, 0x07, 0x73, 
+0xf0, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 
+0x64, 0x2d, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x30, 0x01, 0x18, 0x00, 
+0x7c, 0x29, 0x00, 0x80, 0xec, 0x54, 0xff, 0xff, 0x38, 0x01, 0x18, 0x00, 
+0xfc, 0x54, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x21, 0x1e, 0x4a, 0xbb, 0x23, 
+0x1b, 0x01, 0xd7, 0x18, 0xf9, 0x73, 0x19, 0x23, 0xdb, 0x01, 0xd0, 0x18, 
+0x01, 0x24, 0xcd, 0x23, 0x1b, 0x01, 0xd3, 0x18, 0xc1, 0x61, 0x1c, 0x70, 
+0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x99, 0x60, 0xb9, 0x73, 0x59, 0x61, 
+0x2f, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x19, 0x60, 0x13, 0x4b, 0x51, 0x27, 
+0xbf, 0x03, 0x03, 0x63, 0x3b, 0x60, 0x84, 0x69, 0xe4, 0x18, 0x44, 0x63, 
+0x04, 0x3c, 0x7c, 0x60, 0x01, 0x24, 0xe4, 0x02, 0x84, 0x63, 0x0e, 0x4c, 
+0xc0, 0x46, 0xbc, 0x60, 0x04, 0x6b, 0xc0, 0x46, 0x44, 0x62, 0x84, 0x69, 
+0xe4, 0x18, 0x0b, 0x4b, 0xe3, 0x18, 0xfb, 0x60, 0x03, 0x6b, 0xc0, 0x46, 
+0x83, 0x62, 0x43, 0x6a, 0xc0, 0x46, 0x03, 0x62, 0xc1, 0x63, 0x51, 0x64, 
+0x91, 0x64, 0xd1, 0x65, 0xd1, 0x66, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0xfc, 0x07, 0x00, 0x00, 
+0xfc, 0xf7, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x22, 0x1b, 0x49, 0xc9, 0x23, 
+0x1b, 0x01, 0xc8, 0x18, 0x02, 0x71, 0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 
+0xcb, 0x18, 0x58, 0x73, 0x17, 0x48, 0x03, 0x1c, 0x00, 0x27, 0xdc, 0x1d, 
+0xc1, 0x34, 0x1c, 0x65, 0x23, 0x1c, 0x01, 0x37, 0x3f, 0x2f, 0xf8, 0xd3, 
+0x1a, 0x65, 0x19, 0x23, 0xdb, 0x01, 0xcf, 0x18, 0x33, 0x23, 0x9b, 0x01, 
+0xcb, 0x18, 0x3a, 0x61, 0x98, 0x61, 0x40, 0x20, 0xf8, 0x60, 0xda, 0x61, 
+0x1a, 0x62, 0xca, 0x64, 0x0a, 0x66, 0x0c, 0x48, 0xc0, 0x46, 0xc2, 0x60, 
+0x0b, 0x48, 0x00, 0x6b, 0xc0, 0x06, 0xc0, 0x0e, 0xf8, 0x63, 0x0a, 0x48, 
+0x01, 0x68, 0xc0, 0x46, 0x19, 0x80, 0x41, 0x68, 0xc0, 0x46, 0x59, 0x80, 
+0x80, 0x68, 0xc0, 0x46, 0x98, 0x80, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x3c, 0xbd, 0x20, 0x40, 0x3c, 0xef, 0x20, 0x40, 
+0x80, 0x00, 0x14, 0x40, 0x40, 0x00, 0x14, 0x40, 0x00, 0x20, 0x0a, 0x49, 
+0xc0, 0x46, 0x08, 0x73, 0xcb, 0x1d, 0xff, 0x33, 0x3a, 0x33, 0x88, 0x61, 
+0xc8, 0x61, 0x18, 0x70, 0x06, 0x4a, 0xc0, 0x46, 0x10, 0x65, 0x50, 0x66, 
+0x90, 0x66, 0x08, 0x70, 0x58, 0x70, 0xbb, 0x23, 0x1b, 0x01, 0xd1, 0x18, 
+0x08, 0x73, 0x70, 0x47, 0x28, 0x05, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 
+0xf0, 0xb4, 0x2f, 0x49, 0x2f, 0x4a, 0xc0, 0x46, 0x11, 0x61, 0x01, 0x23, 
+0x9b, 0x02, 0xc8, 0x18, 0x50, 0x61, 0x2d, 0x48, 0xc0, 0x46, 0x10, 0x62, 
+0xdb, 0x00, 0xc3, 0x18, 0x53, 0x62, 0x00, 0x23, 0x13, 0x63, 0x53, 0x63, 
+0x29, 0x4a, 0x2a, 0x4f, 0xd4, 0x1d, 0xff, 0x34, 0xfa, 0x34, 0x14, 0xc7, 
+0x08, 0x3f, 0x3b, 0x61, 0x1c, 0x1f, 0x7c, 0x61, 0x26, 0x4f, 0xc0, 0x46, 
+0x39, 0x60, 0xb8, 0x61, 0x79, 0x61, 0xf8, 0x62, 0x3b, 0x63, 0x7b, 0x64, 
+0xba, 0x64, 0xfa, 0x65, 0x22, 0x4f, 0xfe, 0x1d, 0xf9, 0x36, 0x22, 0x4d, 
+0xec, 0x1d, 0x79, 0x34, 0x26, 0x62, 0x51, 0x26, 0xb6, 0x03, 0x37, 0x61, 
+0x24, 0x6a, 0xc0, 0x46, 0x74, 0x61, 0x2f, 0x67, 0x1d, 0x4d, 0x09, 0x27, 
+0x7f, 0x04, 0xec, 0x1d, 0x75, 0x34, 0x7c, 0x60, 0x3d, 0x60, 0x1b, 0x4c, 
+0xc0, 0x46, 0x3c, 0x61, 0xe6, 0x1d, 0x75, 0x36, 0x7e, 0x61, 0x19, 0x4f, 
+0xc0, 0x46, 0x7c, 0x60, 0x3d, 0x60, 0x0f, 0x1c, 
+0x00, 0x21, 0xff, 0x24, 0x01, 0x34, 0x1d, 0x1c, 0x8b, 0x00, 0xfd, 0x50, 
+0x01, 0x31, 0xa1, 0x42, 0xfa, 0xd3, 0x01, 0x1c, 0x00, 0x20, 0x01, 0x27, 
+0xff, 0x02, 0x83, 0x00, 0xcd, 0x50, 0x01, 0x30, 0xb8, 0x42, 0xfa, 0xd3, 
+0x00, 0x20, 0x81, 0x00, 0x55, 0x50, 0x01, 0x30, 0x80, 0x28, 0xfa, 0xd3, 
+0xf0, 0xbc, 0x70, 0x47, 0x24, 0xa3, 0x20, 0x40, 0x40, 0x01, 0x18, 0x00, 
+0x24, 0x83, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x80, 0x01, 0x18, 0x00, 
+0xa8, 0x03, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 0x08, 0x04, 0x00, 0x80, 
+0xb8, 0xb5, 0x2c, 0x48, 0xfc, 0xf7, 0x0a, 0xff, 0x01, 0x20, 0x2b, 0x49, 
+0x0a, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1, 
+0x0a, 0x68, 0x92, 0x0a, 0x00, 0xd2, 0x00, 0x20, 0x04, 0x06, 0x24, 0x0e, 
+0x25, 0x4a, 0xd7, 0x1d, 0x0d, 0x37, 0x00, 0x23, 0x00, 0x20, 0x9d, 0x00, 
+0x78, 0x51, 0x01, 0x33, 0x04, 0x2b, 0xfa, 0xd3, 0x01, 0x27, 0x3f, 0x05, 
+0x50, 0x61, 0xf8, 0x60, 0xd0, 0x61, 0xf8, 0x61, 0x00, 0x23, 0xdb, 0x43, 
+0x93, 0x61, 0x3b, 0x61, 0x13, 0x62, 0x3b, 0x62, 0x00, 0x27, 0x1b, 0x4b, 
+0x8d, 0x68, 0xc0, 0x46, 0x00, 0x95, 0x8d, 0x69, 0xc0, 0x46, 0x00, 0x95, 
+0x00, 0x2c, 0x0b, 0xd0, 0xdd, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x9d, 0x6b, 
+0xc0, 0x46, 0x00, 0x95, 0x5d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x1d, 0x6b, 
+0xc0, 0x46, 0x00, 0x95, 0x01, 0x37, 0x40, 0x2f, 0xe8, 0xd3, 0x00, 0x27, 
+0x6c, 0x46, 0x01, 0x23, 0x5b, 0x07, 0x1c, 0x43, 0x01, 0xe0, 0x20, 0x60, 
+0x01, 0x37, 0x0d, 0x68, 0x2b, 0x09, 0x02, 0xd2, 0x80, 0x2f, 0xf8, 0xd3, 
+0x01, 0xe0, 0x80, 0x2f, 0x03, 0xd3, 0x08, 0x49, 0x4b, 0x6e, 0x01, 0x33, 
+0x4b, 0x66, 0xd0, 0x62, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xf4, 0x01, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0x01, 0x18, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x90, 0xb4, 0x00, 0x21, 
+0x0e, 0x4f, 0x0f, 0x4a, 0x00, 0x20, 0x4c, 0x01, 0x64, 0x1a, 0xa4, 0x00, 
+0xa3, 0x18, 0x58, 0x60, 0x98, 0x60, 0x18, 0x64, 0x58, 0x64, 0x10, 0x53, 
+0x58, 0x80, 0xcc, 0x00, 0xe4, 0x19, 0x98, 0x67, 0xdc, 0x62, 0x01, 0x31, 
+0x03, 0x29, 0xee, 0xd3, 0x06, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x48, 0x60, 
+0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0x58, 0x67, 0x21, 0x40, 0x5c, 0x2b, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80, 
+0x64, 0x21, 0x05, 0x48, 0xc0, 0x46, 0x01, 0x63, 0x00, 0x21, 0xc9, 0x43, 
+0x41, 0x63, 0x81, 0x63, 0x00, 0x21, 0xc1, 0x63, 0x01, 0x64, 0x70, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb4, 0x01, 0x20, 0x40, 0x02, 0x0a, 0x49, 
+0xc0, 0x46, 0x08, 0x60, 0x3c, 0x20, 0x48, 0x60, 0x88, 0x60, 0x08, 0x48, 
+0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x07, 0x4a, 0x87, 0x00, 0xcb, 0x68, 
+0xc0, 0x46, 0xda, 0x51, 0x01, 0x30, 0x10, 0x28, 0xf8, 0xd3, 0x80, 0xbc, 
+0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 0xf4, 0x2d, 0x00, 0x80, 
+0x49, 0x4c, 0xff, 0xff, 0x12, 0x49, 0x13, 0x48, 0x67, 0x23, 0x9b, 0x01, 
+0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x11, 0x4b, 0xca, 0x18, 0xc1, 0x60, 
 0x82, 0x60, 0x01, 0x61, 0x0f, 0x49, 0x10, 0x48, 0xa7, 0x23, 0x9b, 0x01, 
 0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x0e, 0x4b, 0xca, 0x18, 0xc1, 0x60, 
-0x82, 0x60, 0x01, 0x61, 0x0c, 0x48, 0x0d, 0x49, 0x67, 0x23, 0x9b, 0x01, 
-0xc2, 0x18, 0x05, 0xc1, 0x08, 0x39, 0x05, 0x4b, 0xc2, 0x18, 0xc8, 0x60, 
-0x8a, 0x60, 0x08, 0x61, 0x70, 0x47, 0x00, 0x00, 0x58, 0x1f, 0x21, 0x40, 
-0xb4, 0x2d, 0x00, 0x80, 0xfc, 0x1f, 0x00, 0x00, 0x58, 0xef, 0x20, 0x40, 
-0xa0, 0x2d, 0x00, 0x80, 0xfc, 0x2f, 0x00, 0x00, 0x58, 0x3f, 0x21, 0x40, 
-0xc8, 0x2d, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21, 0x40, 0x4c, 0x00, 0x20, 
-0x0a, 0x01, 0x12, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 0xd0, 0x62, 
-0x10, 0x63, 0x50, 0x63, 0x90, 0x63, 0x01, 0x31, 0x03, 0x29, 0xf3, 0xd3, 
-0x3a, 0x49, 0xc0, 0x46, 0xc8, 0x62, 0x08, 0x63, 0x48, 0x63, 0x20, 0x60, 
-0x01, 0x21, 0xe3, 0x1d, 0x59, 0x33, 0x60, 0x60, 0x19, 0x71, 0x18, 0x72, 
-0x98, 0x71, 0x98, 0x72, 0x59, 0x71, 0x58, 0x72, 0xd8, 0x71, 0xd8, 0x72, 
-0xe2, 0x1d, 0x49, 0x32, 0x11, 0x73, 0x19, 0x70, 0x90, 0x73, 0x98, 0x70, 
-0x51, 0x73, 0x59, 0x70, 0xd0, 0x73, 0xd8, 0x70, 0x11, 0x71, 0x11, 0x72, 
-0x90, 0x71, 0x90, 0x72, 0x50, 0x71, 0x50, 0x72, 0xd0, 0x71, 0xd0, 0x72, 
-0x18, 0x73, 0x02, 0x22, 0xe7, 0x1d, 0x69, 0x37, 0x3a, 0x70, 0x99, 0x73, 
-0xba, 0x70, 0x58, 0x73, 0x78, 0x70, 0xd8, 0x73, 0xf8, 0x70, 0x39, 0x71, 
-0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71, 0x7a, 0x72, 0xf9, 0x71, 
-0xf9, 0x72, 0x39, 0x73, 0xe3, 0x1d, 0x79, 0x33, 0x1a, 0x70, 0xb9, 0x73, 
-0x99, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73, 0xd9, 0x70, 0x1a, 0x71, 
-0x1a, 0x72, 0x99, 0x71, 0x9a, 0x72, 0x58, 0x71, 0x5a, 0x72, 0xd9, 0x71, 
-0xda, 0x72, 0x19, 0x73, 0xe7, 0x1d, 0x89, 0x37, 0x3a, 0x70, 0x99, 0x73, 
-0xb9, 0x70, 0x58, 0x73, 0x7a, 0x70, 0xd9, 0x73, 0xf9, 0x70, 0x39, 0x71, 
-0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71, 0x7a, 0x72, 0xf9, 0x71, 
-0xf9, 0x72, 0x3a, 0x73, 0xe3, 0x1d, 0x99, 0x33, 0x1a, 0x70, 0xb9, 0x73, 
-0x9a, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73, 0xda, 0x70, 0x19, 0x71, 
-0x1a, 0x72, 0x99, 0x71, 0x99, 0x72, 0x58, 0x71, 0x5a, 0x72, 0xd9, 0x71, 
-0xd9, 0x72, 0x20, 0x61, 0xe0, 0x60, 0x60, 0x61, 0xa0, 0x60, 0x90, 0xbc, 
-0x70, 0x47, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x80, 0x68, 0x19, 0x00, 0x80, 
-0x81, 0x20, 0x00, 0x02, 0x01, 0x49, 0xc0, 0x46, 0x88, 0x62, 0x70, 0x47, 
-0xc0, 0x00, 0x14, 0x00, 0x0a, 0x49, 0x13, 0x23, 0xdb, 0x01, 0xc8, 0x18, 
-0x25, 0x23, 0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x63, 0x00, 0x21, 0xc2, 0x1d, 
+0x82, 0x60, 0x01, 0x61, 0x0c, 0x48, 0x0d, 0x49, 
+0x67, 0x23, 0x9b, 0x01, 0xc2, 0x18, 0x05, 0xc1, 0x08, 0x39, 0x05, 0x4b, 
+0xc2, 0x18, 0xc8, 0x60, 0x8a, 0x60, 0x08, 0x61, 0x70, 0x47, 0x00, 0x00, 
+0x58, 0x1f, 0x21, 0x40, 0x48, 0x2e, 0x00, 0x80, 0xfc, 0x1f, 0x00, 0x00, 
+0x58, 0xef, 0x20, 0x40, 0x34, 0x2e, 0x00, 0x80, 0xfc, 0x2f, 0x00, 0x00, 
+0x58, 0x3f, 0x21, 0x40, 0x5c, 0x2e, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21, 
+0x40, 0x4c, 0x00, 0x20, 0x0a, 0x01, 0x12, 0x19, 0x19, 0x23, 0xdb, 0x01, 
+0xd2, 0x18, 0xd0, 0x62, 0x10, 0x63, 0x50, 0x63, 0x90, 0x63, 0x01, 0x31, 
+0x03, 0x29, 0xf3, 0xd3, 0x3a, 0x49, 0xc0, 0x46, 0x08, 0x63, 0x48, 0x63, 
+0x88, 0x63, 0x20, 0x60, 0x01, 0x21, 0xe3, 0x1d, 0x59, 0x33, 0x60, 0x60, 
+0x19, 0x71, 0x18, 0x72, 0x98, 0x71, 0x98, 0x72, 0x59, 0x71, 0x58, 0x72, 
+0xd8, 0x71, 0xd8, 0x72, 0xe2, 0x1d, 0x49, 0x32, 0x11, 0x73, 0x19, 0x70, 
+0x90, 0x73, 0x98, 0x70, 0x51, 0x73, 0x59, 0x70, 0xd0, 0x73, 0xd8, 0x70, 
+0x11, 0x71, 0x11, 0x72, 0x90, 0x71, 0x90, 0x72, 0x50, 0x71, 0x50, 0x72, 
+0xd0, 0x71, 0xd0, 0x72, 0x18, 0x73, 0x02, 0x22, 0xe7, 0x1d, 0x69, 0x37, 
+0x3a, 0x70, 0x99, 0x73, 0xba, 0x70, 0x58, 0x73, 0x78, 0x70, 0xd8, 0x73, 
+0xf8, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71, 
+0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x39, 0x73, 0xe3, 0x1d, 0x79, 0x33, 
+0x1a, 0x70, 0xb9, 0x73, 0x99, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73, 
+0xd9, 0x70, 0x1a, 0x71, 0x1a, 0x72, 0x99, 0x71, 0x9a, 0x72, 0x58, 0x71, 
+0x5a, 0x72, 0xd9, 0x71, 0xda, 0x72, 0x19, 0x73, 0xe7, 0x1d, 0x89, 0x37, 
+0x3a, 0x70, 0x99, 0x73, 0xb9, 0x70, 0x58, 0x73, 0x7a, 0x70, 0xd9, 0x73, 
+0xf9, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71, 
+0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x3a, 0x73, 0xe3, 0x1d, 0x99, 0x33, 
+0x1a, 0x70, 0xb9, 0x73, 0x9a, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73, 
+0xda, 0x70, 0x19, 0x71, 0x1a, 0x72, 0x99, 0x71, 0x99, 0x72, 0x58, 0x71, 
+0x5a, 0x72, 0xd9, 0x71, 0xd9, 0x72, 0x20, 0x61, 0xe0, 0x60, 0x60, 0x61, 
+0xa0, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80, 
+0xe8, 0x19, 0x00, 0x80, 0x81, 0x20, 0x00, 0x02, 0x01, 0x49, 0xc0, 0x46, 
+0x88, 0x62, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x09, 0x49, 0x0a, 0x4b, 
+0xc8, 0x18, 0x04, 0x3b, 0xc9, 0x18, 0x08, 0x60, 0x00, 0x21, 0xc2, 0x1d, 
 0x29, 0x32, 0xc2, 0x61, 0x10, 0x1c, 0x01, 0x31, 0x08, 0x29, 0xf8, 0xd3, 
 0xc1, 0x1f, 0x29, 0x39, 0x00, 0x20, 0xc8, 0x61, 0x70, 0x47, 0x00, 0x00, 
-0xe8, 0x0d, 0x00, 0x80, 0x06, 0x48, 0x07, 0x49, 0xc0, 0x46, 0x08, 0x80, 
-0x48, 0x80, 0x00, 0x20, 0x88, 0x80, 0xc8, 0x80, 0x88, 0x60, 0x04, 0x49, 
-0xc0, 0x46, 0x48, 0x61, 0x88, 0x61, 0x70, 0x47, 0xff, 0xff, 0x00, 0x00, 
-0xc8, 0x29, 0x00, 0x80, 0xec, 0x05, 0x00, 0x80, 0x00, 0x21, 0x06, 0x48, 
-0xc2, 0x1d, 0x19, 0x32, 0xc1, 0x60, 0x01, 0x61, 0xc1, 0x61, 0x01, 0x62, 
-0x11, 0x71, 0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 
-0xec, 0x05, 0x00, 0x80, 0x09, 0x48, 0x0a, 0x4b, 0xc0, 0x46, 0x18, 0x60, 
-0x00, 0x21, 0xc2, 0x1d, 0x4d, 0x32, 0xc2, 0x60, 
+0x68, 0x0e, 0x00, 0x80, 0x84, 0x09, 0x00, 0x00, 0x06, 0x48, 0x07, 0x49, 
+0xc0, 0x46, 0x08, 0x80, 0x48, 0x80, 0x00, 0x20, 0x88, 0x80, 0xc8, 0x80, 
+0x88, 0x60, 0x04, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x88, 0x61, 0x70, 0x47, 
+0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0x00, 0x21, 0x06, 0x48, 0xc2, 0x1d, 0x19, 0x32, 0xc1, 0x60, 0x01, 0x61, 
+0xc1, 0x61, 0x01, 0x62, 0x11, 0x71, 0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 
+0x70, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x09, 0x48, 0x0a, 0x4b, 
+0xc0, 0x46, 0x18, 0x60, 0x00, 0x21, 0xc2, 0x1d, 0x4d, 0x32, 0xc2, 0x60, 
 0x10, 0x1c, 0x01, 0x31, 0x14, 0x29, 0xf8, 0xd3, 0xc1, 0x1f, 0x4d, 0x39, 
 0x00, 0x20, 0xc8, 0x60, 0x58, 0x60, 0x98, 0x60, 0x70, 0x47, 0x00, 0x00, 
-0x58, 0x07, 0x00, 0x80, 0xec, 0x05, 0x00, 0x80, 0x00, 0xb5, 0x0c, 0x49, 
-0x0c, 0x48, 0xfd, 0xf7, 0xea, 0xf8, 0x0c, 0x48, 0x00, 0x6a, 0x01, 0x23, 
-0xdb, 0x03, 0x98, 0x43, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x62, 0x0a, 0x48, 
-0xc1, 0x68, 0x01, 0x29, 0x06, 0xd1, 0x80, 0x23, 0xc1, 0x6f, 0x19, 0x43, 
-0xc1, 0x67, 0x07, 0x48, 0xc0, 0x46, 0x01, 0x60, 0x08, 0xbc, 0x18, 0x47, 
-0x59, 0xcd, 0x21, 0x40, 0x61, 0xa1, 0x21, 0x40, 0xc0, 0x00, 0x18, 0x40, 
-0xc0, 0x00, 0x18, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x01, 0x11, 0x00, 
-0x00, 0xb5, 0x10, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x06, 0xd1, 0x80, 0x23, 
-0xc1, 0x6f, 0x99, 0x43, 0xc1, 0x67, 0x0d, 0x48, 0xc0, 0x46, 0x01, 0x60, 
-0x0c, 0x4b, 0x0d, 0x48, 0x0d, 0x4a, 0x00, 0x21, 0xfd, 0xf7, 0xb9, 0xf8, 
-0x0c, 0x48, 0x41, 0x8d, 0x01, 0x31, 0x41, 0x85, 0x00, 0x21, 0xc1, 0x85, 
-0x0a, 0x48, 0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03, 0x18, 0x43, 0x09, 0x49, 
-0xc0, 0x46, 0x08, 0x62, 0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 
-0x00, 0x01, 0x11, 0x00, 0xf1, 0xcc, 0x21, 0x40, 0x61, 0xa1, 0x21, 0x40, 
+0xd8, 0x07, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0x00, 0xb5, 0x0b, 0x49, 0x0b, 0x48, 0xfc, 0xf7, 0x3a, 0xfd, 0x0b, 0x48, 
+0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03, 0x98, 0x43, 0x09, 0x49, 0xc0, 0x46, 
+0x08, 0x62, 0x09, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f, 
+0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x08, 0xbc, 0x18, 0x47, 
+0x8d, 0xd5, 0x21, 0x40, 0xc1, 0xa8, 0x21, 0x40, 0xc0, 0x00, 0x18, 0x40, 
+0xc0, 0x00, 0x18, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x0f, 0x48, 
+0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68, 
+0x99, 0x43, 0x01, 0x60, 0x0b, 0x4b, 0x0c, 0x48, 0x0c, 0x4a, 0x00, 0x21, 
+0xfc, 0xf7, 0x0f, 0xfd, 0x0b, 0x48, 0x41, 0x8d, 0x01, 0x31, 0x41, 0x85, 
+0x00, 0x21, 0xc1, 0x85, 0x09, 0x48, 0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03, 
+0x18, 0x43, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x62, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x25, 0xd5, 0x21, 0x40, 0xc1, 0xa8, 0x21, 0x40, 
 0xb8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 
-0xc0, 0x00, 0x18, 0x00, 0xf0, 0xb5, 0xfe, 0xf7, 0xa3, 0xfe, 0x19, 0x4c, 
-0x10, 0x26, 0xe0, 0x68, 0x01, 0x28, 0x05, 0xd1, 0x60, 0x88, 0x00, 0x28, 
-0x02, 0xd1, 0x19, 0x20, 0xa0, 0x67, 0x00, 0xe0, 0xa6, 0x67, 0x00, 0x20, 
-0x07, 0x23, 0x5b, 0x02, 0xe5, 0x18, 0xc1, 0x43, 0xa8, 0x61, 0x29, 0x62, 
-0x59, 0x08, 0xa1, 0x27, 0x7f, 0x03, 0x79, 0x60, 0x0f, 0x21, 0x79, 0x60, 
-0xe1, 0x1d, 0xb9, 0x31, 0x08, 0x70, 0x01, 0x20, 0xb8, 0x60, 0x40, 0x02, 
-0xb8, 0x60, 0x00, 0xf0, 0x47, 0xfa, 0x00, 0xf0, 0xd9, 0xfa, 0x04, 0x20, 
-0xb8, 0x60, 0x07, 0x20, 0x78, 0x61, 0x7e, 0x60, 0x1b, 0x23, 0xdb, 0x01, 
-0xe0, 0x18, 0x40, 0x8b, 0x04, 0x23, 0x18, 0x40, 0xa8, 0x62, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0x80, 0xb4, 0x02, 0x1c, 
-0x00, 0x20, 0xff, 0x23, 0x01, 0x33, 0x9a, 0x42, 0x08, 0xd0, 0x01, 0x29, 
-0x00, 0xd1, 0x01, 0x20, 0x00, 0x2a, 0x01, 0xd1, 0x02, 0x23, 0x18, 0x43, 
-0x80, 0xbc, 0x70, 0x47, 0x18, 0x49, 0xca, 0x68, 0x18, 0x4b, 0x01, 0x2a, 
-0x0b, 0xd1, 0x4a, 0x88, 0x00, 0x2a, 0x08, 0xd1, 0xd9, 0x8a, 0x0a, 0x09, 
-0x00, 0xd3, 0x02, 0x20, 0x49, 0x09, 0xef, 0xd3, 0x01, 0x23, 0x18, 0x43, 
-0xec, 0xe7, 0x0a, 0x79, 0x00, 0x2a, 0x03, 0xd0, 0x18, 0x8a, 0x80, 0x07, 
-0x80, 0x0f, 0xe5, 0xe7, 0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x0a, 0x88, 
-0xff, 0x27, 0x01, 0x37, 0x17, 0x40, 0x0b, 0x49, 0x49, 0x88, 0x03, 0xd0, 
-0x4b, 0x0a, 0x01, 0xd3, 0x03, 0x20, 0xd7, 0xe7, 0x13, 0x0a, 0x03, 0xd3, 
-0x0b, 0x0a, 0x01, 0xd3, 0x02, 0x20, 0xd1, 0xe7, 0xd2, 0x09, 0xcf, 0xd3, 
-0xc9, 0x09, 0xcd, 0xd3, 0x01, 0x20, 0xcb, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 
-0xa8, 0x1b, 0x00, 0x80, 0x88, 0x1b, 0x00, 0x80, 0xf0, 0xb5, 0xc1, 0xb0, 
-0x01, 0x20, 0x00, 0x07, 0x52, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x52, 0x48, 
-0x42, 0x69, 0x40, 0x0d, 0xa1, 0x21, 0x49, 0x03, 0x48, 0x60, 0x50, 0x48, 
-0xc0, 0x6a, 0x50, 0x4b, 0x18, 0x43, 0x00, 0x21, 0x03, 0x03, 0x1b, 0x0b, 
-0x4e, 0x4c, 0x27, 0x6f, 0x3d, 0x03, 0x2d, 0x0b, 
+0xc0, 0x00, 0x18, 0x00, 0xf0, 0xb5, 0xfe, 0xf7, 0x9b, 0xfe, 0x1b, 0x4c, 
+0x10, 0x26, 0xe0, 0x68, 0x01, 0x28, 0x08, 0xd1, 0x60, 0x88, 0x00, 0x28, 
+0x05, 0xd1, 0x20, 0x79, 0x00, 0x28, 0x02, 0xd1, 0x19, 0x20, 0xa0, 0x67, 
+0x00, 0xe0, 0xa6, 0x67, 0x00, 0x20, 0x07, 0x23, 0x5b, 0x02, 0xe5, 0x18, 
+0xc1, 0x43, 0xe8, 0x61, 0x69, 0x62, 0x59, 0x08, 0xa1, 0x27, 0x7f, 0x03, 
+0x79, 0x60, 0x0f, 0x21, 0x79, 0x60, 0xe1, 0x1d, 0xb9, 0x31, 0x08, 0x71, 
+0x01, 0x20, 0xb8, 0x60, 0x40, 0x02, 0xb8, 0x60, 0x00, 0xf0, 0x4c, 0xfa, 
+0x00, 0xf0, 0xf0, 0xfa, 0x04, 0x20, 0xb8, 0x60, 0x07, 0x20, 0x78, 0x61, 
+0x7e, 0x60, 0x1b, 0x23, 0xdb, 0x01, 0xe0, 0x18, 0xc0, 0x8b, 0x04, 0x23, 
+0x18, 0x40, 0xe8, 0x62, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x90, 0xb4, 0x02, 0x1c, 0x00, 0x20, 0xff, 0x23, 
+0x01, 0x33, 0x9a, 0x42, 0x08, 0xd0, 0x01, 0x29, 0x00, 0xd1, 0x01, 0x20, 
+0x00, 0x2a, 0x01, 0xd1, 0x02, 0x23, 0x18, 0x43, 0x90, 0xbc, 0x70, 0x47, 
+0x1b, 0x4a, 0xd7, 0x68, 0x1a, 0x4b, 0x19, 0x79, 0x1c, 0x1c, 0x37, 0x23, 
+0x9b, 0x01, 0xe3, 0x18, 0x01, 0x2f, 0x0d, 0xd1, 0x57, 0x88, 0x00, 0x2f, 
+0x0a, 0xd1, 0x00, 0x29, 0x0a, 0xd1, 0x59, 0x8b, 0x0a, 0x09, 0x00, 0xd3, 
+0x02, 0x20, 0x49, 0x09, 0xe8, 0xd3, 0x01, 0x23, 0x18, 0x43, 0xe5, 0xe7, 
+0x00, 0x29, 0x03, 0xd0, 0x98, 0x8a, 0x80, 0x07, 0x80, 0x0f, 0xdf, 0xe7, 
+0x6d, 0x23, 0x5b, 0x01, 0xd1, 0x18, 0x8a, 0x88, 0xff, 0x27, 0x01, 0x37, 
+0x17, 0x40, 0x0a, 0x49, 0xc9, 0x88, 0x03, 0xd0, 0x4b, 0x0a, 0x01, 0xd3, 
+0x03, 0x20, 0xd1, 0xe7, 0x13, 0x0a, 0x03, 0xd3, 0x0b, 0x0a, 0x01, 0xd3, 
+0x02, 0x20, 0xcb, 0xe7, 0xd2, 0x09, 0xc9, 0xd3, 0xc9, 0x09, 0xc7, 0xd3, 
+0x01, 0x20, 0xc5, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x08, 0x1c, 0x00, 0x80, 
+0xf0, 0xb5, 0xc1, 0xb0, 0x01, 0x20, 0x00, 0x07, 0x52, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0x52, 0x48, 0x42, 0x69, 0x40, 0x0d, 0xa1, 0x21, 0x49, 0x03, 
+0x48, 0x60, 0x50, 0x48, 0xc0, 0x6a, 0x50, 0x4b, 0x18, 0x43, 0x00, 0x21, 
+0x03, 0x03, 0x1b, 0x0b, 0x4e, 0x4c, 0x27, 0x6f, 0x3d, 0x03, 0x2d, 0x0b, 
 0xe7, 0x1d, 0x79, 0x37, 0xab, 0x42, 0x1c, 0xd0, 0xe3, 0x1d, 0x79, 0x33, 
-0xdb, 0x69, 0xc0, 0x46, 0x40, 0x93, 0x01, 0x23, 0x9b, 0x07, 0x03, 0x43, 
-0x1b, 0x68, 0xcc, 0x00, 0x6e, 0x46, 0x33, 0x51, 0x01, 0x23, 0x9b, 0x07, 
-0x06, 0x1d, 0x33, 0x43, 0x1b, 0x68, 0x6c, 0x44, 0x63, 0x60, 0x08, 0x30, 
-0x01, 0x31, 0x40, 0x9b, 0x83, 0x42, 0x00, 0xd8, 0x3f, 0x48, 0x03, 0x03, 
-0x1b, 0x0b, 0xab, 0x42, 0xe7, 0xd1, 0x00, 0x20, 0x01, 0x23, 0x1b, 0x03, 
-0x13, 0x40, 0x3c, 0x4c, 0x03, 0xd0, 0x63, 0x6a, 0x01, 0x33, 0x63, 0x62, 
-0x09, 0xe0, 0x13, 0x0b, 0x03, 0xd3, 0x23, 0x6a, 0x01, 0x33, 0x23, 0x62, 
-0x03, 0xe0, 0x37, 0x4b, 0x5c, 0x6d, 0x01, 0x34, 0x5c, 0x65, 0x00, 0x29, 
-0x09, 0xd0, 0x03, 0x1c, 0xdc, 0x00, 0x23, 0x1c, 0x6b, 0x44, 0x5c, 0x68, 
-0x01, 0x30, 0x23, 0x0d, 0x01, 0xd2, 0x88, 0x42, 0xf5, 0xd1, 0x30, 0x4c, 
-0x25, 0x68, 0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c, 0x08, 0xd1, 
-0x24, 0x68, 0xa3, 0x0a, 0x05, 0xd3, 0x20, 0x24, 0x2b, 0x4b, 0xc0, 0x46, 
-0x5c, 0x62, 0x00, 0x24, 0x5c, 0x62, 0x25, 0x4b, 0x23, 0x4c, 0x51, 0x26, 
-0xb6, 0x03, 0x23, 0x67, 0x33, 0x61, 0xfd, 0x69, 0xc0, 0x46, 0x75, 0x61, 
-0x02, 0x25, 0xa1, 0x26, 0x76, 0x03, 0x75, 0x60, 0x01, 0x25, 0xb5, 0x60, 
-0xe6, 0x1d, 0xb9, 0x36, 0x35, 0x70, 0x88, 0x42, 0x21, 0xd0, 0x25, 0x1c, 
-0xc3, 0x00, 0x6c, 0x46, 0xe4, 0x58, 0x2e, 0x6f, 0x6b, 0x44, 0x34, 0x60, 
-0x5b, 0x68, 0x2c, 0x6f, 0xc0, 0x46, 0x63, 0x60, 0x2b, 0x6f, 0x08, 0x33, 
-0x2b, 0x67, 0xfc, 0x69, 0xa3, 0x42, 0x02, 0xd3, 0x12, 0x4b, 0xc0, 0x46, 
-0x2b, 0x67, 0x03, 0x1c, 0xdb, 0x00, 0x6b, 0x44, 0x5c, 0x68, 0x01, 0x30, 
-0x23, 0x0d, 0x04, 0xd3, 0x51, 0x24, 0xa4, 0x03, 0x2b, 0x6f, 0xc0, 0x46, 
-0xa3, 0x61, 0x88, 0x42, 0xde, 0xd1, 0x10, 0x0b, 0x03, 0xd3, 0x0e, 0x49, 
-0x01, 0x20, 0xfc, 0xf7, 0x72, 0xff, 0x41, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x01, 0x14, 0x40, 
-0x00, 0x40, 0x14, 0x40, 0x00, 0x00, 0x20, 0x40, 0xe8, 0x0d, 0x00, 0x80, 
-0x24, 0xa7, 0x20, 0x40, 0x10, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x49, 0x4f, 0xff, 0xff, 
-0xf0, 0xb4, 0x00, 0x21, 0x00, 0x23, 0x07, 0x22, 0x06, 0x24, 0x47, 0x4f, 
-0xc0, 0x46, 0x3c, 0x61, 0x3a, 0x61, 0x01, 0x33, 0x20, 0x2b, 0xf9, 0xd3, 
-0x04, 0x25, 0x3d, 0x61, 0x05, 0x23, 0x3b, 0x61, 0x3c, 0x61, 0x3a, 0x61, 
-0x3c, 0x61, 0x3a, 0x61, 0x3d, 0x61, 0x3b, 0x61, 0x3f, 0x4d, 0xab, 0x6f, 
-0xde, 0x08, 0x02, 0x23, 0x1e, 0x40, 0x04, 0x23, 0x33, 0x43, 0x3b, 0x61, 
-0x05, 0x23, 0x33, 0x43, 0x3b, 0x61, 0xab, 0x6f, 0x9e, 0x08, 0x02, 0x23, 
+0x1b, 0x6a, 0xc0, 0x46, 0x40, 0x93, 0x01, 0x23, 0x9b, 0x07, 0x03, 0x43, 
+0x1b, 0x68, 0xcc, 0x00, 0x6e, 0x46, 0x33, 0x51, 
+0x01, 0x23, 0x9b, 0x07, 0x06, 0x1d, 0x33, 0x43, 0x1b, 0x68, 0x6c, 0x44, 
+0x63, 0x60, 0x08, 0x30, 0x01, 0x31, 0x40, 0x9b, 0x83, 0x42, 0x00, 0xd8, 
+0x3f, 0x48, 0x03, 0x03, 0x1b, 0x0b, 0xab, 0x42, 0xe7, 0xd1, 0x00, 0x20, 
+0x01, 0x23, 0x1b, 0x03, 0x13, 0x40, 0x3c, 0x4c, 0x03, 0xd0, 0x63, 0x6a, 
+0x01, 0x33, 0x63, 0x62, 0x09, 0xe0, 0x13, 0x0b, 0x03, 0xd3, 0x23, 0x6a, 
+0x01, 0x33, 0x23, 0x62, 0x03, 0xe0, 0x37, 0x4b, 0x5c, 0x6d, 0x01, 0x34, 
+0x5c, 0x65, 0x00, 0x29, 0x09, 0xd0, 0x03, 0x1c, 0xdc, 0x00, 0x23, 0x1c, 
+0x6b, 0x44, 0x5c, 0x68, 0x01, 0x30, 0x23, 0x0d, 0x01, 0xd2, 0x88, 0x42, 
+0xf5, 0xd1, 0x30, 0x4c, 0x25, 0x68, 0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 
+0x1b, 0x0c, 0x08, 0xd1, 0x24, 0x68, 0xa3, 0x0a, 0x05, 0xd3, 0x20, 0x24, 
+0x2b, 0x4b, 0xc0, 0x46, 0x5c, 0x62, 0x00, 0x24, 0x5c, 0x62, 0x25, 0x4b, 
+0x23, 0x4c, 0x51, 0x26, 0xb6, 0x03, 0x23, 0x67, 0x33, 0x61, 0x3d, 0x6a, 
+0xc0, 0x46, 0x75, 0x61, 0x02, 0x25, 0xa1, 0x26, 0x76, 0x03, 0x75, 0x60, 
+0x01, 0x25, 0xb5, 0x60, 0xe6, 0x1d, 0xb9, 0x36, 0x35, 0x71, 0x88, 0x42, 
+0x21, 0xd0, 0x25, 0x1c, 0xc3, 0x00, 0x6c, 0x46, 0xe4, 0x58, 0x2e, 0x6f, 
+0x6b, 0x44, 0x34, 0x60, 0x5b, 0x68, 0x2c, 0x6f, 0xc0, 0x46, 0x63, 0x60, 
+0x2b, 0x6f, 0x08, 0x33, 0x2b, 0x67, 0x3c, 0x6a, 0xa3, 0x42, 0x02, 0xd3, 
+0x12, 0x4b, 0xc0, 0x46, 0x2b, 0x67, 0x03, 0x1c, 0xdb, 0x00, 0x6b, 0x44, 
+0x5c, 0x68, 0x01, 0x30, 0x23, 0x0d, 0x04, 0xd3, 0x51, 0x24, 0xa4, 0x03, 
+0x2b, 0x6f, 0xc0, 0x46, 0xa3, 0x61, 0x88, 0x42, 0xde, 0xd1, 0x10, 0x0b, 
+0x03, 0xd3, 0x0e, 0x49, 0x01, 0x20, 0xfc, 0xf7, 0xc2, 0xfb, 0x41, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x00, 0x01, 0x14, 0x40, 0x00, 0x40, 0x14, 0x40, 0x00, 0x00, 0x20, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00, 
+0xb5, 0x4f, 0xff, 0xff, 0xf0, 0xb4, 0x00, 0x21, 0x00, 0x23, 0x07, 0x22, 
+0x06, 0x24, 0x47, 0x4f, 0xc0, 0x46, 0x3c, 0x61, 0x3a, 0x61, 0x01, 0x33, 
+0x20, 0x2b, 0xf9, 0xd3, 0x04, 0x25, 0x3d, 0x61, 0x05, 0x23, 0x3b, 0x61, 
+0x3c, 0x61, 0x3a, 0x61, 0x3c, 0x61, 0x3a, 0x61, 0x3d, 0x61, 0x3b, 0x61, 
+0x3f, 0x4d, 0xab, 0x6f, 0xde, 0x08, 0x02, 0x23, 0x1e, 0x40, 0x04, 0x23, 
+0x33, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x33, 0x43, 0x3b, 0x61, 0xab, 0x6f, 
+0x9e, 0x08, 0x02, 0x23, 0x1e, 0x40, 0x04, 0x23, 0x33, 0x43, 0x3b, 0x61, 
+0x05, 0x23, 0x33, 0x43, 0x3b, 0x61, 0xab, 0x6f, 0x5e, 0x08, 0x02, 0x23, 
 0x1e, 0x40, 0x04, 0x23, 0x33, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x33, 0x43, 
-0x3b, 0x61, 0xab, 0x6f, 0x5e, 0x08, 0x02, 0x23, 0x1e, 0x40, 0x04, 0x23, 
-0x33, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x33, 0x43, 0x3b, 0x61, 0x02, 0x23, 
-0xae, 0x6f, 0x1e, 0x40, 0x04, 0x23, 0x33, 0x43, 0x3b, 0x61, 0x05, 0x23, 
-0x33, 0x43, 0x3b, 0x61, 0xab, 0x6f, 0x5d, 0x00, 0x02, 0x23, 0x1d, 0x40, 
-0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 
-0xc5, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 
-0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x85, 0x08, 0x02, 0x23, 0x1d, 0x40, 
-0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 
+0x3b, 0x61, 0x02, 0x23, 0xae, 0x6f, 0x1e, 0x40, 0x04, 0x23, 0x33, 0x43, 
+0x3b, 0x61, 0x05, 0x23, 0x33, 0x43, 0x3b, 0x61, 0xab, 0x6f, 0x5d, 0x00, 
+0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 
+0x2b, 0x43, 0x3b, 0x61, 0xc5, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 
+0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x85, 0x08, 
+0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 
 0x2b, 0x43, 0x3b, 0x61, 0x45, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 
 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x02, 0x25, 
-0x05, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 
-0x3b, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 0x04, 0x23, 0x03, 0x43, 
-0x3b, 0x61, 0x05, 0x23, 0x18, 0x43, 0x38, 0x61, 0x00, 0x25, 0x3d, 0x61, 
-0x01, 0x23, 0x3b, 0x61, 0x3d, 0x61, 0x3b, 0x61, 0x00, 0x20, 0x3d, 0x61, 
-0x0d, 0x4b, 0x1b, 0x69, 0x49, 0x00, 0x1e, 0x1c, 0x02, 0x23, 0x33, 0x40, 
-0x19, 0x43, 0x01, 0x23, 0x3b, 0x61, 0x01, 0x30, 0x10, 0x28, 0xf2, 0xd3, 
-0x02, 0x20, 0x38, 0x61, 0x03, 0x20, 0x38, 0x61, 0x3c, 0x61, 0x3a, 0x61, 
-0x3c, 0x61, 0x3a, 0x61, 0x38, 0x61, 0x48, 0x08, 0xf0, 0xbc, 0x70, 0x47, 
-0x80, 0x00, 0x14, 0x00, 0xe8, 0x0d, 0x00, 0x80, 0x80, 0x00, 0x14, 0x40, 
-0xf0, 0xb4, 0x00, 0x24, 0x07, 0x23, 0x06, 0x27, 0x44, 0x4a, 0xc0, 0x46, 
-0x17, 0x61, 0x13, 0x61, 0x01, 0x34, 0x20, 0x2c, 0xf9, 0xd3, 0x04, 0x26, 
-0x16, 0x61, 0x05, 0x24, 0x14, 0x61, 0x17, 0x61, 0x07, 0x23, 0x13, 0x61, 
-0x16, 0x61, 0x14, 0x61, 0x17, 0x61, 0x13, 0x61, 0x3c, 0x4b, 0x9b, 0x6f, 
-0xdd, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 
-0x25, 0x43, 0x15, 0x61, 0x37, 0x4b, 0x9b, 0x6f, 0x9d, 0x08, 0x02, 0x23, 
+0x05, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 
+0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 
+0x04, 0x23, 0x03, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x18, 0x43, 0x38, 0x61, 
+0x00, 0x25, 0x3d, 0x61, 0x01, 0x23, 0x3b, 0x61, 0x3d, 0x61, 0x3b, 0x61, 
+0x00, 0x20, 0x3d, 0x61, 0x0d, 0x4b, 0x1b, 0x69, 0x49, 0x00, 0x1e, 0x1c, 
+0x02, 0x23, 0x33, 0x40, 0x19, 0x43, 0x01, 0x23, 0x3b, 0x61, 0x01, 0x30, 
+0x10, 0x28, 0xf2, 0xd3, 0x02, 0x20, 0x38, 0x61, 0x03, 0x20, 0x38, 0x61, 
+0x3c, 0x61, 0x3a, 0x61, 0x3c, 0x61, 0x3a, 0x61, 0x38, 0x61, 0x48, 0x08, 
+0xf0, 0xbc, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x80, 0x00, 0x14, 0x40, 0xf0, 0xb4, 0x00, 0x24, 0x07, 0x23, 0x06, 0x27, 
+0x44, 0x4a, 0xc0, 0x46, 0x17, 0x61, 0x13, 0x61, 0x01, 0x34, 0x20, 0x2c, 
+0xf9, 0xd3, 0x04, 0x26, 0x16, 0x61, 0x05, 0x24, 0x14, 0x61, 0x17, 0x61, 
+0x07, 0x23, 0x13, 0x61, 0x16, 0x61, 0x14, 0x61, 0x17, 0x61, 0x13, 0x61, 
+0x3c, 0x4b, 0x9b, 0x6f, 0xdd, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 
+0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x37, 0x4b, 0x9b, 0x6f, 
+0x9d, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 
+0x25, 0x43, 0x15, 0x61, 0x32, 0x4b, 0x9b, 0x6f, 0x5d, 0x08, 0x02, 0x23, 
 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 
-0x32, 0x4b, 0x9b, 0x6f, 0x5d, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 
-0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x2d, 0x4b, 0x9d, 0x6f, 
+0x2d, 0x4b, 0x9d, 0x6f, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 
+0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x29, 0x4b, 0x9b, 0x6f, 0x5d, 0x00, 
 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 
-0x15, 0x61, 0x29, 0x4b, 0x9b, 0x6f, 0x5d, 0x00, 0x02, 0x23, 0x1d, 0x40, 
-0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0xc5, 0x08, 
+0x15, 0x61, 0xc5, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 
+0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x85, 0x08, 0x02, 0x23, 0x1d, 0x40, 
+0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x45, 0x08, 
 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 
-0x15, 0x61, 0x85, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x2b, 0x1c, 0x33, 0x43, 
-0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x45, 0x08, 0x02, 0x23, 0x1d, 0x40, 
-0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 0x02, 0x25, 
-0x05, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 0x25, 0x43, 0x15, 0x61, 
-0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 0x03, 0x1c, 0x33, 0x43, 0x13, 0x61, 
-0x20, 0x43, 0x10, 0x61, 0x17, 0x61, 0x07, 0x23, 0x13, 0x61, 0x16, 0x61, 
-0x14, 0x61, 0x4c, 0x00, 0x00, 0x20, 0x0f, 0x21, 0x25, 0x1c, 0xcd, 0x40, 
-0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x13, 0x61, 0x05, 0x23, 
-0x2b, 0x43, 0x13, 0x61, 0x01, 0x30, 0x01, 0x39, 0x10, 0x28, 0xf1, 0xd3, 
-0x17, 0x61, 0x07, 0x23, 0x13, 0x61, 0x17, 0x61, 0x13, 0x61, 0x03, 0x20, 
-0x10, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x00, 
-0xe8, 0x0d, 0x00, 0x80, 0xf0, 0xb5, 0x47, 0x48, 0x01, 0x89, 0x47, 0x4d, 
-0x07, 0x23, 0x5b, 0x02, 0xef, 0x18, 0xb9, 0x83, 0x40, 0x8b, 0xc0, 0x46, 
-0xf8, 0x83, 0x28, 0x79, 0x00, 0x28, 0x01, 0xd0, 0x00, 0x20, 0xb8, 0x83, 
-0xe8, 0x68, 0x01, 0x28, 0x06, 0xd1, 0x68, 0x88, 0x00, 0x28, 0x03, 0xd1, 
-0xf9, 0x21, 0x12, 0x20, 0xff, 0xf7, 0x54, 0xff, 0x01, 0x21, 0xc9, 0x03, 
-0x00, 0x20, 0xff, 0xf7, 0x4f, 0xff, 0x00, 0x24, 0x7d, 0x26, 0xf6, 0x00, 
-0x00, 0xe0, 0x01, 0x34, 0x00, 0x20, 0xff, 0xf7, 0xad, 0xfe, 0x00, 0x0c, 
-0x01, 0xd3, 0xb4, 0x42, 0xf7, 0xd3, 0x00, 0x24, 
-0x05, 0xe0, 0x03, 0x21, 0x09, 0x03, 0x00, 0x20, 0xff, 0xf7, 0x3c, 0xff, 
-0x01, 0x34, 0x00, 0x20, 0xff, 0xf7, 0x9e, 0xfe, 0x40, 0x0b, 0x01, 0xd2, 
-0xb4, 0x42, 0xf2, 0xd3, 0x04, 0x20, 0xff, 0xf7, 0x97, 0xfe, 0xff, 0x23, 
-0xe1, 0x33, 0x98, 0x43, 0x01, 0x21, 0x01, 0x43, 0xb8, 0x8b, 0xff, 0x23, 
-0x01, 0x33, 0x98, 0x42, 0x03, 0xd1, 0x2f, 0x23, 0x5b, 0x01, 0x19, 0x43, 
-0x16, 0xe0, 0x01, 0x28, 0x09, 0xd1, 0xf8, 0x8b, 0x01, 0x28, 0x03, 0xd1, 
-0x23, 0x23, 0x5b, 0x01, 0x19, 0x43, 0x0d, 0xe0, 0x20, 0x23, 0x19, 0x43, 
-0x0a, 0xe0, 0x00, 0x28, 0x08, 0xd1, 0xf8, 0x8b, 0x01, 0x28, 0x03, 0xd1, 
-0x0b, 0x23, 0xdb, 0x01, 0x19, 0x43, 0x01, 0xe0, 0x80, 0x23, 0x19, 0x43, 
-0x04, 0x20, 0xff, 0xf7, 0x09, 0xff, 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 
-0xff, 0xf7, 0x04, 0xff, 0xe8, 0x68, 0x00, 0x28, 0x0c, 0xd1, 0x00, 0x21, 
-0x1b, 0x20, 0xff, 0xf7, 0xfd, 0xfe, 0x1a, 0x20, 0xff, 0xf7, 0x60, 0xfe, 
-0x01, 0x21, 0xc9, 0x03, 0x01, 0x43, 0x1a, 0x20, 0xff, 0xf7, 0xf4, 0xfe, 
-0x00, 0x27, 0x03, 0xe0, 0x08, 0x2f, 0x01, 0xd3, 0x0f, 0x2f, 0x08, 0xd9, 
-0x38, 0x1c, 0xff, 0xf7, 0x51, 0xfe, 0x79, 0x00, 0x49, 0x19, 0x1b, 0x23, 
-0xdb, 0x01, 0xc9, 0x18, 0x08, 0x83, 0x01, 0x37, 0x20, 0x2f, 0xef, 0xd3, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x70, 0x67, 0x21, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0x81, 0xb0, 0x13, 0x48, 0x01, 0x68, 0xc0, 0x46, 
-0x00, 0x91, 0x41, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x81, 0x68, 0xc0, 0x46, 
-0x00, 0x91, 0xc1, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x01, 0x69, 0xc0, 0x46, 
-0x00, 0x91, 0x41, 0x69, 0xc0, 0x46, 0x00, 0x91, 0x81, 0x69, 0xc0, 0x46, 
-0x00, 0x91, 0xc1, 0x69, 0xc0, 0x46, 0x00, 0x91, 0x01, 0x6a, 0xc0, 0x46, 
-0x00, 0x91, 0x41, 0x6a, 0xc0, 0x46, 0x00, 0x91, 0x81, 0x6a, 0xc0, 0x46, 
-0x00, 0x91, 0xc0, 0x6a, 0xc0, 0x46, 0x00, 0x90, 0x01, 0xb0, 0x70, 0x47, 
-0x00, 0x08, 0x14, 0x40, 0xf0, 0xb5, 0x83, 0xb0, 0x66, 0x4e, 0x1b, 0x23, 
-0xdb, 0x01, 0xf7, 0x18, 0x78, 0x8b, 0x04, 0x22, 0x02, 0x40, 0x02, 0x92, 
-0x07, 0x23, 0x5b, 0x02, 0xf4, 0x18, 0xa0, 0x8b, 0xc0, 0x46, 0x01, 0x90, 
-0xe0, 0x8b, 0xc0, 0x46, 0x00, 0x90, 0x00, 0x25, 0x03, 0xe0, 0x08, 0x2d, 
-0x01, 0xd3, 0x0f, 0x2d, 0x08, 0xd9, 0x28, 0x1c, 0xff, 0xf7, 0xfa, 0xfd, 
-0x69, 0x00, 0x89, 0x19, 0x1b, 0x23, 0xdb, 0x01, 0xc9, 0x18, 0x08, 0x83, 
-0x01, 0x35, 0x20, 0x2d, 0xef, 0xd3, 0xa0, 0x69, 0x00, 0x28, 0x15, 0xd0, 
-0x54, 0x4e, 0x20, 0x25, 0x01, 0x3d, 0x52, 0x49, 0xa0, 0x69, 0x30, 0x40, 
-0x0b, 0xd0, 0x68, 0x00, 0x40, 0x18, 0x37, 0x23, 0x9b, 0x01, 0xc0, 0x18, 
-0x01, 0x8b, 0x28, 0x1c, 0xff, 0xf7, 0x78, 0xfe, 0xa0, 0x69, 0xb0, 0x43, 
-0xa0, 0x61, 0x76, 0x08, 0x00, 0x2d, 0xeb, 0xd1, 0x01, 0x20, 0xff, 0xf7, 
-0xd5, 0xfd, 0x01, 0x1c, 0x46, 0x48, 0xc0, 0x46, 0x79, 0x83, 0x79, 0x8b, 
-0xca, 0x08, 0x22, 0xd3, 0xc2, 0x68, 0x01, 0x2a, 0x10, 0xd1, 0x40, 0x88, 
-0x00, 0x28, 0x1c, 0xd1, 0x01, 0x98, 0x42, 0x4a, 0x00, 0x28, 0x05, 0xd0, 
-0x01, 0x28, 0x16, 0xd1, 0xd0, 0x8a, 0xc0, 0x08, 0x13, 0xd2, 0x0f, 0xe0, 
-0xd0, 0x8a, 0x00, 0x09, 0x0f, 0xd2, 0x0b, 0xe0, 0x02, 0x79, 0x00, 0x2a, 
-0x0b, 0xd1, 0x6d, 0x23, 0x5b, 0x01, 0xc0, 0x18, 0x02, 0x88, 0x40, 0x88, 
-0x10, 0x40, 0x40, 0x09, 0x00, 0x07, 0x02, 0xd1, 0x04, 0x23, 0x99, 0x43, 
-0x79, 0x83, 0x78, 0x8b, 0x04, 0x21, 0x01, 0x40, 
-0x02, 0x9a, 0x1f, 0xd0, 0x39, 0x8b, 0x4a, 0x0b, 0x27, 0xd3, 0x80, 0x09, 
-0x25, 0xd3, 0xff, 0x23, 0x01, 0x98, 0x01, 0x33, 0x98, 0x42, 0x20, 0xd0, 
-0x00, 0x25, 0x00, 0x98, 0x01, 0x28, 0x00, 0xd1, 0x05, 0x02, 0x01, 0x98, 
-0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0x5b, 0x03, 0x1d, 0x43, 0xa9, 0x42, 
-0x13, 0xd0, 0x00, 0x20, 0x29, 0x1c, 0xff, 0xf7, 0x25, 0xfe, 0x3d, 0x83, 
-0x00, 0x20, 0xc0, 0x43, 0x20, 0x62, 0x0a, 0xe0, 0x38, 0x8b, 0x40, 0x0b, 
-0x07, 0xd2, 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0xff, 0xf7, 0x18, 0xfe, 
-0x09, 0x20, 0x40, 0x02, 0x38, 0x83, 0x78, 0x8b, 0xc0, 0x08, 0x2d, 0xd3, 
-0x1b, 0x48, 0xc7, 0x6a, 0x01, 0x98, 0x00, 0x99, 0xff, 0xf7, 0x6a, 0xfc, 
-0xc2, 0x07, 0xd2, 0x0f, 0x18, 0x49, 0x03, 0xd0, 0x04, 0x23, 0xcd, 0x6d, 
-0x2b, 0x43, 0x03, 0xe0, 0x04, 0x23, 0xcd, 0x6d, 0x9d, 0x43, 0x2b, 0x1c, 
-0xcb, 0x65, 0x83, 0x08, 0x03, 0xd3, 0x02, 0x23, 0xcd, 0x6d, 0x2b, 0x43, 
-0x03, 0xe0, 0x02, 0x23, 0xcd, 0x6d, 0x9d, 0x43, 0x2b, 0x1c, 0xcb, 0x65, 
-0x21, 0x6a, 0x81, 0x42, 0x0c, 0xd0, 0x20, 0x62, 0x0c, 0x48, 0x00, 0x2a, 
-0x03, 0xd0, 0xff, 0x21, 0x21, 0x31, 0x39, 0x43, 0x03, 0xe0, 0xff, 0x23, 
-0x21, 0x33, 0x9f, 0x43, 0x39, 0x1c, 0xc1, 0x62, 0x03, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
-0xa8, 0x1b, 0x00, 0x80, 0x40, 0x00, 0x14, 0x40, 0x10, 0x2a, 0x00, 0x80, 
-0x40, 0x00, 0x14, 0x00, 0x90, 0xb4, 0x01, 0x22, 0x20, 0x28, 0x0f, 0xd2, 
-0x43, 0x00, 0x0f, 0x1c, 0x07, 0x49, 0x5c, 0x18, 0x37, 0x23, 0x9b, 0x01, 
-0xe3, 0x18, 0x1f, 0x83, 0x82, 0x40, 0x07, 0x23, 0x5b, 0x02, 0xc9, 0x18, 
-0x10, 0x1c, 0x8a, 0x69, 0x10, 0x43, 0x88, 0x61, 0x90, 0xbc, 0x70, 0x47, 
-0xe8, 0x0d, 0x00, 0x80, 0x0b, 0x48, 0x40, 0x69, 0x0b, 0x49, 0x49, 0x8b, 
-0x04, 0x22, 0x0a, 0x40, 0x0a, 0x49, 0x06, 0xd0, 0x01, 0x23, 0xdb, 0x02, 
-0x98, 0x43, 0x01, 0x23, 0xca, 0x6d, 0x1a, 0x43, 0x05, 0xe0, 0x01, 0x23, 
-0xdb, 0x02, 0x18, 0x43, 0xca, 0x6d, 0x52, 0x08, 0x52, 0x00, 0xca, 0x65, 
-0x70, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x40, 0x68, 0x1b, 0x00, 0x80, 
-0x10, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x84, 0xb0, 0xff, 0xf7, 0xde, 0xff, 
-0x01, 0x1c, 0x05, 0x20, 0x00, 0x90, 0x00, 0x20, 0x01, 0xab, 0x18, 0x80, 
-0x04, 0x3b, 0x58, 0x70, 0x1b, 0x22, 0x00, 0xab, 0x5a, 0x80, 0xd9, 0x80, 
-0x05, 0x49, 0xc9, 0x6d, 0xc0, 0x46, 0x02, 0x91, 0x03, 0x90, 0x68, 0x46, 
-0x00, 0x21, 0xfc, 0xf7, 0x9d, 0xfd, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 
-0x10, 0x2a, 0x00, 0x80, 0x0d, 0x48, 0x01, 0x68, 0x49, 0x0c, 0x05, 0xd2, 
-0x01, 0x68, 0x09, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x03, 0xd3, 
-0x09, 0x48, 0x00, 0x68, 0x00, 0x0c, 0x01, 0xe0, 0x08, 0x48, 0x80, 0x6c, 
-0x00, 0x04, 0x00, 0x0c, 0x07, 0x4b, 0x98, 0x42, 0x02, 0xd0, 0x02, 0x33, 
-0x98, 0x42, 0x01, 0xd1, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7, 
+0x15, 0x61, 0x02, 0x25, 0x05, 0x40, 0x2b, 0x1c, 0x33, 0x43, 0x13, 0x61, 
+0x25, 0x43, 0x15, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 0x03, 0x1c, 
+0x33, 0x43, 0x13, 0x61, 0x20, 0x43, 0x10, 0x61, 0x17, 0x61, 0x07, 0x23, 
+0x13, 0x61, 0x16, 0x61, 0x14, 0x61, 0x4c, 0x00, 0x00, 0x20, 0x0f, 0x21, 
+0x25, 0x1c, 0xcd, 0x40, 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 
+0x13, 0x61, 0x05, 0x23, 0x2b, 0x43, 0x13, 0x61, 0x01, 0x30, 0x01, 0x39, 
+0x10, 0x28, 0xf1, 0xd3, 0x17, 0x61, 0x07, 0x23, 0x13, 0x61, 0x17, 0x61, 
+0x13, 0x61, 0x03, 0x20, 0x10, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0x80, 0x00, 0x14, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x4f, 0x4d, 
+0x08, 0x21, 0x02, 0x20, 0x2a, 0x1c, 0xfc, 0xf7, 0x75, 0xfa, 0x4d, 0x4c, 
+0x71, 0x23, 0x5b, 0x01, 0xe7, 0x18, 0x38, 0x80, 0x1a, 0x21, 0x02, 0x20, 
+0x2a, 0x1c, 0xfc, 0xf7, 0x6b, 0xfa, 0x78, 0x80, 0x20, 0x79, 0x00, 0x28, 
+0x0b, 0xd0, 0x00, 0x20, 0x38, 0x80, 0xe0, 0x68, 0x01, 0x28, 0x10, 0xd1, 
+0x44, 0x48, 0x00, 0x68, 0x01, 0x23, 0x9b, 0x02, 0x18, 0x43, 0x99, 0x02, 
+0x08, 0x60, 0xe0, 0x68, 0x01, 0x28, 0x06, 0xd1, 0x60, 0x88, 0x00, 0x28, 
+0x03, 0xd1, 0xf9, 0x21, 0x12, 0x20, 0xff, 0xf7, 0x43, 0xff, 0x01, 0x21, 
+0xc9, 0x03, 0x00, 0x20, 0xff, 0xf7, 0x3e, 0xff, 0x00, 0x25, 0x7d, 0x26, 
+0xf6, 0x00, 0x00, 0xe0, 0x01, 0x35, 0x00, 0x20, 0xff, 0xf7, 0x9c, 0xfe, 
+0x00, 0x0c, 0x01, 0xd3, 0xb5, 0x42, 0xf7, 0xd3, 
+0x00, 0x25, 0x05, 0xe0, 0x03, 0x21, 0x09, 0x03, 0x00, 0x20, 0xff, 0xf7, 
+0x2b, 0xff, 0x01, 0x35, 0x00, 0x20, 0xff, 0xf7, 0x8d, 0xfe, 0x40, 0x0b, 
+0x01, 0xd2, 0xb5, 0x42, 0xf2, 0xd3, 0x04, 0x20, 0xff, 0xf7, 0x86, 0xfe, 
+0xff, 0x23, 0xe1, 0x33, 0x98, 0x43, 0x01, 0x21, 0x01, 0x43, 0x38, 0x88, 
+0xff, 0x23, 0x01, 0x33, 0x98, 0x42, 0x03, 0xd1, 0x2f, 0x23, 0x5b, 0x01, 
+0x19, 0x43, 0x16, 0xe0, 0x01, 0x28, 0x09, 0xd1, 0x78, 0x88, 0x01, 0x28, 
+0x03, 0xd1, 0x23, 0x23, 0x5b, 0x01, 0x19, 0x43, 0x0d, 0xe0, 0x20, 0x23, 
+0x19, 0x43, 0x0a, 0xe0, 0x00, 0x28, 0x08, 0xd1, 0x78, 0x88, 0x01, 0x28, 
+0x03, 0xd1, 0x0b, 0x23, 0xdb, 0x01, 0x19, 0x43, 0x01, 0xe0, 0x80, 0x23, 
+0x19, 0x43, 0x04, 0x20, 0xff, 0xf7, 0xf8, 0xfe, 0x09, 0x21, 0x49, 0x02, 
+0x00, 0x20, 0xff, 0xf7, 0xf3, 0xfe, 0xe0, 0x68, 0x00, 0x28, 0x0c, 0xd1, 
+0x00, 0x21, 0x1b, 0x20, 0xff, 0xf7, 0xec, 0xfe, 0x1a, 0x20, 0xff, 0xf7, 
+0x4f, 0xfe, 0x01, 0x21, 0xc9, 0x03, 0x01, 0x43, 0x1a, 0x20, 0xff, 0xf7, 
+0xe3, 0xfe, 0x00, 0x27, 0x03, 0xe0, 0x08, 0x2f, 0x01, 0xd3, 0x0f, 0x2f, 
+0x08, 0xd9, 0x38, 0x1c, 0xff, 0xf7, 0x40, 0xfe, 0x79, 0x00, 0x09, 0x19, 
+0x1b, 0x23, 0xdb, 0x01, 0xc9, 0x18, 0x88, 0x83, 0x01, 0x37, 0x20, 0x2f, 
+0xef, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x79, 0xbf, 0x21, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb0, 0x13, 0x48, 
+0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 0xc0, 0x46, 0x00, 0x91, 
+0x81, 0x68, 0xc0, 0x46, 0x00, 0x91, 0xc1, 0x68, 0xc0, 0x46, 0x00, 0x91, 
+0x01, 0x69, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x69, 0xc0, 0x46, 0x00, 0x91, 
+0x81, 0x69, 0xc0, 0x46, 0x00, 0x91, 0xc1, 0x69, 0xc0, 0x46, 0x00, 0x91, 
+0x01, 0x6a, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x6a, 0xc0, 0x46, 0x00, 0x91, 
+0x81, 0x6a, 0xc0, 0x46, 0x00, 0x91, 0xc0, 0x6a, 0xc0, 0x46, 0x00, 0x90, 
+0x01, 0xb0, 0x70, 0x47, 0x00, 0x08, 0x14, 0x40, 0xf0, 0xb5, 0x83, 0xb0, 
+0x68, 0x4d, 0x1b, 0x23, 0xdb, 0x01, 0xef, 0x18, 0xf8, 0x8b, 0x04, 0x22, 
+0x02, 0x40, 0x02, 0x92, 0x71, 0x23, 0x5b, 0x01, 0xe8, 0x18, 0x01, 0x88, 
+0xc0, 0x46, 0x01, 0x91, 0x40, 0x88, 0xc0, 0x46, 0x00, 0x90, 0x00, 0x24, 
+0x03, 0xe0, 0x08, 0x2c, 0x01, 0xd3, 0x0f, 0x2c, 0x08, 0xd9, 0x20, 0x1c, 
+0xff, 0xf7, 0xe8, 0xfd, 0x61, 0x00, 0x49, 0x19, 0x1b, 0x23, 0xdb, 0x01, 
+0xc9, 0x18, 0x88, 0x83, 0x01, 0x34, 0x20, 0x2c, 0xef, 0xd3, 0x58, 0x4c, 
+0xe0, 0x69, 0x00, 0x28, 0x15, 0xd0, 0x57, 0x4e, 0x20, 0x25, 0x01, 0x3d, 
+0x53, 0x49, 0xe0, 0x69, 0x30, 0x40, 0x0b, 0xd0, 0x68, 0x00, 0x40, 0x18, 
+0x37, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x8b, 0x28, 0x1c, 0xff, 0xf7, 
+0x65, 0xfe, 0xe0, 0x69, 0xb0, 0x43, 0xe0, 0x61, 0x76, 0x08, 0x00, 0x2d, 
+0xeb, 0xd1, 0x01, 0x20, 0xff, 0xf7, 0xc2, 0xfd, 0x48, 0x49, 0xc0, 0x46, 
+0xf8, 0x83, 0xf8, 0x8b, 0xc2, 0x08, 0x25, 0xd3, 0xca, 0x68, 0x01, 0x2a, 
+0x13, 0xd1, 0x0a, 0x79, 0x00, 0x2a, 0x1f, 0xd1, 0x49, 0x88, 0x00, 0x29, 
+0x1c, 0xd1, 0x01, 0x99, 0x43, 0x4a, 0x00, 0x29, 0x05, 0xd0, 0x01, 0x29, 
+0x16, 0xd1, 0x51, 0x8b, 0xc9, 0x08, 0x13, 0xd2, 0x0f, 0xe0, 0x51, 0x8b, 
+0x09, 0x09, 0x0f, 0xd2, 0x0b, 0xe0, 0x0a, 0x79, 0x00, 0x2a, 0x0b, 0xd1, 
+0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x8a, 0x88, 0xc9, 0x88, 0x11, 0x40, 
+0x49, 0x09, 0x09, 0x07, 0x02, 0xd1, 0x04, 0x23, 
+0x98, 0x43, 0xf8, 0x83, 0xf8, 0x8b, 0x04, 0x21, 0x01, 0x40, 0x02, 0x9a, 
+0x1f, 0xd0, 0xb9, 0x8b, 0x4a, 0x0b, 0x27, 0xd3, 0x80, 0x09, 0x25, 0xd3, 
+0xff, 0x23, 0x01, 0x98, 0x01, 0x33, 0x98, 0x42, 0x20, 0xd0, 0x00, 0x25, 
+0x00, 0x98, 0x01, 0x28, 0x00, 0xd1, 0x05, 0x02, 0x01, 0x98, 0x00, 0x28, 
+0x02, 0xd1, 0x01, 0x23, 0x5b, 0x03, 0x1d, 0x43, 0xa9, 0x42, 0x13, 0xd0, 
+0x00, 0x20, 0x29, 0x1c, 0xff, 0xf7, 0x10, 0xfe, 0xbd, 0x83, 0x00, 0x20, 
+0xc0, 0x43, 0x60, 0x62, 0x0a, 0xe0, 0xb8, 0x8b, 0x40, 0x0b, 0x07, 0xd2, 
+0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0xff, 0xf7, 0x03, 0xfe, 0x09, 0x20, 
+0x40, 0x02, 0xb8, 0x83, 0xf8, 0x8b, 0xc0, 0x08, 0x2d, 0xd3, 0x1d, 0x48, 
+0xc7, 0x6a, 0x01, 0x98, 0x00, 0x99, 0xff, 0xf7, 0x51, 0xfc, 0xc2, 0x07, 
+0xd2, 0x0f, 0x1a, 0x49, 0x03, 0xd0, 0x04, 0x23, 0xcd, 0x6d, 0x2b, 0x43, 
+0x03, 0xe0, 0x04, 0x23, 0xcd, 0x6d, 0x9d, 0x43, 0x2b, 0x1c, 0xcb, 0x65, 
+0x83, 0x08, 0x03, 0xd3, 0x02, 0x23, 0xcd, 0x6d, 0x2b, 0x43, 0x03, 0xe0, 
+0x02, 0x23, 0xcd, 0x6d, 0x9d, 0x43, 0x2b, 0x1c, 0xcb, 0x65, 0x61, 0x6a, 
+0x81, 0x42, 0x0c, 0xd0, 0x60, 0x62, 0x0e, 0x48, 0x00, 0x2a, 0x03, 0xd0, 
+0xff, 0x21, 0x21, 0x31, 0x39, 0x43, 0x03, 0xe0, 0xff, 0x23, 0x21, 0x33, 
+0x9f, 0x43, 0x39, 0x1c, 0xc1, 0x62, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x68, 0x1c, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0x80, 0x28, 0x1c, 0x00, 0x80, 0x40, 0x00, 0x14, 0x40, 
+0xa4, 0x2a, 0x00, 0x80, 0x40, 0x00, 0x14, 0x00, 0x90, 0xb4, 0x01, 0x22, 
+0x20, 0x28, 0x0f, 0xd2, 0x43, 0x00, 0x0f, 0x1c, 0x07, 0x49, 0x5c, 0x18, 
+0x37, 0x23, 0x9b, 0x01, 0xe3, 0x18, 0x9f, 0x83, 0x82, 0x40, 0x07, 0x23, 
+0x5b, 0x02, 0xc9, 0x18, 0x10, 0x1c, 0xca, 0x69, 0x10, 0x43, 0xc8, 0x61, 
+0x90, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x0b, 0x48, 0x40, 0x69, 
+0x0b, 0x49, 0xc9, 0x8b, 0x04, 0x22, 0x0a, 0x40, 0x0a, 0x49, 0x06, 0xd0, 
+0x01, 0x23, 0xdb, 0x02, 0x98, 0x43, 0x01, 0x23, 0xca, 0x6d, 0x1a, 0x43, 
+0x05, 0xe0, 0x01, 0x23, 0xdb, 0x02, 0x18, 0x43, 0xca, 0x6d, 0x52, 0x08, 
+0x52, 0x00, 0xca, 0x65, 0x70, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x40, 
+0xe8, 0x1b, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x84, 0xb0, 
+0xff, 0xf7, 0xde, 0xff, 0x01, 0x1c, 0x05, 0x20, 0x00, 0x90, 0x00, 0x20, 
+0x01, 0xab, 0x18, 0x80, 0x04, 0x3b, 0x58, 0x70, 0x1b, 0x22, 0x00, 0xab, 
+0x5a, 0x80, 0xd9, 0x80, 0x05, 0x49, 0xc9, 0x6d, 0xc0, 0x46, 0x02, 0x91, 
+0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfc, 0xf7, 0xd5, 0xf9, 0x04, 0xb0, 
+0x08, 0xbc, 0x18, 0x47, 0xa4, 0x2a, 0x00, 0x80, 0x0f, 0x48, 0x01, 0x68, 
+0x49, 0x0c, 0x05, 0xd2, 0x01, 0x68, 0x09, 0x0c, 0x06, 0xd1, 0x00, 0x68, 
+0x80, 0x0a, 0x03, 0xd3, 0x0b, 0x48, 0x00, 0x68, 0x00, 0x0c, 0x01, 0xe0, 
+0x0a, 0x48, 0x80, 0x6c, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x4b, 0x98, 0x42, 
+0x05, 0xd0, 0x02, 0x33, 0x98, 0x42, 0x02, 0xd0, 0x07, 0x4b, 0x98, 0x42, 
+0x01, 0xd1, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7, 0x00, 0x00, 
 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 
-0x04, 0x99, 0x00, 0x00, 0x90, 0xb4, 0x01, 0x24, 0x21, 0x1c, 0x17, 0x48, 
-0x02, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x02, 0x68, 0x12, 0x0c, 0x02, 0xd1, 
-0x00, 0x68, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x21, 0x09, 0x06, 0x09, 0x0e, 
-0x11, 0x4f, 0x12, 0x4a, 0x02, 0xd0, 0x38, 0x68, 0x00, 0x0c, 0x00, 0xe0, 
-0x90, 0x6c, 0x00, 0x04, 0x00, 0x0c, 0x0f, 0x4b, 
-0x98, 0x42, 0x05, 0xd0, 0x02, 0x33, 0x98, 0x42, 0x02, 0xd0, 0x0d, 0x4b, 
-0x98, 0x42, 0x0c, 0xd1, 0x00, 0x29, 0x02, 0xd0, 0xf8, 0x6a, 0x00, 0x0c, 
-0x00, 0xe0, 0xd0, 0x6c, 0x40, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x20, 0x06, 
-0x00, 0x0e, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 0xfb, 0xe7, 0x00, 0x00, 
-0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 
-0x04, 0x99, 0x00, 0x00, 0x05, 0x99, 0x00, 0x00, 0x0c, 0x48, 0x01, 0x68, 
-0x49, 0x0c, 0x05, 0xd2, 0x01, 0x68, 0x09, 0x0c, 0x05, 0xd1, 0x00, 0x68, 
-0x80, 0x0a, 0x02, 0xd3, 0x08, 0x48, 0x80, 0x68, 0x01, 0xe0, 0x08, 0x48, 
-0x40, 0x6c, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x21, 0x03, 0x28, 0x03, 0xd0, 
-0x40, 0x08, 0x01, 0xd3, 0x01, 0x20, 0x70, 0x47, 0x08, 0x1c, 0xfc, 0xe7, 
-0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 
-0xf0, 0xb5, 0x01, 0x27, 0x1a, 0x4c, 0x25, 0x68, 0xff, 0xf7, 0x7a, 0xff, 
-0x03, 0x1c, 0x19, 0x4a, 0x02, 0x21, 0x01, 0x26, 0x18, 0x48, 0x01, 0x2b, 
-0x1b, 0xd1, 0xcb, 0x04, 0x1e, 0x60, 0x55, 0x23, 0x03, 0x60, 0x00, 0x23, 
-0x43, 0x60, 0x06, 0x68, 0x55, 0x2e, 0x1b, 0xd1, 0xaa, 0x26, 0x06, 0x60, 
-0x43, 0x60, 0x03, 0x68, 0xaa, 0x2b, 0x15, 0xd1, 0x09, 0x23, 0x03, 0x60, 
-0x05, 0x23, 0x0f, 0x4f, 0xc0, 0x46, 0x3b, 0x60, 0x03, 0x23, 0x0e, 0x4f, 
-0xc0, 0x46, 0x3b, 0x60, 0x11, 0x60, 0x07, 0x68, 0x08, 0xe0, 0x08, 0x23, 
-0x23, 0x60, 0x04, 0x23, 0x0a, 0x4f, 0xc0, 0x46, 0x3b, 0x60, 0x11, 0x60, 
-0x06, 0x60, 0x27, 0x68, 0xc0, 0x46, 0x25, 0x60, 0x38, 0x1c, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x24, 0x40, 
-0x00, 0x00, 0x22, 0x40, 0x00, 0x00, 0x2a, 0x40, 0x00, 0x00, 0x26, 0x40, 
-0x00, 0x00, 0x28, 0x40, 0x80, 0xb5, 0x07, 0x1c, 0xff, 0xf7, 0x38, 0xff, 
-0x01, 0x28, 0x05, 0xd1, 0x19, 0x48, 0x00, 0x68, 0x19, 0x49, 0x49, 0x6b, 
-0x08, 0x40, 0x22, 0xe0, 0x18, 0x48, 0x01, 0x68, 0x49, 0x0c, 0x05, 0xd2, 
-0x01, 0x68, 0x09, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x03, 0xd3, 
-0x14, 0x48, 0x00, 0x68, 0x00, 0x0c, 0x01, 0xe0, 0x13, 0x48, 0x80, 0x6c, 
-0x00, 0x04, 0x00, 0x0c, 0x12, 0x4b, 0xc0, 0x18, 0x08, 0x28, 0x0b, 0xd2, 
-0x01, 0xa3, 0x1b, 0x5c, 0x5b, 0x00, 0x9f, 0x44, 0x05, 0x03, 0x07, 0x03, 
-0x07, 0x07, 0x05, 0x03, 0x03, 0x20, 0x02, 0xe0, 0x01, 0x20, 0x00, 0xe0, 
-0x00, 0x20, 0x01, 0x21, 0x38, 0x60, 0x80, 0x07, 0x00, 0xd1, 0x00, 0x21, 
-0x08, 0x06, 0x00, 0x0e, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x98, 0x6e, 0x21, 0x40, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x10, 0x40, 
-0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x66, 0xff, 0xff, 
-0xf0, 0xb5, 0x83, 0xb0, 0x07, 0x1c, 0x01, 0x20, 0x02, 0x90, 0x01, 0x25, 
-0x02, 0x24, 0x10, 0x26, 0x20, 0x21, 0x00, 0x91, 0xff, 0xf7, 0xea, 0xfe, 
-0x01, 0x28, 0x4d, 0xd1, 0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x3a, 0xd1, 
-0x2e, 0x4e, 0x3c, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfc, 0xf7, 0x1c, 0xfb, 
-0x3e, 0x21, 0x05, 0x1c, 0x02, 0x20, 0x32, 0x1c, 0xfc, 0xf7, 0x16, 0xfb, 
-0x00, 0x04, 0x05, 0x43, 0x40, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfc, 0xf7, 
-0x0f, 0xfb, 0x01, 0x90, 0x42, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfc, 0xf7, 
-0x09, 0xfb, 0x00, 0x04, 0x01, 0x99, 0x08, 0x43, 0x06, 0x1c, 0xa8, 0x2f, 
-0x1b, 0xd1, 0x1f, 0x4a, 0x44, 0x21, 0x02, 0x20, 
-0xfc, 0xf7, 0xfe, 0xfa, 0x04, 0x1c, 0x1c, 0x4a, 0x46, 0x21, 0x02, 0x20, 
-0xfc, 0xf7, 0xf8, 0xfa, 0x00, 0x04, 0x04, 0x43, 0x18, 0x4a, 0x48, 0x21, 
-0x02, 0x20, 0xfc, 0xf7, 0xf1, 0xfa, 0x00, 0x90, 0x15, 0x4a, 0x4a, 0x21, 
-0x02, 0x20, 0xfc, 0xf7, 0xeb, 0xfa, 0x00, 0x04, 0x00, 0x99, 0x01, 0x43, 
-0x00, 0x91, 0x28, 0x1c, 0x30, 0x43, 0x20, 0x43, 0x00, 0x99, 0x08, 0x43, 
-0x00, 0xd1, 0x16, 0xe0, 0x11, 0x20, 0x00, 0x04, 0x05, 0x62, 0x46, 0x62, 
-0x84, 0x62, 0x00, 0x99, 0xc0, 0x46, 0xc1, 0x62, 0x00, 0x21, 0x0a, 0x48, 
-0xc0, 0x46, 0x01, 0x60, 0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x05, 0xd1, 
-0x01, 0x21, 0x01, 0x60, 0xa8, 0x2f, 0x01, 0xd1, 0x03, 0x21, 0x01, 0x60, 
-0x02, 0x98, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x39, 0xb7, 0x21, 0x40, 0x98, 0x6e, 0x21, 0x40, 0x80, 0xb5, 0x07, 0x1c, 
-0xff, 0xf7, 0x7e, 0xfe, 0x01, 0x28, 0x19, 0xd1, 0x01, 0x05, 0x11, 0x48, 
-0x00, 0x2f, 0x18, 0xd0, 0x0b, 0x0a, 0x02, 0x68, 0x9a, 0x43, 0x0a, 0x60, 
-0x01, 0x68, 0x49, 0x0c, 0x05, 0xd2, 0x01, 0x68, 0x09, 0x0c, 0x0b, 0xd1, 
-0x00, 0x68, 0x80, 0x0a, 0x08, 0xd3, 0x0a, 0x48, 0x40, 0x6a, 0xff, 0x22, 
-0x01, 0x32, 0x02, 0x43, 0x08, 0x49, 0xc0, 0x46, 0x4a, 0x62, 0x48, 0x62, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x68, 0x01, 0x23, 0x1b, 0x03, 
-0x18, 0x43, 0x08, 0x60, 0xf6, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
-0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x70, 0x47, 0x00, 0x00, 
+0x04, 0x99, 0x00, 0x00, 0x07, 0x99, 0x00, 0x00, 0x90, 0xb4, 0x01, 0x24, 
+0x21, 0x1c, 0x18, 0x48, 0x02, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x02, 0x68, 
+0x12, 0x0c, 0x02, 0xd1, 0x00, 0x68, 0x80, 0x0a, 
+0x00, 0xd2, 0x00, 0x21, 0x09, 0x06, 0x09, 0x0e, 0x12, 0x4f, 0x13, 0x4a, 
+0x02, 0xd0, 0x38, 0x68, 0x00, 0x0c, 0x00, 0xe0, 0x90, 0x6c, 0x00, 0x04, 
+0x00, 0x0c, 0x10, 0x4b, 0x98, 0x42, 0x08, 0xd0, 0x02, 0x33, 0x98, 0x42, 
+0x05, 0xd0, 0x0e, 0x4b, 0x98, 0x42, 0x02, 0xd0, 0x02, 0x3b, 0x98, 0x42, 
+0x0c, 0xd1, 0x00, 0x29, 0x02, 0xd0, 0xf8, 0x6a, 0x00, 0x0c, 0x00, 0xe0, 
+0xd0, 0x6c, 0x40, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x20, 0x06, 0x00, 0x0e, 
+0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 0xfb, 0xe7, 0x00, 0x00, 0x10, 0x40, 
+0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 0x04, 0x99, 0x00, 0x00, 
+0x07, 0x99, 0x00, 0x00, 0x0c, 0x48, 0x01, 0x68, 0x49, 0x0c, 0x05, 0xd2, 
+0x01, 0x68, 0x09, 0x0c, 0x05, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x02, 0xd3, 
+0x08, 0x48, 0x80, 0x68, 0x01, 0xe0, 0x08, 0x48, 0x40, 0x6c, 0x00, 0x04, 
+0x00, 0x0c, 0x00, 0x21, 0x03, 0x28, 0x03, 0xd0, 0x40, 0x08, 0x01, 0xd3, 
+0x01, 0x20, 0x70, 0x47, 0x08, 0x1c, 0xfc, 0xe7, 0x00, 0x00, 0x10, 0x40, 
+0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x01, 0x27, 
+0x1a, 0x4c, 0x25, 0x68, 0xff, 0xf7, 0x72, 0xff, 0x03, 0x1c, 0x19, 0x4a, 
+0x02, 0x21, 0x01, 0x26, 0x18, 0x48, 0x01, 0x2b, 0x1b, 0xd1, 0xcb, 0x04, 
+0x1e, 0x60, 0x55, 0x23, 0x03, 0x60, 0x00, 0x23, 0x43, 0x60, 0x06, 0x68, 
+0x55, 0x2e, 0x1b, 0xd1, 0xaa, 0x26, 0x06, 0x60, 0x43, 0x60, 0x03, 0x68, 
+0xaa, 0x2b, 0x15, 0xd1, 0x09, 0x23, 0x03, 0x60, 0x05, 0x23, 0x0f, 0x4f, 
+0xc0, 0x46, 0x3b, 0x60, 0x03, 0x23, 0x0e, 0x4f, 0xc0, 0x46, 0x3b, 0x60, 
+0x11, 0x60, 0x07, 0x68, 0x08, 0xe0, 0x08, 0x23, 0x23, 0x60, 0x04, 0x23, 
+0x0a, 0x4f, 0xc0, 0x46, 0x3b, 0x60, 0x11, 0x60, 0x06, 0x60, 0x27, 0x68, 
+0xc0, 0x46, 0x25, 0x60, 0x38, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x22, 0x40, 
+0x00, 0x00, 0x2a, 0x40, 0x00, 0x00, 0x26, 0x40, 0x00, 0x00, 0x28, 0x40, 
+0x80, 0xb5, 0x07, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x01, 0x28, 0x05, 0xd1, 
+0x19, 0x48, 0x00, 0x68, 0x19, 0x49, 0x49, 0x6b, 0x08, 0x40, 0x22, 0xe0, 
+0x18, 0x48, 0x01, 0x68, 0x49, 0x0c, 0x05, 0xd2, 0x01, 0x68, 0x09, 0x0c, 
+0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x03, 0xd3, 0x14, 0x48, 0x00, 0x68, 
+0x00, 0x0c, 0x01, 0xe0, 0x13, 0x48, 0x80, 0x6c, 0x00, 0x04, 0x00, 0x0c, 
+0x12, 0x4b, 0xc0, 0x18, 0x08, 0x28, 0x0b, 0xd2, 0x01, 0xa3, 0x1b, 0x5c, 
+0x5b, 0x00, 0x9f, 0x44, 0x05, 0x03, 0x07, 0x03, 0x07, 0x07, 0x05, 0x03, 
+0x03, 0x20, 0x02, 0xe0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x01, 0x21, 
+0x38, 0x60, 0x80, 0x07, 0x00, 0xd1, 0x00, 0x21, 0x08, 0x06, 0x00, 0x0e, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x98, 0x6e, 0x21, 0x40, 
+0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 
+0x00, 0x00, 0x00, 0x80, 0xfe, 0x66, 0xff, 0xff, 0xf0, 0xb5, 0x83, 0xb0, 
+0x07, 0x1c, 0x01, 0x20, 0x02, 0x90, 0x01, 0x25, 0x02, 0x24, 0x10, 0x26, 
+0x20, 0x21, 0x00, 0x91, 0xff, 0xf7, 0xe2, 0xfe, 0x01, 0x28, 0x4d, 0xd1, 
+0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x3a, 0xd1, 0x2e, 0x4e, 0x3c, 0x21, 
+0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 0x4c, 0xff, 0x3e, 0x21, 0x05, 0x1c, 
+0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 0x46, 0xff, 0x00, 0x04, 0x05, 0x43, 
+0x40, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 
+0x3f, 0xff, 0x01, 0x90, 0x42, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 
+0x39, 0xff, 0x00, 0x04, 0x01, 0x99, 0x08, 0x43, 0x06, 0x1c, 0xa8, 0x2f, 
+0x1b, 0xd1, 0x1f, 0x4a, 0x44, 0x21, 0x02, 0x20, 0xfb, 0xf7, 0x2e, 0xff, 
+0x04, 0x1c, 0x1c, 0x4a, 0x46, 0x21, 0x02, 0x20, 0xfb, 0xf7, 0x28, 0xff, 
+0x00, 0x04, 0x04, 0x43, 0x18, 0x4a, 0x48, 0x21, 0x02, 0x20, 0xfb, 0xf7, 
+0x21, 0xff, 0x00, 0x90, 0x15, 0x4a, 0x4a, 0x21, 0x02, 0x20, 0xfb, 0xf7, 
+0x1b, 0xff, 0x00, 0x04, 0x00, 0x99, 0x01, 0x43, 0x00, 0x91, 0x28, 0x1c, 
+0x30, 0x43, 0x20, 0x43, 0x00, 0x99, 0x08, 0x43, 0x00, 0xd1, 0x16, 0xe0, 
+0x11, 0x20, 0x00, 0x04, 0x05, 0x62, 0x46, 0x62, 0x84, 0x62, 0x00, 0x99, 
+0xc0, 0x46, 0xc1, 0x62, 0x00, 0x21, 0x0a, 0x48, 0xc0, 0x46, 0x01, 0x60, 
+0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x05, 0xd1, 0x01, 0x21, 0x01, 0x60, 
+0xa8, 0x2f, 0x01, 0xd1, 0x03, 0x21, 0x01, 0x60, 0x02, 0x98, 0x03, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x79, 0xbf, 0x21, 0x40, 
+0x98, 0x6e, 0x21, 0x40, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
 0x90, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x21, 0x68, 0x12, 0x48, 0x81, 0x42, 
-0x0b, 0xd0, 0x00, 0x23, 0x21, 0x1c, 0xe2, 0x1d, 0x6d, 0x32, 0x00, 0xe0, 
-0x08, 0xc1, 0x91, 0x42, 0xfc, 0xd3, 0x20, 0x60, 0x74, 0x20, 0xa0, 0x80, 
+0x0b, 0xd0, 0x00, 0x23, 0x21, 0x1c, 0xe2, 0x1d, 0xc5, 0x32, 0x00, 0xe0, 
+0x08, 0xc1, 0x91, 0x42, 0xfc, 0xd3, 0x20, 0x60, 0xcc, 0x20, 0xa0, 0x80, 
 0x67, 0x72, 0x38, 0x01, 0x00, 0xf0, 0x18, 0xf8, 0x27, 0x72, 0x0a, 0x48, 
-0xc0, 0x46, 0xe0, 0x60, 0x08, 0x2f, 0x00, 0xdb, 0x00, 0x27, 0xe0, 0x19, 
+0xc0, 0x46, 0xe0, 0x60, 0x09, 0x2f, 0x00, 0xdb, 0x00, 0x27, 0xe0, 0x19, 
 0x01, 0x7d, 0x01, 0x31, 0x01, 0x75, 0xe0, 0x88, 0x01, 0x30, 0xe0, 0x80, 
 0x01, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x80, 
-0xfe, 0xca, 0x01, 0x20, 0x17, 0x40, 0x00, 0x02, 0x80, 0xb4, 0x08, 0x4a, 
-0xd1, 0x1d, 0x49, 0x31, 0x0b, 0x78, 0x20, 0x2b, 0x01, 0xd3, 0x00, 0x23, 
-0x0b, 0x70, 0x07, 0x1c, 0x08, 0x78, 0x43, 0x1c, 0x0b, 0x70, 0x80, 0x18, 
-0x50, 0x30, 0x47, 0x70, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x80, 
+0xee, 0xff, 0xc0, 0xd0, 0x02, 0x10, 0x00, 0x03, 0x80, 0xb4, 0x08, 0x4a, 
+0xd1, 0x1d, 0x89, 0x31, 0x0b, 0x7b, 0x20, 0x2b, 0x01, 0xd3, 0x00, 0x23, 
+0x0b, 0x73, 0x07, 0x1c, 0x08, 0x7b, 0x43, 0x1c, 0x0b, 0x73, 0x80, 0x18, 
+0x90, 0x30, 0x47, 0x73, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x80, 
 0x07, 0x49, 0x01, 0x22, 0x12, 0x04, 0x08, 0x68, 0x02, 0x40, 0x01, 0x20, 
 0x00, 0x2a, 0x06, 0xd1, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1, 0x09, 0x68, 
 0x89, 0x0a, 0x00, 0xd2, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x10, 0x40, 
 0x90, 0xb5, 0x07, 0x1c, 0x09, 0x4c, 0x38, 0x1c, 0x21, 0x1c, 0xfc, 0xf7, 
-0x4d, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 0x01, 0x23, 0xd8, 0x42, 
-0x01, 0xd1, 0x00, 0x0c, 0xe0, 0x80, 0x00, 0x21, 0x20, 0x1c, 0xfc, 0xf7, 
-0x81, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xbc, 0x67, 0x21, 0x40, 
+0xab, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 0x01, 0x23, 0xd8, 0x42, 
+0x01, 0xd1, 0x00, 0x0c, 0xe0, 0x80, 0x00, 0x21, 0x20, 0x1c, 0xfb, 0xf7, 
+0xdf, 0xff, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x67, 0x21, 0x40, 
 0xf8, 0xb5, 0x07, 0x1c, 0x79, 0x7a, 0x76, 0x48, 0x00, 0x23, 0x76, 0x4c, 
 0x01, 0x29, 0x5d, 0xd1, 0xa2, 0x88, 0xc0, 0x46, 0x00, 0x92, 0xa1, 0x89, 
 0x8a, 0x42, 0x74, 0xda, 0xfa, 0x7a, 0x00, 0x2a, 0x15, 0xd0, 0x7a, 0x6c, 
 0x00, 0x2a, 0x12, 0xd0, 0x8a, 0x42, 0x10, 0xd8, 0x00, 0x9a, 0x51, 0x1c, 
 0xa1, 0x80, 0xa1, 0x88, 0xc0, 0x46, 0x41, 0x81, 0x78, 0x6c, 0x6b, 0x4e, 
-0xc0, 0x46, 0xf0, 0x80, 0xa0, 0x6a, 0x58, 0x23, 
-0x79, 0x6c, 0x59, 0x43, 0x40, 0x18, 0xc1, 0x1a, 0x28, 0xe0, 0x22, 0x88, 
-0x01, 0x32, 0x12, 0x04, 0x12, 0x0c, 0x22, 0x80, 0x8a, 0x42, 0x00, 0xdb, 
-0x23, 0x80, 0x00, 0x22, 0x00, 0x29, 0x69, 0xdd, 0x5f, 0x4c, 0xa4, 0x6a, 
-0x5e, 0x4b, 0x1d, 0x88, 0x58, 0x23, 0x6b, 0x43, 0xe3, 0x18, 0xde, 0x1d, 
-0x01, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 
+0xc0, 0x46, 0xf0, 0x80, 0xa0, 0x6a, 0x58, 0x23, 0x79, 0x6c, 0x59, 0x43, 
+0x40, 0x18, 0xc1, 0x1a, 0x28, 0xe0, 0x22, 0x88, 0x01, 0x32, 0x12, 0x04, 
+0x12, 0x0c, 0x22, 0x80, 0x8a, 0x42, 0x00, 0xdb, 0x23, 0x80, 0x00, 0x22, 
+0x00, 0x29, 0x69, 0xdd, 0x5f, 0x4c, 0xa4, 0x6a, 0x5e, 0x4b, 0x1d, 0x88, 
+0x58, 0x23, 0x6b, 0x43, 0xe3, 0x18, 0xde, 0x1d, 0x01, 0x36, 0x01, 0x23, 
+0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 
 0x15, 0xd1, 0x58, 0x49, 0x00, 0x9a, 0x01, 0x32, 0x8a, 0x80, 0x8a, 0x88, 
 0xc0, 0x46, 0x42, 0x81, 0x08, 0x88, 0x01, 0x30, 0x54, 0x4e, 0xc0, 0x46, 
 0xf0, 0x80, 0x58, 0x20, 0x68, 0x43, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 
-0x65, 0xfa, 0xf0, 0x88, 0x00, 0x04, 0x00, 0x14, 0x95, 0xe0, 0x4d, 0x4b, 
+0x8d, 0xfa, 0xf0, 0x88, 0x00, 0x04, 0x00, 0x14, 0x95, 0xe0, 0x4d, 0x4b, 
 0x01, 0x35, 0x2d, 0x04, 0x2d, 0x0c, 0x1d, 0x80, 0x8d, 0x42, 0x01, 0xdb, 
 0x00, 0x25, 0x1d, 0x80, 0x01, 0x32, 0x12, 0x04, 0x12, 0x14, 0x91, 0x42, 
 0xce, 0xdc, 0x81, 0xe0, 0xe1, 0x88, 0xe2, 0x89, 0x91, 0x42, 0x18, 0xda, 
@@ -3446,9 +3614,9 @@ const u8 typhoon_firmware_image[] = {
 0xdb, 0x03, 0x78, 0x6c, 0x18, 0x43, 0x3a, 0x4e, 0xc0, 0x46, 0xf0, 0x80, 
 0x00, 0xe0, 0x63, 0xe0, 0xe0, 0x6a, 0x79, 0x6c, 0x4b, 0x00, 0x59, 0x18, 
 0x49, 0x01, 0x40, 0x18, 0xc1, 0x1f, 0x59, 0x39, 0x38, 0x1c, 0x00, 0xf0, 
-0x4b, 0xfa, 0xe0, 0x6a, 0x79, 0x6c, 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 
+0x79, 0xfa, 0xe0, 0x6a, 0x79, 0x6c, 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 
 0x80, 0x18, 0x01, 0x39, 0x09, 0x04, 0x09, 0x0c, 0x60, 0x38, 0x00, 0xf0, 
-0xc5, 0xfa, 0xb6, 0xe7, 0x4a, 0xe0, 0x61, 0x88, 0x01, 0x31, 0x09, 0x04, 
+0xf3, 0xfa, 0xb6, 0xe7, 0x4a, 0xe0, 0x61, 0x88, 0x01, 0x31, 0x09, 0x04, 
 0x09, 0x0c, 0x61, 0x80, 0xe2, 0x89, 0x91, 0x42, 0x00, 0xdb, 0x63, 0x80, 
 0x00, 0x21, 0x00, 0x2a, 0x3e, 0xdd, 0x24, 0x4c, 0xe4, 0x6a, 0x23, 0x4b, 
 0x5d, 0x88, 0x6b, 0x00, 0x5b, 0x19, 0x5b, 0x01, 0xe3, 0x18, 0xde, 0x1d, 
@@ -3456,193 +3624,208 @@ const u8 typhoon_firmware_image[] = {
 0x20, 0xd1, 0x1c, 0x4e, 0xf1, 0x88, 0x01, 0x31, 0xf1, 0x80, 0xf1, 0x88, 
 0xc0, 0x46, 0x81, 0x81, 0x70, 0x88, 0x01, 0x23, 0xdb, 0x03, 0x01, 0x30, 
 0x18, 0x43, 0x17, 0x49, 0xc0, 0x46, 0xc8, 0x80, 0x68, 0x00, 0x40, 0x19, 
-0x40, 0x01, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x0b, 0xfa, 0x71, 0x88, 
+0x40, 0x01, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x39, 0xfa, 0x71, 0x88, 
 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 0xf0, 0x6a, 0x80, 0x18, 0x00, 0xf0, 
-0x89, 0xfa, 0x0e, 0x49, 0xc8, 0x88, 0x79, 0xe7, 0x0b, 0x4b, 0x01, 0x35, 
+0xb7, 0xfa, 0x0e, 0x49, 0xc8, 0x88, 0x79, 0xe7, 0x0b, 0x4b, 0x01, 0x35, 
 0x2d, 0x04, 0x2d, 0x0c, 0x5d, 0x80, 0x95, 0x42, 0x01, 0xdb, 0x00, 0x25, 
 0x5d, 0x80, 0x01, 0x31, 0x09, 0x04, 0x09, 0x14, 0x8a, 0x42, 0xc2, 0xdc, 
 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x00, 0x20, 0xc0, 0x43, 0xf8, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xb8, 0x2a, 0x00, 0x80, 0xc8, 0x29, 0x00, 0x80, 
-0xbc, 0x67, 0x21, 0x40, 0xf0, 0xb4, 0x06, 0x1c, 0x01, 0x23, 0xdb, 0x03, 
-0x33, 0x40, 0x01, 0x24, 0x30, 0x4f, 0x00, 0x20, 0x30, 0x4a, 0x31, 0x4d, 
-0xd1, 0x1d, 0x39, 0x31, 0x00, 0x2b, 0x2f, 0xd0, 0xe3, 0x03, 0xf3, 0x1a, 
-0x51, 0xd0, 0xee, 0x89, 0x9e, 0x42, 0x4e, 0xd3, 0xee, 0x88, 0x00, 0x2e, 
-0x4b, 0xd0, 0xee, 0x6a, 0x5d, 0x1e, 0x6b, 0x00, 0x5d, 0x19, 0x6d, 0x01, 
-0x73, 0x19, 0x9e, 0x68, 0x36, 0x06, 0x36, 0x0e, 0x03, 0x2e, 0x02, 0xd0, 
-0xce, 0x89, 0x01, 0x36, 0xce, 0x81, 0x40, 0x33, 0x9b, 0x8b, 0x9b, 0x00, 
-0x21, 0x4e, 0x76, 0x6a, 0xc0, 0x46, 0xf0, 0x50, 
-0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x1e, 0x4e, 0xf2, 0x6a, 0x52, 0x19, 
-0x90, 0x60, 0xf0, 0x88, 0x01, 0x38, 0xf0, 0x80, 0xf0, 0x88, 0xc0, 0x46, 
-0x88, 0x81, 0x19, 0x49, 0x00, 0x28, 0x23, 0xd1, 0x4f, 0x80, 0x21, 0xe0, 
-0x00, 0x2e, 0x22, 0xd9, 0xab, 0x89, 0xb3, 0x42, 0x1f, 0xd3, 0xab, 0x88, 
-0x00, 0x2b, 0x1c, 0xd0, 0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x58, 0x23, 
-0x01, 0x3e, 0x73, 0x43, 0xaa, 0x6a, 0xd2, 0x18, 0x93, 0x68, 0x1b, 0x06, 
-0x1b, 0x0e, 0x03, 0x2b, 0x02, 0xd0, 0xcb, 0x89, 0x01, 0x33, 0xcb, 0x81, 
-0x90, 0x60, 0xa8, 0x88, 0x01, 0x38, 0xa8, 0x80, 0xa8, 0x88, 0xc0, 0x46, 
-0x48, 0x81, 0x00, 0x28, 0x00, 0xd1, 0x2f, 0x80, 0x20, 0x1c, 0xf0, 0xbc, 
-0x70, 0x47, 0xca, 0x89, 0x01, 0x32, 0xca, 0x81, 0xf9, 0xe7, 0x00, 0x00, 
-0xff, 0xff, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x80, 0xc8, 0x29, 0x00, 0x80, 
-0x00, 0xb5, 0x00, 0x21, 0x41, 0x60, 0x10, 0x49, 0x4a, 0x68, 0x00, 0x2a, 
-0x10, 0xd1, 0xca, 0x68, 0x00, 0x2a, 0x04, 0xd0, 0xca, 0x1d, 0x19, 0x32, 
-0x12, 0x79, 0x00, 0x2a, 0x08, 0xd0, 0x4a, 0x69, 0x00, 0x2a, 0x0b, 0xd1, 
-0x88, 0x61, 0x48, 0x61, 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
-0x4a, 0x69, 0x00, 0x2a, 0x02, 0xd1, 0x88, 0x61, 0x48, 0x61, 0xf7, 0xe7, 
-0x8a, 0x69, 0xc0, 0x46, 0x50, 0x60, 0x88, 0x61, 0xf2, 0xe7, 0x00, 0x00, 
-0xec, 0x05, 0x00, 0x80, 0xb0, 0xb5, 0x2a, 0x48, 0x40, 0x69, 0x00, 0x28, 
-0x4c, 0xd0, 0x08, 0x22, 0xc1, 0x68, 0x0a, 0x40, 0x00, 0x27, 0x27, 0x4b, 
-0xd9, 0x1d, 0xb9, 0x31, 0x00, 0x2a, 0x11, 0xd0, 0x04, 0x22, 0x25, 0x4c, 
-0xc0, 0x46, 0x0c, 0x61, 0x24, 0x4c, 0xc0, 0x46, 0x4c, 0x62, 0x24, 0x4c, 
-0xc0, 0x46, 0x8c, 0x62, 0x23, 0x4c, 0xc0, 0x46, 0xcc, 0x62, 0x23, 0x4c, 
-0xc0, 0x46, 0x0c, 0x63, 0x4f, 0x63, 0x12, 0xe0, 0x05, 0x22, 0x21, 0x4c, 
-0xc0, 0x46, 0x0c, 0x61, 0x20, 0x4c, 0xc0, 0x46, 0x4c, 0x62, 0x20, 0x4c, 
-0xc0, 0x46, 0x8c, 0x62, 0x1f, 0x4c, 0xc0, 0x46, 0xcc, 0x62, 0x1f, 0x4c, 
-0xc0, 0x46, 0x0c, 0x63, 0x1e, 0x4c, 0xc0, 0x46, 0x4c, 0x63, 0x40, 0x24, 
-0xcc, 0x82, 0x4f, 0x83, 0x1c, 0x4f, 0x00, 0x21, 0x00, 0x2a, 0x0c, 0xd9, 
-0x8c, 0x00, 0x05, 0x19, 0x6d, 0x6a, 0x7d, 0x40, 0xe4, 0x18, 0xff, 0x34, 
-0x01, 0x34, 0x65, 0x62, 0x01, 0x31, 0x91, 0x42, 0xf4, 0xd3, 0x10, 0x29, 
-0x07, 0xd2, 0x8a, 0x00, 0xd2, 0x18, 0xff, 0x32, 0x01, 0x32, 0x57, 0x62, 
-0x01, 0x31, 0x10, 0x29, 0xf7, 0xd3, 0x11, 0x49, 0x00, 0xf0, 0x22, 0xf8, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xec, 0x05, 0x00, 0x80, 
-0x1c, 0xad, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 0x01, 0x23, 0x45, 0x67, 
-0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 
-0x20, 0x01, 0x40, 0x00, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 
-0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0, 
-0x36, 0x36, 0x36, 0x36, 0x30, 0x80, 0x20, 0x40, 0xb0, 0xb5, 0x0f, 0x1c, 
-0x15, 0x4d, 0xe9, 0x1d, 0xc9, 0x31, 0x15, 0x4c, 0x23, 0x1c, 0x15, 0x4a, 
-0x00, 0x20, 0xfc, 0xf7, 0x1a, 0xf8, 0xe9, 0x1d, 0xff, 0x31, 0x1e, 0x31, 
-0x23, 0x1c, 0x0d, 0x1c, 0x11, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x11, 0xf8, 
-0x29, 0x1c, 0x23, 0x1c, 0x0e, 0x4a, 0x00, 0x20, 0xfc, 0xf7, 0x0b, 0xf8, 
-0x39, 0x1c, 0x23, 0x1c, 0x0c, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x05, 0xf8, 
-0x00, 0x21, 0x0b, 0x48, 0xc2, 0x1d, 0x19, 0x32, 
-0x51, 0x71, 0x01, 0x21, 0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 0x08, 0x1c, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x1c, 0xad, 0x20, 0x40, 
-0x75, 0x08, 0xff, 0xff, 0x28, 0x00, 0x03, 0x00, 0x40, 0x00, 0x02, 0x00, 
-0x14, 0x00, 0x07, 0x00, 0xec, 0x05, 0x00, 0x80, 0xf0, 0xb5, 0x37, 0x4a, 
-0x50, 0x69, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x30, 0x18, 0x43, 0x00, 0x68, 
-0x01, 0x06, 0x09, 0x0e, 0x33, 0x4b, 0x01, 0x29, 0x49, 0xd1, 0x1f, 0x68, 
-0x19, 0x1c, 0x32, 0x4b, 0x9f, 0x42, 0x04, 0xd1, 0xff, 0xf7, 0x3e, 0xff, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x23, 0x9f, 0x00, 0xcc, 0x59, 
-0x55, 0x69, 0xef, 0x19, 0x3c, 0x61, 0x01, 0x33, 0x05, 0x2b, 0xf7, 0xd3, 
-0x00, 0x0a, 0x00, 0x02, 0x02, 0x23, 0x18, 0x43, 0x53, 0x69, 0xc0, 0x46, 
-0x98, 0x60, 0x50, 0x69, 0x08, 0x23, 0xc2, 0x68, 0x13, 0x40, 0x25, 0x4f, 
-0xfa, 0x1d, 0xb9, 0x32, 0x00, 0x2b, 0x02, 0xd0, 0x04, 0x23, 0x23, 0x4c, 
-0x01, 0xe0, 0x05, 0x23, 0x22, 0x4c, 0xc0, 0x46, 0x14, 0x61, 0x40, 0x24, 
-0xd4, 0x82, 0x00, 0x24, 0x54, 0x83, 0x20, 0x4c, 0x00, 0x22, 0x00, 0x2b, 
-0x0c, 0xd9, 0x95, 0x00, 0x46, 0x19, 0x76, 0x6a, 0x66, 0x40, 0xed, 0x19, 
-0xff, 0x35, 0x01, 0x35, 0x6e, 0x62, 0x01, 0x32, 0x9a, 0x42, 0xf4, 0xd3, 
-0x10, 0x2a, 0x07, 0xd2, 0x93, 0x00, 0xdb, 0x19, 0xff, 0x33, 0x01, 0x33, 
-0x5c, 0x62, 0x01, 0x32, 0x10, 0x2a, 0xf7, 0xd3, 0xff, 0xf7, 0x70, 0xff, 
-0xbc, 0xe7, 0x00, 0x21, 0x8f, 0x00, 0xdc, 0x59, 0x55, 0x69, 0xef, 0x19, 
-0x7c, 0x62, 0x01, 0x31, 0x05, 0x29, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 
-0x03, 0x23, 0x18, 0x43, 0x51, 0x69, 0xc0, 0x46, 0x88, 0x60, 0x50, 0x69, 
-0x40, 0x68, 0xc0, 0x46, 0x50, 0x61, 0x09, 0x48, 0xfb, 0xf7, 0x7a, 0xff, 
-0xa4, 0xe7, 0x00, 0x00, 0xec, 0x05, 0x00, 0x80, 0x30, 0x80, 0x20, 0x40, 
-0x67, 0x45, 0x23, 0x01, 0x1c, 0xad, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 
-0x20, 0x01, 0x40, 0x00, 0x5c, 0x5c, 0x5c, 0x5c, 0x85, 0x30, 0xff, 0xff, 
-0x80, 0xb5, 0x0f, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0xb9, 0x6b, 
-0x0b, 0x48, 0xc2, 0x68, 0x12, 0x04, 0x51, 0x40, 0x82, 0x69, 0x51, 0x40, 
-0x39, 0x65, 0xf9, 0x6b, 0x82, 0x69, 0x12, 0x04, 0xd2, 0x43, 0x51, 0x40, 
-0xc0, 0x68, 0xc0, 0x43, 0x48, 0x40, 0x78, 0x65, 0x04, 0x48, 0x01, 0x89, 
-0x01, 0x31, 0x01, 0x81, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x08, 0x83, 0x20, 0x40, 0x78, 0x2a, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 
-0x0f, 0x1c, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0xe0, 0x68, 
-0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 
-0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 
-0x08, 0x43, 0x38, 0x65, 0x20, 0x69, 0xc0, 0x46, 0x78, 0x65, 0x60, 0x69, 
-0xc0, 0x46, 0xb8, 0x65, 0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x80, 
-0x90, 0xb5, 0x00, 0x22, 0x93, 0x00, 0x1f, 0x18, 0xbf, 0x69, 0x5b, 0x18, 
-0x5f, 0x62, 0x01, 0x32, 0x05, 0x2a, 0xf7, 0xd3, 0x07, 0x7a, 0xfb, 0x08, 
-0x03, 0xd3, 0x00, 0x23, 0x92, 0x00, 0x52, 0x18, 0x13, 0x62, 0x07, 0x6b, 
+0x08, 0xbc, 0x18, 0x47, 0x4c, 0x2b, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 
+0x70, 0x67, 0x21, 0x40, 0xf0, 0xb4, 0x06, 0x1c, 0x01, 0x23, 0xdb, 0x03, 
+0x33, 0x40, 0x01, 0x24, 0x44, 0x4f, 0x00, 0x20, 0x44, 0x4a, 0x45, 0x4d, 
+0xd1, 0x1d, 0x39, 0x31, 0x00, 0x2b, 0x41, 0xd0, 0xe3, 0x03, 0xf3, 0x1a, 
+0x73, 0xd0, 0xee, 0x89, 0x9e, 0x42, 0x71, 0xd3, 0xee, 0x88, 0x00, 0x2e, 
+0x6d, 0xd0, 0xed, 0x6a, 0x5e, 0x1e, 0x73, 0x00, 0x9b, 0x19, 0x5b, 0x01, 
+0xed, 0x18, 0xae, 0x68, 0x36, 0x06, 0x36, 0x0e, 0x03, 0x2e, 0x02, 0xd0, 
+0xce, 0x89, 0x01, 0x36, 0xce, 0x81, 0x40, 0x35, 0xad, 0x8b, 0xad, 0x00, 
+0x35, 0x4e, 0x76, 0x6a, 0xc0, 0x46, 0x70, 0x51, 0x55, 0x89, 0x01, 0x35, 
+0x55, 0x81, 0x32, 0x4e, 0xf2, 0x6a, 0xd2, 0x18, 0x90, 0x60, 0xf2, 0x6a, 
+0xd2, 0x18, 0x90, 0x63, 0xf2, 0x6a, 0xd2, 0x18, 0xd0, 0x63, 0xf2, 0x6a, 
+0xd2, 0x18, 0x10, 0x64, 0xf2, 0x6a, 0xd2, 0x18, 0x50, 0x64, 0xf2, 0x6a, 
+0xd2, 0x18, 0x90, 0x64, 0xf2, 0x6a, 0xd2, 0x18, 0xd0, 0x64, 0xf0, 0x88, 
+0x01, 0x38, 0xf0, 0x80, 0xf0, 0x88, 0xc0, 0x46, 
+0x88, 0x81, 0x24, 0x49, 0x00, 0x28, 0x39, 0xd1, 0x4f, 0x80, 0x37, 0xe0, 
+0x00, 0x2e, 0x38, 0xd9, 0xab, 0x89, 0xb3, 0x42, 0x30, 0xd3, 0xab, 0x88, 
+0x00, 0x2b, 0x2c, 0xd0, 0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x2a, 0x1c, 
+0xad, 0x6a, 0x58, 0x23, 0x01, 0x3e, 0x73, 0x43, 0xed, 0x18, 0xae, 0x68, 
+0x36, 0x06, 0x36, 0x0e, 0x03, 0x2e, 0x02, 0xd0, 0xce, 0x89, 0x01, 0x36, 
+0xce, 0x81, 0xa8, 0x60, 0x95, 0x6a, 0xed, 0x18, 0xa8, 0x63, 0x95, 0x6a, 
+0xed, 0x18, 0xe8, 0x63, 0x95, 0x6a, 0xed, 0x18, 0x28, 0x64, 0x95, 0x6a, 
+0xed, 0x18, 0x68, 0x64, 0x95, 0x6a, 0xed, 0x18, 0xa8, 0x64, 0x95, 0x6a, 
+0xeb, 0x18, 0xd8, 0x64, 0x90, 0x88, 0x01, 0x38, 0x90, 0x80, 0x90, 0x88, 
+0xc0, 0x46, 0x48, 0x81, 0x00, 0x28, 0x03, 0xd1, 0x01, 0xe0, 0x04, 0xe0, 
+0x03, 0xe0, 0x17, 0x80, 0x20, 0x1c, 0xf0, 0xbc, 0x70, 0x47, 0xca, 0x89, 
+0x01, 0x32, 0xca, 0x81, 0xf9, 0xe7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
+0x0c, 0x2b, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x00, 0x21, 
+0x41, 0x60, 0x10, 0x49, 0x4a, 0x68, 0x00, 0x2a, 0x10, 0xd1, 0xca, 0x68, 
+0x00, 0x2a, 0x04, 0xd0, 0xca, 0x1d, 0x19, 0x32, 0x12, 0x79, 0x00, 0x2a, 
+0x08, 0xd0, 0x4a, 0x69, 0x00, 0x2a, 0x0b, 0xd1, 0x88, 0x61, 0x48, 0x61, 
+0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x4a, 0x69, 0x00, 0x2a, 
+0x02, 0xd1, 0x88, 0x61, 0x48, 0x61, 0xf7, 0xe7, 0x8a, 0x69, 0xc0, 0x46, 
+0x50, 0x60, 0x88, 0x61, 0xf2, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 
+0xb0, 0xb5, 0x2a, 0x48, 0x40, 0x69, 0x00, 0x28, 0x4c, 0xd0, 0x08, 0x22, 
+0xc1, 0x68, 0x0a, 0x40, 0x00, 0x27, 0x27, 0x4b, 0xd9, 0x1d, 0xb9, 0x31, 
+0x00, 0x2a, 0x11, 0xd0, 0x04, 0x22, 0x25, 0x4c, 0xc0, 0x46, 0x0c, 0x61, 
+0x24, 0x4c, 0xc0, 0x46, 0x4c, 0x62, 0x24, 0x4c, 0xc0, 0x46, 0x8c, 0x62, 
+0x23, 0x4c, 0xc0, 0x46, 0xcc, 0x62, 0x23, 0x4c, 0xc0, 0x46, 0x0c, 0x63, 
+0x4f, 0x63, 0x12, 0xe0, 0x05, 0x22, 0x21, 0x4c, 0xc0, 0x46, 0x0c, 0x61, 
+0x20, 0x4c, 0xc0, 0x46, 0x4c, 0x62, 0x20, 0x4c, 0xc0, 0x46, 0x8c, 0x62, 
+0x1f, 0x4c, 0xc0, 0x46, 0xcc, 0x62, 0x1f, 0x4c, 0xc0, 0x46, 0x0c, 0x63, 
+0x1e, 0x4c, 0xc0, 0x46, 0x4c, 0x63, 0x40, 0x24, 0xcc, 0x82, 0x4f, 0x83, 
+0x1c, 0x4f, 0x00, 0x21, 0x00, 0x2a, 0x0c, 0xd9, 0x8c, 0x00, 0x05, 0x19, 
+0x6d, 0x6a, 0x7d, 0x40, 0xe4, 0x18, 0xff, 0x34, 0x01, 0x34, 0x65, 0x62, 
+0x01, 0x31, 0x91, 0x42, 0xf4, 0xd3, 0x10, 0x29, 0x07, 0xd2, 0x8a, 0x00, 
+0xd2, 0x18, 0xff, 0x32, 0x01, 0x32, 0x57, 0x62, 0x01, 0x31, 0x10, 0x29, 
+0xf7, 0xd3, 0x11, 0x49, 0x00, 0xf0, 0x22, 0xf8, 0xb0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 
+0x28, 0x01, 0x40, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 
+0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x20, 0x01, 0x40, 0x00, 
+0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, 0xdc, 0xfe, 
+0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0, 0x36, 0x36, 0x36, 0x36, 
+0x30, 0x80, 0x20, 0x40, 0xb0, 0xb5, 0x0f, 0x1c, 0x15, 0x4d, 0xe9, 0x1d, 
+0xc9, 0x31, 0x15, 0x4c, 0x23, 0x1c, 0x15, 0x4a, 0x00, 0x20, 0xfb, 0xf7, 
+0x50, 0xfc, 0xe9, 0x1d, 0xff, 0x31, 0x1e, 0x31, 0x23, 0x1c, 0x0d, 0x1c, 
+0x11, 0x4a, 0x01, 0x20, 0xfb, 0xf7, 0x47, 0xfc, 0x29, 0x1c, 0x23, 0x1c, 
+0x0e, 0x4a, 0x00, 0x20, 0xfb, 0xf7, 0x41, 0xfc, 
+0x39, 0x1c, 0x23, 0x1c, 0x0c, 0x4a, 0x01, 0x20, 0xfb, 0xf7, 0x3b, 0xfc, 
+0x00, 0x21, 0x0b, 0x48, 0xc2, 0x1d, 0x19, 0x32, 0x51, 0x71, 0x01, 0x21, 
+0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x1c, 0xad, 0x20, 0x40, 0x75, 0x08, 0xff, 0xff, 
+0x28, 0x00, 0x03, 0x00, 0x40, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x00, 
+0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x37, 0x4a, 0x50, 0x69, 0x01, 0x23, 
+0x9b, 0x07, 0x08, 0x30, 0x18, 0x43, 0x00, 0x68, 0x01, 0x06, 0x09, 0x0e, 
+0x33, 0x4b, 0x01, 0x29, 0x49, 0xd1, 0x1f, 0x68, 0x19, 0x1c, 0x32, 0x4b, 
+0x9f, 0x42, 0x04, 0xd1, 0xff, 0xf7, 0x3e, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x23, 0x9f, 0x00, 0xcc, 0x59, 0x55, 0x69, 0xef, 0x19, 
+0x3c, 0x61, 0x01, 0x33, 0x05, 0x2b, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 
+0x02, 0x23, 0x18, 0x43, 0x53, 0x69, 0xc0, 0x46, 0x98, 0x60, 0x50, 0x69, 
+0x08, 0x23, 0xc2, 0x68, 0x13, 0x40, 0x25, 0x4f, 0xfa, 0x1d, 0xb9, 0x32, 
+0x00, 0x2b, 0x02, 0xd0, 0x04, 0x23, 0x23, 0x4c, 0x01, 0xe0, 0x05, 0x23, 
+0x22, 0x4c, 0xc0, 0x46, 0x14, 0x61, 0x40, 0x24, 0xd4, 0x82, 0x00, 0x24, 
+0x54, 0x83, 0x20, 0x4c, 0x00, 0x22, 0x00, 0x2b, 0x0c, 0xd9, 0x95, 0x00, 
+0x46, 0x19, 0x76, 0x6a, 0x66, 0x40, 0xed, 0x19, 0xff, 0x35, 0x01, 0x35, 
+0x6e, 0x62, 0x01, 0x32, 0x9a, 0x42, 0xf4, 0xd3, 0x10, 0x2a, 0x07, 0xd2, 
+0x93, 0x00, 0xdb, 0x19, 0xff, 0x33, 0x01, 0x33, 0x5c, 0x62, 0x01, 0x32, 
+0x10, 0x2a, 0xf7, 0xd3, 0xff, 0xf7, 0x70, 0xff, 0xbc, 0xe7, 0x00, 0x21, 
+0x8f, 0x00, 0xdc, 0x59, 0x55, 0x69, 0xef, 0x19, 0x7c, 0x62, 0x01, 0x31, 
+0x05, 0x29, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 0x03, 0x23, 0x18, 0x43, 
+0x51, 0x69, 0xc0, 0x46, 0x88, 0x60, 0x50, 0x69, 0x40, 0x68, 0xc0, 0x46, 
+0x50, 0x61, 0x09, 0x48, 0xfb, 0xf7, 0xb0, 0xfb, 0xa4, 0xe7, 0x00, 0x00, 
+0x6c, 0x06, 0x00, 0x80, 0x30, 0x80, 0x20, 0x40, 0x67, 0x45, 0x23, 0x01, 
+0x1c, 0xad, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00, 
+0x5c, 0x5c, 0x5c, 0x5c, 0xfd, 0x30, 0xff, 0xff, 0x80, 0xb5, 0x87, 0xb0, 
+0x0f, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x48, 0xf8, 0x0e, 0x49, 0xc8, 0x68, 
+0x02, 0x04, 0x89, 0x69, 0x4a, 0x40, 0x05, 0x92, 0x09, 0x04, 0xc9, 0x43, 
+0xc0, 0x43, 0x48, 0x40, 0x06, 0x90, 0x08, 0x21, 0x6a, 0x46, 0x05, 0xa8, 
+0xfd, 0xf7, 0x8b, 0xfb, 0x00, 0x98, 0xc0, 0x46, 0x38, 0x65, 0x03, 0x98, 
+0xc0, 0x46, 0x78, 0x65, 0x04, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 
+0x07, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x08, 0x83, 0x20, 0x40, 
+0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x20, 0x1c, 
+0x39, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0xe0, 0x68, 0x01, 0x0e, 0xff, 0x22, 
+0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 
+0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 0x38, 0x65, 
+0x20, 0x69, 0xc0, 0x46, 0x78, 0x65, 0x60, 0x69, 0xc0, 0x46, 0xb8, 0x65, 
+0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x00, 0x22, 
+0x93, 0x00, 0x1f, 0x18, 0xbf, 0x69, 0x5b, 0x18, 0x5f, 0x62, 0x01, 0x32, 
+0x05, 0x2a, 0xf7, 0xd3, 0x07, 0x7a, 0xfb, 0x08, 0x03, 0xd3, 0x00, 0x23, 
+0x92, 0x00, 0x52, 0x18, 0x13, 0x62, 0x07, 0x6b, 
 0xc0, 0x46, 0x8f, 0x63, 0xc7, 0x6a, 0xc0, 0x46, 0xcf, 0x63, 0x87, 0x6b, 
 0xc0, 0x46, 0x0f, 0x64, 0x47, 0x6b, 0xc0, 0x46, 0x4f, 0x64, 0x07, 0x6c, 
-0xc0, 0x46, 0x8f, 0x64, 0xc2, 0x6b, 0xc0, 0x46, 
-0xca, 0x64, 0xc2, 0x88, 0xc0, 0x46, 0x0a, 0x80, 0x82, 0x7a, 0x12, 0x06, 
-0x03, 0x7a, 0x1b, 0x04, 0x1a, 0x43, 0xc3, 0x88, 0x1b, 0x02, 0x1a, 0x43, 
-0x43, 0x7a, 0xdb, 0x07, 0x1a, 0x43, 0x8a, 0x60, 0x17, 0x1c, 0x83, 0x7a, 
-0x5a, 0x08, 0x05, 0xd3, 0x14, 0x22, 0x1c, 0x1c, 0xa3, 0x08, 0x02, 0xd2, 
-0x15, 0x22, 0x00, 0xe0, 0x00, 0x22, 0x00, 0x7a, 0x43, 0x08, 0x10, 0xd3, 
-0xc0, 0x08, 0x02, 0xd3, 0x88, 0x20, 0x10, 0x43, 0x01, 0xe0, 0x80, 0x20, 
-0x10, 0x43, 0x3a, 0x0a, 0x12, 0x02, 0x01, 0x23, 0x1a, 0x43, 0xc8, 0x60, 
-0x8a, 0x60, 0x08, 0x1c, 0xff, 0xf7, 0x14, 0xfe, 0x05, 0xe0, 0x38, 0x0a, 
-0x00, 0x02, 0x03, 0x23, 0x18, 0x43, 0x88, 0x60, 0xca, 0x60, 0x03, 0x48, 
-0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x78, 0x2a, 0x00, 0x80, 0xf0, 0xb4, 0x02, 0x6d, 0x14, 0x4c, 0x15, 0x1c, 
-0xe7, 0x69, 0xbd, 0x40, 0x13, 0x1c, 0x26, 0x6a, 0xf3, 0x40, 0x5d, 0x40, 
-0x2e, 0x1c, 0x45, 0x6d, 0xbd, 0x40, 0x6e, 0x40, 0x2b, 0x1c, 0x35, 0x1c, 
-0xfd, 0x40, 0x2f, 0x1c, 0xbb, 0x00, 0x65, 0x6a, 0xeb, 0x58, 0x00, 0x2b, 
-0x08, 0xd0, 0x23, 0x69, 0x01, 0x37, 0x9f, 0x42, 0x00, 0xd3, 0x00, 0x27, 
-0xbe, 0x00, 0xae, 0x59, 0x00, 0x2e, 0xf7, 0xd1, 0xa4, 0x69, 0xa2, 0x40, 
-0x11, 0x43, 0x05, 0x4b, 0x19, 0x43, 0xba, 0x00, 0xa9, 0x50, 0x40, 0x30, 
-0x87, 0x83, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xc8, 0x29, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x00, 0xf0, 
-0xb1, 0xfa, 0x20, 0x1c, 0x00, 0xf0, 0x0e, 0xfa, 0x38, 0x0c, 0x00, 0xf0, 
-0x0b, 0xfa, 0x38, 0x0a, 0x00, 0xf0, 0x08, 0xfa, 0x38, 0x1c, 0x00, 0xf0, 
-0x05, 0xfa, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 
-0x00, 0xf0, 0x9e, 0xfa, 0x54, 0x20, 0x00, 0xf0, 0xfb, 0xf9, 0x38, 0x0c, 
-0x00, 0xf0, 0xf8, 0xf9, 0x38, 0x0a, 0x00, 0xf0, 0xf5, 0xf9, 0x38, 0x1c, 
-0x00, 0xf0, 0xf2, 0xf9, 0x00, 0x20, 0x00, 0xf0, 0xef, 0xf9, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 0x89, 0xfa, 0x57, 0x20, 
-0x00, 0xf0, 0xe6, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 
-0x41, 0x02, 0x53, 0x20, 0xff, 0xf7, 0xc8, 0xff, 0x00, 0xf0, 0x64, 0xfa, 
-0x00, 0xf0, 0xf5, 0xf8, 0x00, 0x24, 0x00, 0x26, 0x00, 0x25, 0x00, 0x27, 
-0x30, 0x1c, 0x01, 0x36, 0xff, 0xf7, 0xd0, 0xff, 0x00, 0xf0, 0x46, 0xf9, 
-0x00, 0x90, 0x00, 0xf0, 0x55, 0xfa, 0xf8, 0x00, 0x00, 0x99, 0x81, 0x40, 
-0x0d, 0x43, 0x01, 0x34, 0x01, 0x37, 0x04, 0x2f, 0xee, 0xd3, 0x02, 0x99, 
-0x20, 0xc1, 0x02, 0x91, 0xff, 0x23, 0x09, 0x33, 0x9c, 0x42, 0xe5, 0xd3, 
-0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x04, 0x1c, 
-0x0f, 0x1c, 0x00, 0x26, 0x20, 0xcf, 0xb1, 0x00, 0x84, 0x20, 0xff, 0xf7, 
-0x9b, 0xff, 0x28, 0x1c, 0x00, 0xf0, 0xae, 0xf9, 0x28, 0x0a, 0x00, 0xf0, 
-0xab, 0xf9, 0x28, 0x0c, 0x00, 0xf0, 0xa8, 0xf9, 0x28, 0x0e, 0x00, 0xf0, 
-0xa5, 0xf9, 0x00, 0xf0, 0x2b, 0xfa, 0x01, 0x36, 0x42, 0x2e, 0xe9, 0xd3, 
-0x61, 0x02, 0x83, 0x20, 0xff, 0xf7, 0x86, 0xff, 0x00, 0xf0, 0x22, 0xfa, 
-0x00, 0xf0, 0xb3, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 
-0x41, 0x02, 0x60, 0x20, 0xff, 0xf7, 0x7a, 0xff, 0x00, 0xf0, 0x16, 0xfa, 
-0x00, 0xf0, 0xa7, 0xf8, 0x38, 0x1c, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x90, 0xb5, 0x0f, 0x1c, 0x41, 0x02, 0x53, 0x20, 
-0xff, 0xf7, 0x6c, 0xff, 0x00, 0xf0, 0x08, 0xfa, 0x00, 0xf0, 0x99, 0xf8, 
-0xf8, 0x1d, 0x05, 0x30, 0x44, 0x1c, 0xff, 0xf7, 0x77, 0xff, 0x00, 0xf0, 
-0xed, 0xf8, 0x07, 0x1c, 0x00, 0xf0, 0xfc, 0xf9, 0x20, 0x1c, 0xff, 0xf7, 
-0x6f, 0xff, 0x00, 0xf0, 0xe5, 0xf8, 0x04, 0x1c, 0x00, 0xf0, 0xf4, 0xf9, 
-0x20, 0x02, 0x38, 0x43, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 
-0xc2, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 0x17, 0x1c, 0x61, 0x02, 0x53, 0x20, 
-0xff, 0xf7, 0x48, 0xff, 0x00, 0xf0, 0xe4, 0xf9, 0x00, 0xf0, 0x75, 0xf8, 
-0x68, 0x46, 0x00, 0xf0, 0x5c, 0xf8, 0x6a, 0x46, 0xe8, 0x1d, 0x05, 0x30, 
-0x17, 0x54, 0x39, 0x0a, 0x68, 0x44, 0x41, 0x70, 0x68, 0x46, 0x00, 0x99, 
-0x0c, 0x30, 0x00, 0xf0, 0x73, 0xf8, 0x02, 0xab, 0x18, 0x70, 0x00, 0x20, 
-0x58, 0x70, 0x68, 0x46, 0x0c, 0x21, 0x00, 0xf0, 0x6b, 0xf8, 0x02, 0xab, 
-0x58, 0x70, 0x69, 0x46, 0x20, 0x1c, 0xff, 0xf7, 0x83, 0xff, 0x42, 0xb0, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0xc2, 0xb0, 0x04, 0x1c, 
-0x1f, 0x1c, 0x6b, 0x46, 0x00, 0x20, 0xc5, 0x43, 0x20, 0xc3, 0x01, 0x30, 
-0x42, 0x28, 0xfb, 0xd3, 0x68, 0x46, 0x0c, 0x30, 0x03, 0x1c, 0x00, 0x25, 
-0x00, 0x2a, 0x0a, 0xd9, 0x0e, 0x88, 0xc0, 0x46, 0x06, 0x70, 0x0e, 0x88, 
-0x36, 0x12, 0x46, 0x70, 0x02, 0x30, 0x02, 0x31, 0x02, 0x35, 0x95, 0x42, 
-0xf4, 0xd3, 0x00, 0x92, 0x18, 0x1c, 0x11, 0x1c, 0x00, 0xf0, 0x40, 0xf8, 
-0x00, 0x26, 0x01, 0x96, 0x02, 0xab, 0x18, 0x70, 0x5e, 0x70, 0x9e, 0x70, 
-0xde, 0x70, 0x05, 0x1c, 0x68, 0x46, 0x0c, 0x21, 0x00, 0xf0, 0x34, 0xf8, 
-0x02, 0xab, 0x58, 0x70, 0x38, 0x06, 0x00, 0x0e, 0x85, 0x42, 0x05, 0xd1, 
-0x69, 0x46, 0x20, 0x1c, 0xff, 0xf7, 0x48, 0xff, 0x30, 0x1c, 0x00, 0xe0, 
-0x01, 0x20, 0x42, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
-0x07, 0x1c, 0x00, 0x24, 0xff, 0x26, 0x09, 0x36, 0x20, 0x1c, 0xff, 0xf7, 
-0xf1, 0xfe, 0x00, 0xf0, 0x67, 0xf8, 0x05, 0x1c, 0x00, 0xf0, 0x76, 0xf9, 
-0x3d, 0x70, 0x28, 0x1c, 0x01, 0x37, 0x01, 0x34, 0xb4, 0x42, 0xf1, 0xd3, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0xff, 0xf7, 0xf6, 0xfe, 
-0x00, 0xf0, 0x56, 0xf8, 0x07, 0x1c, 0x00, 0xf0, 0x65, 0xf9, 0x38, 0x0a, 
-0xf6, 0xd3, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb4, 0x00, 0x22, 
-0x00, 0x23, 0x00, 0x29, 0x05, 0xd9, 0x07, 0x78, 0x7a, 0x40, 0x01, 0x30, 
-0x01, 0x33, 0x8b, 0x42, 0xf9, 0xd3, 0xd0, 0x43, 0x00, 0x06, 0x00, 0x0e, 
-0x80, 0xbc, 0x70, 0x47, 0xb0, 0xb5, 0xc2, 0xb0, 0x0f, 0x1c, 0x41, 0x02, 
-0x53, 0x20, 0xff, 0xf7, 0xab, 0xfe, 0x00, 0xf0, 0x47, 0xf9, 0xff, 0xf7, 
-0xd8, 0xff, 0x68, 0x46, 0xff, 0xf7, 0xbf, 0xff, 0x02, 0xad, 0x6d, 0x78, 
-0x00, 0x24, 0x02, 0xab, 0x5c, 0x70, 0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 
-0xd9, 0xff, 0xa8, 0x42, 0x02, 0xd1, 0x00, 0x98, 0x87, 0x42, 0x01, 0xd3, 
-0x20, 0x1c, 0x00, 0xe0, 0x01, 0x20, 0x42, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x80, 0xb5, 0xc2, 0xb0, 0x69, 0x46, 0x02, 0x20, 0xff, 0xf7, 
-0xbb, 0xfe, 0x68, 0x46, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20, 0x07, 0x4a, 
-0x0f, 0x88, 0x43, 0x00, 0xd7, 0x52, 0x02, 0x31, 0x01, 0x30, 0x00, 0x04, 
-0x00, 0x0c, 0x25, 0x28, 0xf6, 0xdb, 0x42, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x70, 0x67, 0x21, 0x40, 0xfc, 0x46, 0x60, 0x47, 
-0x00, 0x00, 0xa0, 0xe3, 0xb4, 0x22, 0x9f, 0xe5, 
+0xc0, 0x46, 0x8f, 0x64, 0xc2, 0x6b, 0xc0, 0x46, 0xca, 0x64, 0xc2, 0x88, 
+0xc0, 0x46, 0x0a, 0x80, 0x82, 0x7a, 0x12, 0x06, 0x03, 0x7a, 0x1b, 0x04, 
+0x1a, 0x43, 0xc3, 0x88, 0x1b, 0x02, 0x1a, 0x43, 0x43, 0x7a, 0xdb, 0x07, 
+0x1a, 0x43, 0x8a, 0x60, 0x17, 0x1c, 0x83, 0x7a, 0x5a, 0x08, 0x05, 0xd3, 
+0x14, 0x22, 0x1c, 0x1c, 0xa3, 0x08, 0x02, 0xd2, 0x15, 0x22, 0x00, 0xe0, 
+0x00, 0x22, 0x00, 0x7a, 0x43, 0x08, 0x10, 0xd3, 0xc0, 0x08, 0x02, 0xd3, 
+0x88, 0x20, 0x10, 0x43, 0x01, 0xe0, 0x80, 0x20, 0x10, 0x43, 0x3a, 0x0a, 
+0x12, 0x02, 0x01, 0x23, 0x1a, 0x43, 0xc8, 0x60, 0x8a, 0x60, 0x08, 0x1c, 
+0xff, 0xf7, 0x0e, 0xfe, 0x05, 0xe0, 0x38, 0x0a, 0x00, 0x02, 0x03, 0x23, 
+0x18, 0x43, 0x88, 0x60, 0xca, 0x60, 0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 
+0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 
+0xf0, 0xb4, 0x02, 0x6d, 0x14, 0x4c, 0x15, 0x1c, 0xe7, 0x69, 0xbd, 0x40, 
+0x13, 0x1c, 0x26, 0x6a, 0xf3, 0x40, 0x5d, 0x40, 0x2e, 0x1c, 0x45, 0x6d, 
+0xbd, 0x40, 0x6e, 0x40, 0x2b, 0x1c, 0x35, 0x1c, 0xfd, 0x40, 0x2f, 0x1c, 
+0xbb, 0x00, 0x65, 0x6a, 0xeb, 0x58, 0x00, 0x2b, 0x08, 0xd0, 0x23, 0x69, 
+0x01, 0x37, 0x9f, 0x42, 0x00, 0xd3, 0x00, 0x27, 0xbe, 0x00, 0xae, 0x59, 
+0x00, 0x2e, 0xf7, 0xd1, 0xa4, 0x69, 0xa2, 0x40, 0x11, 0x43, 0x05, 0x4b, 
+0x19, 0x43, 0xba, 0x00, 0xa9, 0x50, 0x40, 0x30, 0x87, 0x83, 0xf0, 0xbc, 
+0x70, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
+0x80, 0xb4, 0x00, 0x22, 0x00, 0x23, 0x00, 0x29, 0x05, 0xd9, 0x07, 0x78, 
+0x7a, 0x40, 0x01, 0x30, 0x01, 0x33, 0x8b, 0x42, 0xf9, 0xd3, 0xd0, 0x43, 
+0x00, 0x06, 0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0x07, 0x1c, 
+0x00, 0x24, 0xff, 0x26, 0x09, 0x36, 0x20, 0x1c, 0x00, 0xf0, 0x8c, 0xf8, 
+0x00, 0xf0, 0x9e, 0xf9, 0x05, 0x1c, 0x00, 0xf0, 0xad, 0xfa, 0x3d, 0x70, 
+0x28, 0x1c, 0x01, 0x37, 0x01, 0x34, 0xb4, 0x42, 0xf1, 0xd3, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x00, 0xf0, 0x85, 0xf8, 0x00, 0xf0, 
+0x8d, 0xf9, 0x07, 0x1c, 0x00, 0xf0, 0x9c, 0xfa, 0x38, 0x0a, 0xf6, 0xd3, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 0x41, 0x02, 
+0x53, 0x20, 0x00, 0xf0, 0x57, 0xf8, 0x00, 0xf0, 0x8f, 0xfa, 0xff, 0xf7, 
+0xe9, 0xff, 0x00, 0x24, 0x00, 0x26, 0x00, 0x25, 0x00, 0x27, 0x30, 0x1c, 
+0x01, 0x36, 0x00, 0xf0, 0x5f, 0xf8, 0x00, 0xf0, 0x71, 0xf9, 0x00, 0x90, 
+0x00, 0xf0, 0x80, 0xfa, 0xf8, 0x00, 0x00, 0x99, 0x81, 0x40, 0x0d, 0x43, 
+0x01, 0x34, 0x01, 0x37, 0x04, 0x2f, 0xee, 0xd3, 0x02, 0x99, 0x20, 0xc1, 
+0x02, 0x91, 0xff, 0x23, 0x09, 0x33, 0x9c, 0x42, 0xe5, 0xd3, 0x03, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 
+0x16, 0x48, 0xc0, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0x00, 0x26, 0x20, 0xcf, 0xb1, 0x00, 0x84, 0x20, 0x00, 0xf0, 0x24, 0xf8, 
+0x28, 0x1c, 0x00, 0xf0, 0xd3, 0xf9, 0x28, 0x0a, 0x00, 0xf0, 0xd0, 0xf9, 
+0x28, 0x0c, 0x00, 0xf0, 0xcd, 0xf9, 0x28, 0x0e, 0x00, 0xf0, 0xca, 0xf9, 
+0x00, 0xf0, 0x50, 0xfa, 0x01, 0x36, 0x42, 0x2e, 0xe9, 0xd3, 0x61, 0x02, 
+0x83, 0x20, 0x00, 0xf0, 0x0f, 0xf8, 0x00, 0xf0, 
+0x47, 0xfa, 0xff, 0xf7, 0xa1, 0xff, 0x04, 0x48, 0xc0, 0x6f, 0x40, 0x23, 
+0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x00, 0xf0, 
+0x4d, 0xfa, 0x20, 0x1c, 0x00, 0xf0, 0xaa, 0xf9, 0x38, 0x0c, 0x00, 0xf0, 
+0xa7, 0xf9, 0x38, 0x0a, 0x00, 0xf0, 0xa4, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 
+0xa1, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 
+0x54, 0x20, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x96, 0xf9, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 0x31, 0xfa, 0x57, 0x20, 
+0x00, 0xf0, 0x8e, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x08, 0x4f, 
+0xfa, 0x6f, 0x20, 0x23, 0x14, 0x68, 0x9c, 0x43, 0x14, 0x60, 0x23, 0x1c, 
+0xff, 0xf7, 0x73, 0xff, 0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
+0x01, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x90, 0xb5, 0x08, 0x4f, 0xfa, 0x6f, 0x20, 0x23, 0x14, 0x68, 0x9c, 0x43, 
+0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x89, 0xff, 0xf8, 0x6f, 0x20, 0x23, 
+0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x0f, 0x1c, 0x15, 0x4d, 0xe9, 0x6f, 
+0x20, 0x23, 0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0x41, 0x02, 0x53, 0x20, 
+0xff, 0xf7, 0xa6, 0xff, 0x00, 0xf0, 0xde, 0xf9, 0xff, 0xf7, 0x38, 0xff, 
+0xf8, 0x1d, 0x05, 0x30, 0x44, 0x1c, 0xff, 0xf7, 0xb1, 0xff, 0x00, 0xf0, 
+0xc3, 0xf8, 0x07, 0x1c, 0x00, 0xf0, 0xd2, 0xf9, 0x20, 0x1c, 0xff, 0xf7, 
+0xa9, 0xff, 0x00, 0xf0, 0xbb, 0xf8, 0x04, 0x1c, 0x00, 0xf0, 0xca, 0xf9, 
+0xe8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x21, 0x02, 
+0x39, 0x43, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0xc2, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 
+0x17, 0x1c, 0x61, 0x02, 0x19, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x02, 0x68, 
+0x9a, 0x43, 0x02, 0x60, 0x53, 0x20, 0xff, 0xf7, 0x73, 0xff, 0x00, 0xf0, 
+0xab, 0xf9, 0xff, 0xf7, 0x05, 0xff, 0x68, 0x46, 0xff, 0xf7, 0xec, 0xfe, 
+0x6a, 0x46, 0xe8, 0x1d, 0x05, 0x30, 0x17, 0x54, 0x39, 0x0a, 0x68, 0x44, 
+0x41, 0x70, 0x68, 0x46, 0x00, 0x99, 0x0c, 0x30, 0xff, 0xf7, 0xd0, 0xfe, 
+0x02, 0xab, 0x18, 0x70, 0x00, 0x20, 0x58, 0x70, 0x68, 0x46, 0x0c, 0x21, 
+0xff, 0xf7, 0xc8, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x69, 0x46, 0x20, 0x1c, 
+0xff, 0xf7, 0x1f, 0xff, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
+0x01, 0x60, 0x42, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0xff, 0xb5, 0xc2, 0xb0, 0x07, 0x1c, 0x6b, 0x46, 
+0x00, 0x20, 0xc4, 0x43, 0x10, 0xc3, 0x01, 0x30, 0x42, 0x28, 0xfb, 0xd3, 
+0x68, 0x46, 0x0c, 0x30, 0x03, 0x1c, 0x00, 0x24, 0x00, 0x2a, 0x0a, 0xd9, 
+0x0e, 0x88, 0xc0, 0x46, 0x06, 0x70, 0x0e, 0x88, 0x36, 0x12, 0x46, 0x70, 
+0x02, 0x30, 0x02, 0x31, 0x02, 0x34, 0x94, 0x42, 0xf4, 0xd3, 0x00, 0x92, 
+0x18, 0x1c, 0x11, 0x1c, 0xff, 0xf7, 0x96, 0xfe, 0x04, 0x1c, 0x00, 0x20, 
+0x01, 0x90, 0x02, 0xab, 0x1c, 0x70, 0x58, 0x70, 0x9d, 0x70, 0x68, 0x46, 
+0x0c, 0x21, 0xff, 0xf7, 0x8b, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x45, 0x9b, 
+0x1d, 0x06, 0x2d, 0x0e, 0xac, 0x42, 0x03, 0xd1, 0x69, 0x46, 0x38, 0x1c, 
+0xff, 0xf7, 0x4a, 0xff, 0x01, 0x20, 0xac, 0x42, 
+0x00, 0xd1, 0x00, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xb0, 0xb5, 0xc2, 0xb0, 0x0f, 0x1c, 0x41, 0x02, 0x14, 0x4c, 0xe0, 0x6f, 
+0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0x53, 0x20, 0xff, 0xf7, 
+0xfb, 0xfe, 0x00, 0xf0, 0x33, 0xf9, 0xff, 0xf7, 0x8d, 0xfe, 0x68, 0x46, 
+0xff, 0xf7, 0x74, 0xfe, 0xe0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
+0x02, 0xad, 0x01, 0x60, 0x6d, 0x78, 0x00, 0x24, 0x02, 0xab, 0x5c, 0x70, 
+0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 0x56, 0xfe, 0xa8, 0x42, 0x02, 0xd1, 
+0x00, 0x98, 0x87, 0x42, 0x01, 0xd3, 0x20, 0x1c, 0x00, 0xe0, 0x01, 0x20, 
+0x42, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0xfc, 0x46, 0x60, 0x47, 0x00, 0x00, 0xa0, 0xe3, 0xb4, 0x22, 0x9f, 0xe5, 
 0xb4, 0x32, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x03, 0x80, 0xe1, 
@@ -3675,17 +3858,17 @@ const u8 typhoon_firmware_image[] = {
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x20, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
+0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
+0xa0, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0xa0, 0x11, 0xa0, 0xe1, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x11, 0xa0, 0xe1, 
 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x82, 0xe5, 0x20, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
+0x00, 0x10, 0x82, 0xe5, 0xa0, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0xa0, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe1, 
-0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
 0xfc, 0x46, 0x60, 0x47, 0xa0, 0x30, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
@@ -3714,82 +3897,82 @@ const u8 typhoon_firmware_image[] = {
 0x0a, 0x60, 0x70, 0x47, 0xb0, 0x6e, 0x21, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 
 0x00, 0x24, 0x00, 0x2f, 0x21, 0xd0, 0x00, 0x26, 0xf8, 0x79, 0x00, 0x28, 
 0x1b, 0xdd, 0x30, 0x01, 0xc0, 0x19, 0xc5, 0x1d, 0x05, 0x35, 0x00, 0x7b, 
-0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x92, 0xfb, 0x01, 0x1c, 0x8b, 0x68, 
+0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x9e, 0xfb, 0x01, 0x1c, 0x8b, 0x68, 
 0x00, 0x2b, 0x08, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x05, 0xd0, 0xca, 0x68, 
-0xa9, 0x68, 0xfb, 0xf7, 0x4a, 0xfb, 0x00, 0x20, 0x68, 0x60, 0x70, 0x1c, 
+0xa9, 0x68, 0xfa, 0xf7, 0x4e, 0xff, 0x00, 0x20, 0x68, 0x60, 0x70, 0x1c, 
 0x06, 0x06, 0x36, 0x0e, 0xf8, 0x79, 0xb0, 0x42, 0xe3, 0xdc, 0xff, 0x20, 
-0x38, 0x72, 0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 
-0x81, 0xb0, 0x0f, 0x1c, 0x68, 0x46, 0xff, 0xf7, 0xbd, 0xff, 0x00, 0x28, 
-0x01, 0xd1, 0x0d, 0x20, 0x37, 0xe0, 0xb9, 0x88, 0xc0, 0x46, 0x01, 0x80, 
-0xf9, 0x88, 0xc0, 0x46, 0x41, 0x80, 0xb9, 0x7a, 0xc0, 0x46, 0x41, 0x71, 
-0xf9, 0x7a, 0xc0, 0x46, 0x81, 0x71, 0x8c, 0x21, 0x01, 0x71, 0x3d, 0x7e, 
-0x00, 0x21, 0x00, 0x23, 0x00, 0x2d, 0x1f, 0xdd, 0x1a, 0x01, 0xd2, 0x19, 
-0x1c, 0x32, 0x16, 0x78, 0x05, 0x2e, 0x0d, 0xdc, 0x0c, 0x01, 0x24, 0x18, 
-0x26, 0x73, 0x96, 0x68, 0xc0, 0x46, 0x66, 0x61, 0xd6, 0x68, 0xc0, 0x46, 
-0x26, 0x61, 0x00, 0x24, 0x01, 0x31, 0x09, 0x06, 0x09, 0x0e, 0xd4, 0x60, 
-0x5a, 0x1c, 0x13, 0x06, 0x1b, 0x0e, 0xab, 0x42, 0xe6, 0xdb, 0x00, 0x29, 
-0x04, 0xd0, 0xc1, 0x71, 0x00, 0x99, 0xc0, 0x46, 
+0x38, 0x72, 0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 0x0f, 0x1c, 0x68, 0x46, 0xff, 0xf7, 
+0xbd, 0xff, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20, 0x37, 0xe0, 0xb9, 0x88, 
+0xc0, 0x46, 0x01, 0x80, 0xf9, 0x88, 0xc0, 0x46, 0x41, 0x80, 0xb9, 0x7a, 
+0xc0, 0x46, 0x41, 0x71, 0xf9, 0x7a, 0xc0, 0x46, 0x81, 0x71, 0x8c, 0x21, 
+0x01, 0x71, 0x3d, 0x7e, 0x00, 0x21, 0x00, 0x23, 0x00, 0x2d, 0x1f, 0xdd, 
+0x1a, 0x01, 0xd2, 0x19, 0x1c, 0x32, 0x16, 0x78, 0x05, 0x2e, 0x0d, 0xdc, 
+0x0c, 0x01, 0x24, 0x18, 0x26, 0x73, 0x96, 0x68, 0xc0, 0x46, 0x66, 0x61, 
+0xd6, 0x68, 0xc0, 0x46, 0x26, 0x61, 0x00, 0x24, 0x01, 0x31, 0x09, 0x06, 
+0x09, 0x0e, 0xd4, 0x60, 0x5a, 0x1c, 0x13, 0x06, 0x1b, 0x0e, 0xab, 0x42, 
+0xe6, 0xdb, 0x00, 0x29, 0x04, 0xd0, 0xc1, 0x71, 0x00, 0x99, 0xc0, 0x46, 
 0x01, 0x72, 0x00, 0xe0, 0x00, 0x20, 0x01, 0x99, 0xc0, 0x46, 0x08, 0x60, 
 0x00, 0x20, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
 0x07, 0x1c, 0x38, 0x7e, 0x00, 0x28, 0x28, 0xd0, 0x01, 0x38, 0x05, 0x06, 
 0x2d, 0x0e, 0x00, 0x26, 0xff, 0x2d, 0x21, 0xd0, 0x28, 0x01, 0xc0, 0x19, 
 0xc4, 0x1d, 0x15, 0x34, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 
-0x1f, 0xfb, 0x01, 0x1c, 0x11, 0xd0, 0x8a, 0x68, 0x00, 0x2a, 0x0c, 0xd0, 
+0x2b, 0xfb, 0x01, 0x1c, 0x11, 0xd0, 0x8a, 0x68, 0x00, 0x2a, 0x0c, 0xd0, 
 0xe0, 0x68, 0x00, 0x28, 0x09, 0xd0, 0x00, 0x23, 0xcb, 0x56, 0x05, 0x2b, 
-0x05, 0xdc, 0x13, 0x1c, 0xca, 0x68, 0xa1, 0x68, 0xfb, 0xf7, 0xd1, 0xfa, 
+0x05, 0xdc, 0x13, 0x1c, 0xca, 0x68, 0xa1, 0x68, 0xfa, 0xf7, 0xd5, 0xfe, 
 0xe6, 0x60, 0xff, 0x20, 0x20, 0x70, 0x68, 0x1e, 0x05, 0x06, 0x2d, 0x0e, 
 0xff, 0x2d, 0xdd, 0xd1, 0x3e, 0x76, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0x13, 0x20, 0x70, 0x47, 0xf0, 0xb5, 0x82, 0xb0, 0x07, 0x1c, 0xf8, 0x1d, 
 0xd5, 0x30, 0x39, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x00, 0x90, 0x00, 0x98, 
 0x00, 0x28, 0x3b, 0xd1, 0x38, 0x7e, 0xc0, 0x46, 0x01, 0x90, 0x00, 0x26, 
 0x01, 0x98, 0x00, 0x28, 0x2d, 0xdd, 0x30, 0x01, 0xc0, 0x19, 0xc5, 0x1d, 
-0x15, 0x35, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0xe4, 0xfa, 
+0x15, 0x35, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0xf0, 0xfa, 
 0x04, 0x1c, 0x20, 0x69, 0x00, 0x28, 0x17, 0xd0, 0x28, 0x78, 0x05, 0x28, 
 0x0d, 0xdd, 0xe9, 0x68, 0xaa, 0x68, 0x60, 0x68, 0x40, 0x08, 0x40, 0x00, 
-0x01, 0xf0, 0x0e, 0xf8, 0x09, 0x22, 0xe8, 0x68, 0xa9, 0x68, 0xfb, 0xf7, 
-0x87, 0xf9, 0x00, 0x20, 0xe8, 0x60, 0x21, 0x69, 0x28, 0x1c, 0xfb, 0xf7, 
-0x8c, 0xfa, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x90, 0x00, 0x98, 0x00, 0x28, 
+0x01, 0xf0, 0x2c, 0xf8, 0x09, 0x22, 0xe8, 0x68, 0xa9, 0x68, 0xfa, 0xf7, 
+0x8b, 0xfd, 0x00, 0x20, 0xe8, 0x60, 0x21, 0x69, 0x28, 0x1c, 0xfa, 0xf7, 
+0x90, 0xfe, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x90, 0x00, 0x98, 0x00, 0x28, 
 0x0c, 0xd1, 0x70, 0x1c, 0x06, 0x06, 0x36, 0x0e, 0x01, 0x98, 0x86, 0x42, 
 0xd1, 0xdb, 0x00, 0x20, 0x38, 0x76, 0x00, 0x98, 0x02, 0xb0, 0xf0, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x82, 0xff, 0xf6, 0xe7, 
 0xc1, 0x1d, 0x79, 0x31, 0x4a, 0x6b, 0xc0, 0x46, 0xca, 0x63, 0xc1, 0x1d, 
 0xb9, 0x31, 0x0a, 0x60, 0x00, 0x22, 0x8a, 0x60, 0x04, 0x4a, 0xc0, 0x46, 
 0x4a, 0x61, 0x8a, 0x61, 0x01, 0x21, 0xd0, 0x30, 0x41, 0x70, 0x08, 0x1c, 
-0x70, 0x47, 0x00, 0x00, 0xb9, 0xbd, 0x21, 0x40, 0xf8, 0xb5, 0x07, 0x1c, 
+0x70, 0x47, 0x00, 0x00, 0xb1, 0xc5, 0x21, 0x40, 0xf8, 0xb5, 0x07, 0x1c, 
 0x00, 0x20, 0x00, 0x90, 0xfe, 0x1d, 0xc9, 0x36, 0x30, 0x78, 0x00, 0x01, 
 0xc0, 0x19, 0xc4, 0x1d, 0x15, 0x34, 0x80, 0x6a, 0x45, 0x08, 0x6d, 0x00, 
 0x04, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xb2, 0xfe, 0x31, 0x78, 0x40, 0x18, 
 0x01, 0x06, 0x09, 0x0e, 0x00, 0x20, 0xa2, 0x68, 0x00, 0x2a, 0x0a, 0xd9, 
 0x2a, 0x78, 0x4a, 0x40, 0x2a, 0x70, 0x01, 0x30, 0x09, 0x18, 0x09, 0x06, 
-0x09, 0x0e, 0xa2, 0x68, 0x01, 0x35, 0x82, 0x42, 0xf4, 0xd8, 0xe0, 0x68, 
-0xa1, 0x68, 0x40, 0x08, 0x40, 0x00, 0xff, 0xf7, 0x99, 0xfe, 0x61, 0x78, 
-0x81, 0x42, 0x0a, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x0f, 0xf8, 0xf8, 0x1d, 
-0x79, 0x30, 0x80, 0x6b, 0xf9, 0x1d, 0xb9, 0x31, 0xc8, 0x60, 0x0c, 0x20, 
-0x00, 0x90, 0x30, 0x78, 0x01, 0x30, 0x30, 0x70, 0x00, 0x98, 0xf8, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d, 0xc9, 0x32, 0x11, 0x78, 0x09, 0x01, 
-0x09, 0x18, 0x09, 0x6a, 0xc3, 0x1d, 0x79, 0x33, 0xd9, 0x63, 0x13, 0x78, 
-0x1b, 0x01, 0x1b, 0x18, 0x5b, 0x6a, 0xcb, 0x18, 0xc1, 0x1d, 0xb9, 0x31, 
-0x0b, 0x60, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18, 0x9b, 0x6a, 0xc0, 0x46, 
-0x8b, 0x60, 0x07, 0x4b, 0xc0, 0x46, 0x4b, 0x61, 0x12, 0x78, 0x00, 0x7e, 
-0x01, 0x32, 0x82, 0x42, 0x01, 0xdb, 0x04, 0x48, 
+0x09, 0x0e, 0xa2, 0x68, 0x01, 0x35, 0x82, 0x42, 
+0xf4, 0xd8, 0xe0, 0x68, 0xa1, 0x68, 0x40, 0x08, 0x40, 0x00, 0xff, 0xf7, 
+0x99, 0xfe, 0x61, 0x78, 0x81, 0x42, 0x0a, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
+0x0f, 0xf8, 0xf8, 0x1d, 0x79, 0x30, 0x80, 0x6b, 0xf9, 0x1d, 0xb9, 0x31, 
+0xc8, 0x60, 0x0c, 0x20, 0x00, 0x90, 0x30, 0x78, 0x01, 0x30, 0x30, 0x70, 
+0x00, 0x98, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d, 0xc9, 0x32, 
+0x11, 0x78, 0x09, 0x01, 0x09, 0x18, 0x09, 0x6a, 0xc3, 0x1d, 0x79, 0x33, 
+0xd9, 0x63, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18, 0x5b, 0x6a, 0xcb, 0x18, 
+0xc1, 0x1d, 0xb9, 0x31, 0x0b, 0x60, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18, 
+0x9b, 0x6a, 0xc0, 0x46, 0x8b, 0x60, 0x07, 0x4b, 0xc0, 0x46, 0x4b, 0x61, 
+0x12, 0x78, 0x00, 0x7e, 0x01, 0x32, 0x82, 0x42, 0x01, 0xdb, 0x04, 0x48, 
 0x00, 0xe0, 0x04, 0x48, 0xc0, 0x46, 0x88, 0x61, 0x00, 0x20, 0x70, 0x47, 
-0x81, 0xbe, 0x21, 0x40, 0x55, 0xbe, 0x21, 0x40, 0x01, 0xbf, 0x21, 0x40, 
+0x79, 0xc6, 0x21, 0x40, 0x4d, 0xc6, 0x21, 0x40, 0xf9, 0xc6, 0x21, 0x40, 
 0xf8, 0xb5, 0x04, 0x1c, 0x00, 0x20, 0x00, 0x90, 0x25, 0x7e, 0x29, 0x01, 
 0xe0, 0x1d, 0x15, 0x30, 0xff, 0xf7, 0x4e, 0xfe, 0xa1, 0x7e, 0x81, 0x42, 
 0x0a, 0xd0, 0x20, 0x1c, 0x00, 0xf0, 0x61, 0xf8, 0xe0, 0x1d, 0x79, 0x30, 
 0x80, 0x6b, 0xe1, 0x1d, 0xb9, 0x31, 0xc8, 0x60, 0x0b, 0x20, 0x55, 0xe0, 
 0x00, 0x27, 0x00, 0x2d, 0x0f, 0xdd, 0x38, 0x01, 0x00, 0x19, 0x00, 0x7f, 
-0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x10, 0xfa, 0x00, 0x28, 0x01, 0xd1, 
+0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x1c, 0xfa, 0x00, 0x28, 0x01, 0xd1, 
 0x09, 0x20, 0x47, 0xe0, 0x78, 0x1c, 0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 
 0xef, 0xdb, 0x00, 0x26, 0x00, 0x2d, 0x38, 0xdd, 0x30, 0x01, 0x00, 0x19, 
 0xc7, 0x1d, 0x15, 0x37, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 
-0xfb, 0xf9, 0x00, 0x23, 0xc1, 0x56, 0x05, 0x29, 0x0c, 0xdc, 0x42, 0x68, 
-0x00, 0x2a, 0x04, 0xd0, 0xc1, 0x68, 0xb8, 0x68, 0xfb, 0xf7, 0xb2, 0xf9, 
+0x07, 0xfa, 0x00, 0x23, 0xc1, 0x56, 0x05, 0x29, 0x0c, 0xdc, 0x42, 0x68, 
+0x00, 0x2a, 0x04, 0xd0, 0xc1, 0x68, 0xb8, 0x68, 0xfa, 0xf7, 0xb6, 0xfd, 
 0xf8, 0x60, 0xf8, 0x68, 0x00, 0x28, 0x1b, 0xd1, 0x0e, 0x20, 0x17, 0xe0, 
-0xc0, 0x68, 0x00, 0x28, 0x07, 0xd0, 0xfb, 0xf7, 0xa5, 0xf9, 0x00, 0x28, 
+0xc0, 0x68, 0x00, 0x28, 0x07, 0xd0, 0xfa, 0xf7, 0xa9, 0xfd, 0x00, 0x28, 
 0x05, 0xda, 0x40, 0x42, 0xb9, 0x68, 0x81, 0x42, 0x04, 0xd0, 0x05, 0x20, 
 0x0a, 0xe0, 0xb9, 0x68, 0x81, 0x42, 0xfa, 0xd8, 0x09, 0x21, 0xb8, 0x68, 
-0xfb, 0xf7, 0x7a, 0xf8, 0xf8, 0x60, 0x00, 0x28, 0x02, 0xd1, 0x06, 0x20, 
+0xfa, 0xf7, 0x7e, 0xfc, 0xf8, 0x60, 0x00, 0x28, 0x02, 0xd1, 0x06, 0x20, 
 0x00, 0x90, 0x07, 0xe0, 0x70, 0x1c, 0x06, 0x06, 0x36, 0x0e, 0xae, 0x42, 
 0xc6, 0xdb, 0x00, 0x98, 0x00, 0x28, 0x02, 0xd0, 0x20, 0x1c, 0xff, 0xf7, 
 0x92, 0xfe, 0x00, 0x98, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d, 
@@ -3797,25 +3980,25 @@ const u8 typhoon_firmware_image[] = {
 0x8a, 0x18, 0xc1, 0x1d, 0xb9, 0x31, 0x0a, 0x60, 0xc2, 0x1d, 0x15, 0x32, 
 0x8a, 0x60, 0x05, 0x4a, 0xc0, 0x46, 0x4a, 0x61, 0x04, 0x4a, 0xc0, 0x46, 
 0x8a, 0x61, 0x00, 0x21, 0xd0, 0x30, 0x01, 0x70, 0x08, 0x1c, 0x70, 0x47, 
-0x59, 0xbf, 0x21, 0x40, 0x01, 0xbf, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 
+0x51, 0xc7, 0x21, 0x40, 0xf9, 0xc6, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 
 0x38, 0x68, 0x1d, 0x4b, 0x98, 0x42, 0x03, 0xd0, 0x03, 0x20, 0x90, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x1c, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xbc, 0xfd, 
 0xfc, 0x1d, 0x79, 0x34, 0x00, 0x28, 0x09, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
 0x2d, 0xf8, 0xf9, 0x1d, 0xb9, 0x31, 0xa0, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 
 0x0a, 0x20, 0xea, 0xe7, 0x38, 0x7a, 0x1c, 0x28, 0x04, 0xd0, 0x78, 0x7a, 
 0x10, 0x28, 0x01, 0xd0, 0x04, 0x20, 0xe2, 0xe7, 0xb8, 0x7a, 0x01, 0x28, 
-0x01, 0xd0, 0x07, 0x20, 0xdd, 0xe7, 0x60, 0x6b, 0xf9, 0x68, 0x88, 0x42, 
-0x01, 0xd0, 0x05, 0x20, 0xd7, 0xe7, 0x38, 0x69, 0x00, 0x28, 0x04, 0xd0, 
-0x06, 0x4b, 0x98, 0x42, 0x01, 0xd0, 0x08, 0x20, 0xcf, 0xe7, 0x38, 0x7e, 
-0x08, 0x28, 0x01, 0xdd, 0x12, 0x20, 0xca, 0xe7, 0x00, 0x20, 0xc8, 0xe7, 
-0x73, 0x6e, 0x69, 0x70, 0x17, 0x40, 0x00, 0x02, 0xb8, 0xb5, 0x07, 0x1c, 
-0x38, 0x1c, 0xff, 0xf7, 0x2a, 0xfe, 0x00, 0x25, 0xf8, 0x1d, 0xc9, 0x30, 
-0x45, 0x70, 0xfc, 0x1d, 0xb9, 0x34, 0xe5, 0x61, 0x68, 0x46, 0xff, 0xf7, 
-0x9d, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20, 0x0d, 0xe0, 0xf8, 0x1d, 
-0x79, 0x30, 0x85, 0x63, 0xc5, 0x63, 0x1b, 0x20, 0x20, 0x60, 0xa7, 0x60, 
-0x04, 0x48, 0xc0, 0x46, 0x60, 0x61, 0x04, 0x48, 0xc0, 0x46, 0xa0, 0x61, 
-0x28, 0x1c, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x75, 0xc0, 0x21, 0x40, 0x3b, 0xc0, 0x21, 0x40, 0xf0, 0xb5, 0x82, 0xb0, 
+0x01, 0xd0, 0x07, 0x20, 0xdd, 0xe7, 0x60, 0x6b, 
+0xf9, 0x68, 0x88, 0x42, 0x01, 0xd0, 0x05, 0x20, 0xd7, 0xe7, 0x38, 0x69, 
+0x00, 0x28, 0x04, 0xd0, 0x06, 0x4b, 0x98, 0x42, 0x01, 0xd0, 0x08, 0x20, 
+0xcf, 0xe7, 0x38, 0x7e, 0x08, 0x28, 0x01, 0xdd, 0x12, 0x20, 0xca, 0xe7, 
+0x00, 0x20, 0xc8, 0xe7, 0x73, 0x6e, 0x69, 0x70, 0x02, 0x10, 0x00, 0x03, 
+0xb8, 0xb5, 0x07, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x2a, 0xfe, 0x00, 0x25, 
+0xf8, 0x1d, 0xc9, 0x30, 0x45, 0x70, 0xfc, 0x1d, 0xb9, 0x34, 0xe5, 0x61, 
+0x68, 0x46, 0xff, 0xf7, 0x9d, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20, 
+0x0d, 0xe0, 0xf8, 0x1d, 0x79, 0x30, 0x85, 0x63, 0xc5, 0x63, 0x1b, 0x20, 
+0x20, 0x60, 0xa7, 0x60, 0x04, 0x48, 0xc0, 0x46, 0x60, 0x61, 0x04, 0x48, 
+0xc0, 0x46, 0xa0, 0x61, 0x28, 0x1c, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x6d, 0xc8, 0x21, 0x40, 0x33, 0xc8, 0x21, 0x40, 0xf0, 0xb5, 0x82, 0xb0, 
 0x07, 0x1c, 0x00, 0x20, 0xfd, 0x1d, 0x79, 0x35, 0xfc, 0x1d, 0xb9, 0x34, 
 0xe9, 0x6a, 0xc0, 0x46, 0x61, 0x60, 0x62, 0x68, 0xe9, 0x6b, 0x8a, 0x42, 
 0x03, 0xd2, 0x61, 0x60, 0x2a, 0x6b, 0x91, 0x42, 0x34, 0xd2, 0x66, 0x68, 
@@ -3823,52 +4006,54 @@ const u8 typhoon_firmware_image[] = {
 0x26, 0x68, 0x2a, 0x6b, 0x96, 0x42, 0x00, 0xd2, 0x32, 0x1c, 0x01, 0x9e, 
 0x96, 0x1b, 0xa2, 0x68, 0xc0, 0x46, 0x00, 0x92, 0x00, 0x2a, 0x09, 0xd0, 
 0x28, 0x6a, 0x6a, 0x6a, 0x41, 0x18, 0x00, 0x98, 0xc0, 0x18, 0x33, 0x1c, 
-0xfc, 0xf7, 0xc4, 0xff, 0x00, 0x28, 0x1b, 0xd1, 0x61, 0x68, 0x89, 0x19, 
+0xfc, 0xf7, 0x68, 0xff, 0x00, 0x28, 0x1b, 0xd1, 0x61, 0x68, 0x89, 0x19, 
 0x61, 0x60, 0x22, 0x68, 0x91, 0x42, 0x0d, 0xd1, 0x61, 0x69, 0x38, 0x1c, 
-0xfb, 0xf7, 0xc1, 0xf8, 0x00, 0x06, 0x00, 0x0e, 0x0e, 0xd1, 0xa1, 0x69, 
-0x38, 0x1c, 0xfb, 0xf7, 0xba, 0xf8, 0x00, 0x06, 0x00, 0x0e, 0x07, 0xd1, 
+0xfa, 0xf7, 0xc5, 0xfc, 0x00, 0x06, 0x00, 0x0e, 0x0e, 0xd1, 0xa1, 0x69, 
+0x38, 0x1c, 0xfa, 0xf7, 0xbe, 0xfc, 0x00, 0x06, 0x00, 0x0e, 0x07, 0xd1, 
 0x61, 0x68, 0x2a, 0x6b, 0x91, 0x42, 0xc2, 0xd3, 0xa9, 0x6b, 0xaa, 0x6a, 
 0x89, 0x18, 0xa9, 0x63, 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xb0, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfb, 0xf7, 
-0xbf, 0xfa, 0xfa, 0x1d, 0x09, 0x32, 0x32, 0x48, 0x00, 0x21, 0xc9, 0x43, 
-0xc4, 0x1d, 0xb9, 0x34, 0xe1, 0x60, 0xf9, 0x88, 0xc3, 0x1d, 0x89, 0x33, 
-0x19, 0x73, 0xc1, 0x1d, 0x79, 0x31, 0xbd, 0x68, 0xc0, 0x46, 0x0d, 0x62, 
-0xff, 0x68, 0xc0, 0x46, 0x4f, 0x62, 0x17, 0x68, 0xc0, 0x46, 0x8f, 0x62, 
-0x57, 0x68, 0xc0, 0x46, 0xcf, 0x62, 0x92, 0x68, 0xc0, 0x46, 0x4a, 0x63, 
-0xca, 0x6a, 0x8f, 0x6a, 0xd2, 0x19, 0x0a, 0x63, 0x1a, 0x7b, 0x01, 0x2a, 
-0x0d, 0xd0, 0x02, 0x2a, 0x1a, 0xd0, 0x03, 0x2a, 0x2e, 0xd1, 0xc2, 0x1d, 
-0xc9, 0x32, 0x52, 0x78, 0x00, 0x2a, 0x07, 0xd1, 0x10, 0x20, 0x89, 0x6b, 
-0xc0, 0x46, 0xe1, 0x60, 0x25, 0xe0, 0xff, 0xf7, 0x4d, 0xff, 0x22, 0xe0, 
-0xff, 0xf7, 0xac, 0xfd, 0x00, 0x28, 0x1e, 0xd1, 0xe1, 0x69, 0x00, 0x29, 
-0x1b, 0xd0, 0x09, 0x7a, 0x15, 0x4b, 0xc9, 0x18, 0x02, 0x91, 0x16, 0xe0, 
-0x8a, 0x6a, 0xcb, 0x6a, 0x9f, 0x18, 0x4d, 0x6b, 0xaf, 0x42, 0x05, 0xd8, 
-0x00, 0x2a, 0x03, 0xd0, 0x9f, 0x07, 0x01, 0xd1, 0x92, 0x07, 0x01, 0xd0, 
-0x0f, 0x20, 0x08, 0xe0, 0x89, 0x6b, 0x99, 0x42, 0x01, 0xd0, 0xe1, 0x60, 
-0xf8, 0xe7, 0xff, 0xf7, 0x53, 0xff, 0x00, 0xe0, 0x10, 0x20, 0x01, 0xab, 
-0x58, 0x80, 0xe0, 0x68, 0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 
-0xfb, 0xf7, 0x9e, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x3c, 0xac, 0x20, 0x40, 0x0d, 0xf0, 0xfe, 0xca, 
-0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfb, 0xf7, 
-0x4d, 0xfa, 0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7, 0xa0, 0xfc, 0x00, 0x28, 
-0x02, 0xd1, 0x00, 0x98, 0xff, 0xf7, 0xc4, 0xfc, 0x02, 0xab, 0x58, 0x80, 
-0x00, 0x21, 0x01, 0xa8, 0xfb, 0xf7, 0x7e, 0xf9, 0x01, 0x20, 0x05, 0xb0, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 
-0x38, 0x1c, 0x01, 0xa9, 0xfb, 0xf7, 0x32, 0xfa, 0x68, 0x46, 0xb9, 0x68, 
-0xff, 0xf7, 0x85, 0xfc, 0x00, 0x28, 0x00, 0xd1, 0x02, 0x20, 0x02, 0xab, 
-0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfb, 0xf7, 0x65, 0xf9, 0x01, 0x20, 
-0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x85, 0xb0, 
-0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfb, 0xf7, 
-0x19, 0xfa, 0x3c, 0x69, 0x38, 0x1c, 0x01, 0xa9, 0xfb, 0xf7, 0x14, 0xfa, 
-0x68, 0x46, 0x21, 0x1c, 0xff, 0xf7, 0x67, 0xfc, 0x8c, 0x24, 0x00, 0x28, 
+0xf0, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfa, 0xf7, 
+0xc3, 0xfe, 0xfa, 0x1d, 0x09, 0x32, 0x37, 0x49, 0x00, 0x20, 0xc0, 0x43, 
+0xcc, 0x1d, 0xb9, 0x34, 0xe0, 0x60, 0xf8, 0x88, 0xcb, 0x1d, 0x89, 0x33, 
+0x18, 0x73, 0xc8, 0x1d, 0x79, 0x30, 0xbd, 0x68, 0xc0, 0x46, 0x05, 0x62, 
+0xff, 0x68, 0xc0, 0x46, 0x47, 0x62, 0x17, 0x68, 0xc0, 0x46, 0x87, 0x62, 
+0x57, 0x68, 0xc0, 0x46, 0xc7, 0x62, 0x92, 0x68, 0xc0, 0x46, 0x42, 0x63, 
+0xc2, 0x6a, 0x87, 0x6a, 0xd2, 0x19, 0x02, 0x63, 0x1a, 0x7b, 0x28, 0x4d, 
+0x01, 0x2a, 0x0d, 0xd0, 0x02, 0x2a, 0x1c, 0xd0, 0x03, 0x2a, 0x35, 0xd1, 
+0xca, 0x1d, 0xc9, 0x32, 0x52, 0x78, 0x00, 0x2a, 0x08, 0xd1, 0x10, 0x27, 
+0x80, 0x6b, 0xc0, 0x46, 0xe0, 0x60, 0x2c, 0xe0, 0x08, 0x1c, 0xff, 0xf7, 
+0x4b, 0xff, 0x22, 0xe0, 0x08, 0x1c, 0xff, 0xf7, 0xa9, 0xfd, 0x07, 0x1c, 
+0x23, 0xd1, 0xe0, 0x69, 0x00, 0x28, 0x1c, 0xd0, 0x00, 0x7a, 0x1a, 0x4b, 
+0xc0, 0x18, 0x02, 0x90, 0x17, 0xe0, 0x82, 0x6a, 0xc3, 0x6a, 0x9f, 0x18, 
+0x46, 0x6b, 0xb7, 0x42, 0x05, 0xd8, 0x00, 0x2a, 0x03, 0xd0, 0x9f, 0x07, 
+0x01, 0xd1, 0x92, 0x07, 0x01, 0xd0, 0x0f, 0x27, 0x0d, 0xe0, 0x80, 0x6b, 
+0x98, 0x42, 0x01, 0xd0, 0xe0, 0x60, 0xf8, 0xe7, 0x08, 0x1c, 0xff, 0xf7, 
+0x4f, 0xff, 0x07, 0x1c, 0x03, 0xd1, 0x00, 0xf0, 0x1f, 0xfe, 0x01, 0xe0, 
+0x10, 0x27, 0x00, 0x20, 0x28, 0x65, 0x01, 0xab, 0x5f, 0x80, 0xe0, 0x68, 
+0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 
+0xfa, 0xf7, 0x98, 0xfd, 0x01, 0x20, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x3c, 0xac, 0x20, 0x40, 0x00, 0x00, 0x00, 0x80, 
+0x0d, 0xf0, 0xfe, 0xca, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 
+0x01, 0xa9, 0xfa, 0xf7, 0x45, 0xfe, 0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7, 
+0x94, 0xfc, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x98, 0xff, 0xf7, 0xb8, 0xfc, 
+0x02, 0xab, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 0x76, 0xfd, 
+0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 
+0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 0x2a, 0xfe, 
+0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7, 0x79, 0xfc, 0x00, 0x28, 0x00, 0xd1, 
+0x02, 0x20, 0x02, 0xab, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 
+0x5d, 0xfd, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x90, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 
+0x11, 0xfe, 0x3c, 0x69, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 0x0c, 0xfe, 
+0x68, 0x46, 0x21, 0x1c, 0xff, 0xf7, 0x5b, 0xfc, 0x8c, 0x24, 0x00, 0x28, 
 0x0e, 0xd1, 0xb9, 0x68, 0x00, 0x29, 0x02, 0xd1, 0xfa, 0x68, 0x00, 0x2a, 
 0x08, 0xd0, 0xf8, 0x88, 0x23, 0x1c, 0x8c, 0x28, 0x00, 0xd8, 0x03, 0x1c, 
-0xf8, 0x68, 0x00, 0x9a, 0xfc, 0xf7, 0x38, 0xfe, 0x02, 0xab, 0x58, 0x80, 
-0x03, 0x94, 0x00, 0x21, 0x01, 0xa8, 0xfb, 0xf7, 0x37, 0xf9, 0x01, 0x20, 
+0xf8, 0x68, 0x00, 0x9a, 0xfc, 0xf7, 0xd0, 0xfd, 0x02, 0xab, 0x58, 0x80, 
+0x03, 0x94, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 0x2f, 0xfd, 0x01, 0x20, 
 0x05, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0x04, 0x48, 
 0xff, 0x22, 0x02, 0x72, 0x8c, 0x30, 0x01, 0x31, 0x04, 0x29, 0xfa, 0xd3, 
 0x70, 0x47, 0x00, 0x00, 0xb0, 0x6e, 0x21, 0x40, 0x02, 0x48, 0x03, 0x49, 
-0x40, 0x1a, 0x40, 0x42, 0x70, 0x47, 0x00, 0x00, 0xb9, 0xce, 0x21, 0x40, 
-0xb5, 0xce, 0x21, 0x40, 0x00, 0x21, 0x08, 0x4a, 0x8b, 0x00, 0x5b, 0x18, 
+0x40, 0x1a, 0x40, 0x42, 0x70, 0x47, 0x00, 0x00, 0xed, 0xd6, 0x21, 0x40, 
+0xe9, 0xd6, 0x21, 0x40, 0x00, 0x21, 0x08, 0x4a, 0x8b, 0x00, 0x5b, 0x18, 
 0x9b, 0x00, 0xd3, 0x56, 0x83, 0x42, 0x04, 0xd1, 0x88, 0x00, 0x40, 0x18, 
 0x80, 0x00, 0x80, 0x18, 0x70, 0x47, 0x01, 0x31, 0x01, 0x29, 0xf1, 0xd3, 
 0x00, 0x20, 0xf9, 0xe7, 0xe0, 0x70, 0x21, 0x40, 0x80, 0xb5, 0x00, 0xf0, 
@@ -3883,212 +4068,215 @@ const u8 typhoon_firmware_image[] = {
 0x02, 0x6b, 0xcb, 0x69, 0xd2, 0x18, 0x02, 0x63, 0x4a, 0x6a, 0x43, 0x6b, 
 0x9b, 0x18, 0x43, 0x63, 0x93, 0x42, 0x02, 0xd2, 0x82, 0x6b, 0x01, 0x32, 
 0x82, 0x63, 0xc2, 0x6b, 0x4b, 0x69, 0xd2, 0x18, 0xc2, 0x63, 0x02, 0x6c, 
-0xc9, 0x6a, 0x51, 0x18, 0x01, 0x64, 0x70, 0x47, 0x10, 0x2a, 0x00, 0x80, 
+0xc9, 0x6a, 0x51, 0x18, 0x01, 0x64, 0x70, 0x47, 0xa4, 0x2a, 0x00, 0x80, 
 0x00, 0x08, 0x14, 0x40, 0x88, 0xb5, 0x69, 0x46, 0x00, 0xf0, 0x17, 0xf8, 
 0x81, 0x08, 0x0a, 0xd0, 0x00, 0x20, 0x00, 0x29, 0x07, 0xd9, 0x00, 0x22, 
 0x83, 0x00, 0x00, 0x9f, 0xc0, 0x46, 0xfa, 0x50, 0x01, 0x30, 0x88, 0x42, 
 0xf8, 0xd3, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 
-0x04, 0xf8, 0x00, 0x04, 0x00, 0x0c, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x22, 
-0x00, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x0a, 0xd0, 0x02, 0x28, 0x0c, 0xd0, 
-0x03, 0x28, 0x02, 0xd1, 0x07, 0x48, 0x1c, 0x22, 0x08, 0x60, 0x10, 0x1c, 
-0x70, 0x47, 0x06, 0x48, 0x04, 0xe0, 0x06, 0x48, 0x50, 0x22, 0x08, 0x60, 
-0xf7, 0xe7, 0x05, 0x48, 0x68, 0x22, 0x08, 0x60, 0xf3, 0xe7, 0x00, 0x00, 
-0x08, 0x83, 0x20, 0x40, 0x10, 0x2a, 0x00, 0x80, 0x78, 0x2a, 0x00, 0x80, 
-0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x00, 0x27, 0x68, 0x46, 0xfe, 0xf7, 
-0xa7, 0xfb, 0x10, 0x4c, 0x00, 0x28, 0x0b, 0xd0, 0x00, 0xf0, 0x3e, 0xf8, 
-0x00, 0x28, 0x07, 0xd0, 0x01, 0x27, 0x10, 0x23, 0x20, 0x68, 0x18, 0x43, 
-0x20, 0x60, 0x60, 0x68, 0x18, 0x43, 0x0b, 0xe0, 0x10, 0x23, 0xa0, 0x68, 
-0x98, 0x43, 0xa0, 0x60, 0x20, 0x69, 0x98, 0x43, 0x20, 0x61, 0x20, 0x68, 
-0x98, 0x43, 0x20, 0x60, 0x60, 0x68, 0x98, 0x43, 0x60, 0x60, 0x38, 0x1c, 
-0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xe8, 0x18, 0x00, 0x80, 0x00, 0xb5, 0x00, 0xf0, 0xb5, 0xfc, 0xfe, 0xf7, 
-0xc5, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x14, 0x24, 
+0x04, 0xf8, 0x00, 0x04, 0x00, 0x0c, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x22, 0x00, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x0a, 0xd0, 
+0x02, 0x28, 0x0c, 0xd0, 0x03, 0x28, 0x02, 0xd1, 0x07, 0x48, 0x1c, 0x22, 
+0x08, 0x60, 0x10, 0x1c, 0x70, 0x47, 0x06, 0x48, 0x04, 0xe0, 0x06, 0x48, 
+0x50, 0x22, 0x08, 0x60, 0xf7, 0xe7, 0x05, 0x48, 0x68, 0x22, 0x08, 0x60, 
+0xf3, 0xe7, 0x00, 0x00, 0x08, 0x83, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80, 
+0x0c, 0x2b, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x00, 0x27, 
+0x68, 0x46, 0xfe, 0xf7, 0x6f, 0xfb, 0x10, 0x4c, 0x00, 0x28, 0x0b, 0xd0, 
+0x00, 0xf0, 0x44, 0xf8, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x27, 0x10, 0x23, 
+0x60, 0x68, 0x18, 0x43, 0x60, 0x60, 0xa0, 0x68, 0x18, 0x43, 0x0b, 0xe0, 
+0x10, 0x23, 0xe0, 0x68, 0x98, 0x43, 0xe0, 0x60, 0x60, 0x69, 0x98, 0x43, 
+0x60, 0x61, 0x60, 0x68, 0x98, 0x43, 0x60, 0x60, 0xa0, 0x68, 0x98, 0x43, 
+0xa0, 0x60, 0x38, 0x1c, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x19, 0x00, 0x80, 0x00, 0xb5, 0x00, 0xf0, 0xc7, 0xfc, 0x04, 0x49, 
+0x09, 0x6d, 0x08, 0x43, 0xfe, 0xf7, 0x8a, 0xfb, 0x00, 0x20, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x14, 0x24, 
 0x00, 0x25, 0x00, 0x27, 0x08, 0x4e, 0x02, 0x20, 0x21, 0x1c, 0x32, 0x1c, 
-0xfa, 0xf7, 0xec, 0xfe, 0x78, 0x40, 0x07, 0x04, 0x3f, 0x0c, 0x02, 0x34, 
+0xfa, 0xf7, 0xde, 0xfa, 0x78, 0x40, 0x07, 0x04, 0x3f, 0x0c, 0x02, 0x34, 
 0x01, 0x35, 0x03, 0x2d, 0xf3, 0xd3, 0x38, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x39, 0xb7, 0x21, 0x40, 0x90, 0xb5, 0x01, 0x24, 
-0x20, 0x1c, 0x10, 0x49, 0xc9, 0x68, 0x01, 0x29, 0x00, 0xd0, 0x00, 0x20, 
-0x00, 0x06, 0x00, 0x0e, 0x16, 0xd0, 0x0d, 0x4a, 0x3a, 0x21, 0x02, 0x20, 
-0xfa, 0xf7, 0xce, 0xfe, 0x07, 0x04, 0x3f, 0x0c, 0x03, 0xd1, 0x00, 0x20, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0xf7, 0xcf, 0xff, 0xc0, 0x43, 
-0x00, 0x04, 0x00, 0x0c, 0xb8, 0x42, 0x00, 0xd0, 0x00, 0x24, 0x20, 0x06, 
-0x00, 0x0e, 0xf1, 0xe7, 0x20, 0x1c, 0xef, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 
-0x39, 0xb7, 0x21, 0x40, 0xb0, 0xb5, 0x01, 0x27, 0x3a, 0x1c, 0x18, 0x4b, 
-0xdb, 0x68, 0x01, 0x2b, 0x00, 0xd0, 0x00, 0x22, 0x12, 0x06, 0x12, 0x0e, 
-0x00, 0x24, 0x00, 0x2a, 0x23, 0xd0, 0x14, 0x4a, 0x53, 0x68, 0x1b, 0x04, 
-0x1b, 0x0c, 0x1d, 0x02, 0x1b, 0x12, 0x2b, 0x43, 0x92, 0x68, 0x12, 0x04, 
-0x12, 0x0c, 0x15, 0x02, 0x12, 0x12, 0x2a, 0x43, 0x12, 0x04, 0x12, 0x0c, 
-0x1b, 0x04, 0x1a, 0x43, 0x51, 0x40, 0x01, 0x31, 0x0f, 0xd1, 0x00, 0x28, 
-0x02, 0xd0, 0xff, 0xf7, 0x9b, 0xff, 0xc4, 0x43, 0x22, 0x04, 0x12, 0x0c, 
-0x07, 0x4b, 0x3a, 0x21, 0x02, 0x20, 0xfa, 0xf7, 0x8a, 0xfe, 0x38, 0x1c, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x20, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 
-0xe8, 0x0d, 0x00, 0x80, 0x40, 0x00, 0x14, 0x40, 0x7b, 0xb7, 0x21, 0x40, 
-0x80, 0xb4, 0x03, 0x22, 0xc2, 0x80, 0x15, 0x4a, 0xc0, 0x46, 0x82, 0x60, 
-0x14, 0x4a, 0x12, 0x88, 0x01, 0x32, 0xc2, 0x60, 0x00, 0x20, 0x13, 0x4a, 
-0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 
-0xf8, 0xd3, 0x20, 0x22, 0x0a, 0x70, 0x01, 0x31, 0x00, 0x20, 0x0e, 0x4b, 
-0x1f, 0x5c, 0xc0, 0x46, 0x0f, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 
-0xf8, 0xd3, 0x0a, 0x70, 0x01, 0x31, 0x00, 0x20, 0x09, 0x4a, 0x13, 0x5c, 
-0xc0, 0x46, 0x0b, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 
-0x00, 0x20, 0x08, 0x70, 0x80, 0xbc, 0x70, 0x47, 0x17, 0x40, 0x00, 0x02, 
-0xe8, 0x0d, 0x00, 0x80, 0xfc, 0x03, 0x00, 0x80, 0x05, 0x04, 0x00, 0x80, 
-0x0e, 0x04, 0x00, 0x80, 0xf0, 0xb5, 0x01, 0x21, 0x45, 0x4d, 0xe8, 0x1d, 
-0x79, 0x30, 0x41, 0x73, 0x01, 0x73, 0x64, 0x22, 0x42, 0x82, 0x82, 0x82, 
-0xc1, 0x82, 0x7d, 0x21, 0xc9, 0x00, 0x01, 0x83, 0x00, 0x21, 0x41, 0x83, 
-0x3f, 0x48, 0x01, 0x22, 0x00, 0xf0, 0x08, 0xfb, 0x00, 0x26, 0xf6, 0x43, 
-0x3d, 0x4c, 0xe7, 0x1d, 0x39, 0x37, 0xb0, 0x42, 0x07, 0xd1, 0xf8, 0x88, 
-0x01, 0x30, 0xf8, 0x80, 0xa0, 0x79, 0x01, 0x30, 0xa0, 0x71, 0xfc, 0xf7, 
-0xb3, 0xfd, 0x38, 0x48, 0x02, 0x22, 0x00, 0x21, 0x00, 0xf0, 0xf4, 0xfa, 
-0xb0, 0x42, 0x07, 0xd1, 0xf8, 0x88, 0x01, 0x30, 0xf8, 0x80, 0xa0, 0x79, 
-0x01, 0x30, 0xa0, 0x71, 0xfc, 0xf7, 0xa4, 0xfd, 0xe8, 0x68, 0x2f, 0x1c, 
-0x01, 0x28, 0x05, 0xd1, 0x2f, 0x48, 0x7d, 0x22, 0xd2, 0x00, 0x00, 0x21, 
-0x00, 0xf0, 0xe0, 0xfa, 0x2d, 0x4d, 0x28, 0x1c, 0xfa, 0xf7, 0x02, 0xfe, 
-0x2c, 0x48, 0xfa, 0xf7, 0xff, 0xfd, 0x2c, 0x48, 
-0xfa, 0xf7, 0xfc, 0xfd, 0x2b, 0x4e, 0x71, 0x23, 0x5b, 0x01, 0xfc, 0x18, 
-0x2a, 0x4f, 0x20, 0x79, 0x00, 0x28, 0x0f, 0xd0, 0x28, 0x1c, 0xfa, 0xf7, 
-0xf1, 0xfd, 0x38, 0x1c, 0xfa, 0xf7, 0xee, 0xfd, 0x00, 0x28, 0x04, 0xd0, 
-0x38, 0x1c, 0xfa, 0xf7, 0xe9, 0xfd, 0x00, 0x28, 0xfa, 0xd1, 0x30, 0x1c, 
-0xfa, 0xf7, 0xe4, 0xfd, 0x60, 0x79, 0x00, 0x28, 0x23, 0xd0, 0x28, 0x1c, 
-0xfa, 0xf7, 0xde, 0xfd, 0x38, 0x1c, 0xfa, 0xf7, 0xdb, 0xfd, 0x00, 0x28, 
-0x04, 0xd0, 0x38, 0x1c, 0xfa, 0xf7, 0xd6, 0xfd, 0x00, 0x28, 0xfa, 0xd1, 
-0x19, 0x49, 0x01, 0x22, 0x12, 0x04, 0x08, 0x68, 0x02, 0x40, 0x14, 0x20, 
-0x00, 0x2a, 0x05, 0xd1, 0x0a, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 
-0x89, 0x0a, 0x03, 0xd3, 0x13, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x03, 0xe0, 
-0x12, 0x49, 0xc0, 0x46, 0x08, 0x64, 0xff, 0xe7, 0xfe, 0xe7, 0xff, 0xf7, 
-0x1e, 0xfe, 0x10, 0x48, 0xfa, 0xf7, 0xb8, 0xfd, 0x0f, 0x48, 0xfa, 0xf7, 
-0xb5, 0xfd, 0xbc, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 0x5d, 0x22, 0xff, 0xff, 
-0xa0, 0x82, 0x20, 0x40, 0x21, 0x21, 0xff, 0xff, 0x59, 0x7e, 0x21, 0x40, 
-0xf4, 0x01, 0xff, 0xff, 0x09, 0x2c, 0xff, 0xff, 0x04, 0x02, 0xff, 0xff, 
-0x00, 0x00, 0xff, 0xff, 0xb5, 0x07, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40, 
-0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x65, 0xa8, 0x21, 0x40, 
-0x48, 0x57, 0xff, 0xff, 0x00, 0xb5, 0x10, 0x20, 0x0f, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x0f, 0x4a, 0x0f, 0x48, 0x64, 0x21, 0xfa, 0xf7, 0x8e, 0xfd, 
-0x0e, 0x48, 0x01, 0x22, 0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x08, 0x21, 
-0x00, 0x2a, 0x05, 0xd1, 0x02, 0x68, 0x12, 0x0c, 0x07, 0xd1, 0x00, 0x68, 
-0x80, 0x0a, 0x04, 0xd3, 0x08, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x08, 0xbc, 
-0x18, 0x47, 0x07, 0x48, 0xc0, 0x46, 0x01, 0x64, 0xf9, 0xe7, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0x25, 0x55, 0xff, 0xff, 0xf8, 0x28, 0x00, 0x80, 
+0x18, 0x47, 0x00, 0x00, 0x79, 0xbf, 0x21, 0x40, 0x01, 0x20, 0x70, 0x47, 
+0xb0, 0xb5, 0x01, 0x27, 0x3a, 0x1c, 0x18, 0x4b, 0xdb, 0x68, 0x01, 0x2b, 
+0x00, 0xd0, 0x00, 0x22, 0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0x00, 0x2a, 
+0x23, 0xd0, 0x14, 0x4a, 0x53, 0x68, 0x1b, 0x04, 0x1b, 0x0c, 0x1d, 0x02, 
+0x1b, 0x12, 0x2b, 0x43, 0x92, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x15, 0x02, 
+0x12, 0x12, 0x2a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x1b, 0x04, 0x1a, 0x43, 
+0x51, 0x40, 0x01, 0x31, 0x0f, 0xd1, 0x00, 0x28, 0x02, 0xd0, 0xff, 0xf7, 
+0xc1, 0xff, 0xc4, 0x43, 0x22, 0x04, 0x12, 0x0c, 0x07, 0x4b, 0x3a, 0x21, 
+0x02, 0x20, 0xfa, 0xf7, 0xa2, 0xfa, 0x38, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x20, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x40, 0x00, 0x14, 0x40, 0xd9, 0xbf, 0x21, 0x40, 0x80, 0xb4, 0x03, 0x22, 
+0xc2, 0x80, 0x15, 0x4a, 0xc0, 0x46, 0x82, 0x60, 0x14, 0x4a, 0x12, 0x88, 
+0x01, 0x32, 0xc2, 0x60, 0x00, 0x20, 0x13, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 
+0x0b, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x20, 0x22, 
+0x0a, 0x70, 0x01, 0x31, 0x00, 0x20, 0x0e, 0x4b, 0x1f, 0x5c, 0xc0, 0x46, 
+0x0f, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x0a, 0x70, 
+0x01, 0x31, 0x00, 0x20, 0x09, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 
+0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x00, 0x20, 0x08, 0x70, 
+0x80, 0xbc, 0x70, 0x47, 0x02, 0x10, 0x00, 0x03, 0x68, 0x0e, 0x00, 0x80, 
+0x7c, 0x04, 0x00, 0x80, 0x85, 0x04, 0x00, 0x80, 0x8e, 0x04, 0x00, 0x80, 
+0x00, 0xb5, 0x01, 0x23, 0x0a, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x4b, 0x70, 
+0x00, 0x22, 0x0a, 0x70, 0x64, 0x21, 0x80, 0x30, 0xc1, 0x82, 0x01, 0x83, 
+0x43, 0x83, 0x7d, 0x21, 0xc9, 0x00, 0x81, 0x83, 0xc2, 0x83, 0x04, 0x48, 
+0x01, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x38, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0xa1, 0x22, 0xff, 0xff, 
+0x00, 0xb5, 0xff, 0xf7, 0xe1, 0xff, 0x13, 0x48, 0x02, 0x22, 0x00, 0x21, 
+0x00, 0xf0, 0x2a, 0xfb, 0x01, 0x23, 0xd8, 0x42, 0x0a, 0xd1, 0x10, 0x48, 
+0xc1, 0x1d, 0x39, 0x31, 0xca, 0x88, 0x01, 0x32, 0xca, 0x80, 0x81, 0x79, 
+0x01, 0x31, 0x81, 0x71, 0xfc, 0xf7, 0x5c, 0xfd, 0x0b, 0x48, 0xc0, 0x68, 
+0x01, 0x28, 0x05, 0xd1, 0x0a, 0x48, 0x7d, 0x22, 0xd2, 0x00, 0x00, 0x21, 
+0x00, 0xf0, 0x12, 0xfb, 0x08, 0x48, 0xfa, 0xf7, 0x1b, 0xfa, 0x08, 0x48, 
+0x28, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x0a, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
+0x65, 0x21, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0x95, 0x7e, 0x21, 0x40, 0x81, 0x2c, 0xff, 0xff, 0x59, 0x03, 0xff, 0xff, 
+0x00, 0xb5, 0x10, 0x20, 0x0f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4a, 
+0x0f, 0x48, 0x64, 0x21, 0xfa, 0xf7, 0x00, 0xfa, 0x0e, 0x48, 0x01, 0x22, 
+0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x08, 0x21, 0x00, 0x2a, 0x05, 0xd1, 
+0x02, 0x68, 0x12, 0x0c, 0x07, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x04, 0xd3, 
+0x08, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x08, 0xbc, 0x18, 0x47, 0x07, 0x48, 
+0xc0, 0x46, 0x01, 0x64, 0xf9, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x91, 0x55, 0xff, 0xff, 0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
+0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xb5, 0x27, 0x48, 
+0x01, 0x22, 0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x07, 0x21, 0x00, 0x2a, 
+0x05, 0xd1, 0x02, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 
+0x03, 0xd3, 0x21, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x02, 0xe0, 0x20, 0x48, 
+0xc0, 0x46, 0x01, 0x64, 0x1f, 0x48, 0xfa, 0xf7, 0xc1, 0xf9, 0x1f, 0x48, 
+0xc1, 0x6b, 0xff, 0x29, 0xfc, 0xd1, 0x81, 0x6b, 0x42, 0x6b, 0x16, 0x1c, 
+0x0f, 0x1c, 0x1c, 0x4c, 0x10, 0x23, 0x60, 0x69, 0x18, 0x43, 0x60, 0x61, 
+0xa1, 0x69, 0x99, 0x43, 0x1d, 0x04, 0xa1, 0x61, 0xe8, 0x60, 0xa0, 0x69, 
+0xc0, 0x46, 0x28, 0x61, 0x16, 0x4a, 0x17, 0x49, 0x64, 0x20, 0xfa, 0xf7, 
+0xa9, 0xf9, 0x16, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x15, 0x4b, 0x00, 0x20, 
+0x39, 0x1c, 0x32, 0x1c, 0xfa, 0xf7, 0xa8, 0xf9, 0x13, 0x48, 0xc1, 0x68, 
+0x08, 0x29, 0xfc, 0xd1, 0x12, 0x48, 0xfa, 0xf7, 0x97, 0xf9, 0x10, 0x23, 
+0x60, 0x69, 0x98, 0x43, 0x60, 0x61, 0xe8, 0x60, 0x01, 0x20, 0xe3, 0x23, 
+0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x71, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 
+0x04, 0x02, 0xff, 0xff, 0x00, 0x01, 0x18, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0x0c, 0x55, 0xff, 0xff, 0x2d, 0xcf, 0x21, 0x40, 0x64, 0x00, 0x30, 0x02, 
+0x44, 0x80, 0x20, 0x40, 0x40, 0x01, 0x18, 0x40, 0xf4, 0x01, 0xff, 0xff, 
+0x00, 0xb5, 0xfd, 0xf7, 0xeb, 0xfa, 0x06, 0x48, 0xfa, 0xf7, 0x6c, 0xf9, 
+0xfd, 0xf7, 0xc0, 0xfa, 0xfd, 0xf7, 0xee, 0xfb, 0xfd, 0xf7, 0x00, 0xfc, 
+0xfd, 0xf7, 0x0e, 0xfc, 0x08, 0xbc, 0x18, 0x47, 0x91, 0x03, 0xff, 0xff, 
+0x90, 0xb5, 0xfd, 0xf7, 0x55, 0xf8, 0x34, 0x4f, 0x00, 0x24, 0xf9, 0x68, 
+0xf8, 0x1d, 0x79, 0x30, 0x01, 0x29, 0x0f, 0xd1, 0x31, 0x49, 0xc0, 0x46, 
+0xf9, 0x67, 0x31, 0x49, 0xc0, 0x46, 0x01, 0x60, 0x30, 0x49, 0xc0, 0x46, 
+0x0c, 0x60, 0x4c, 0x60, 0x8c, 0x60, 0xcc, 0x60, 0x0c, 0x61, 0x4c, 0x61, 
+0x8c, 0x61, 0x04, 0xe0, 0xf9, 0x1d, 0x7d, 0x31, 0xf9, 0x67, 0x12, 0xc0, 
+0x08, 0x38, 0x00, 0x68, 0x60, 0x23, 0x01, 0x68, 
+0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
+0x01, 0x60, 0xf8, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 
+0x00, 0xf0, 0x54, 0xf8, 0xfd, 0xf7, 0x38, 0xf8, 0x00, 0xf0, 0x08, 0xf9, 
+0xfc, 0xf7, 0x5f, 0xfc, 0xff, 0xf7, 0x84, 0xfd, 0xfd, 0xf7, 0x18, 0xfa, 
+0xfd, 0xf7, 0xa0, 0xf9, 0xfd, 0xf7, 0xac, 0xfa, 0xfd, 0xf7, 0x3e, 0xf9, 
+0xfd, 0xf7, 0xf4, 0xf8, 0xfd, 0xf7, 0x7e, 0xf9, 0x00, 0xf0, 0xc4, 0xf9, 
+0xfd, 0xf7, 0x86, 0xfb, 0xfd, 0xf7, 0xf4, 0xfa, 0xfd, 0xf7, 0xbc, 0xfa, 
+0xfd, 0xf7, 0x26, 0xf8, 0xfa, 0xf7, 0x12, 0xf8, 0xff, 0xf7, 0x40, 0xfd, 
+0x00, 0x20, 0xff, 0xf7, 0x17, 0xfe, 0xff, 0xf7, 0x97, 0xff, 0x71, 0x23, 
+0x5b, 0x01, 0xf8, 0x18, 0x04, 0x72, 0x44, 0x72, 0x07, 0x23, 0x5b, 0x02, 
+0xf8, 0x18, 0x04, 0x63, 0x09, 0x48, 0xc0, 0x46, 0x44, 0x62, 0x00, 0xf0, 
+0xc3, 0xf9, 0x08, 0x48, 0xfa, 0xf7, 0xf8, 0xf8, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x11, 0x40, 
+0x04, 0x01, 0x11, 0x40, 0x00, 0x01, 0x11, 0x00, 0xc0, 0x00, 0x18, 0x00, 
+0x65, 0x9f, 0x21, 0x40, 0x00, 0xb5, 0x04, 0x48, 0xfa, 0xf7, 0xe4, 0xf8, 
+0xfd, 0xf7, 0x48, 0xfb, 0xfd, 0xf7, 0x0e, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
+0x61, 0xa9, 0x21, 0x40, 0xfa, 0x21, 0x03, 0x48, 0xc0, 0x46, 0x41, 0x62, 
+0x40, 0x21, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 
+0x07, 0x48, 0x41, 0x69, 0x07, 0x4b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 
+0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x80, 0x69, 
+0xc0, 0x46, 0x10, 0x61, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0xfe, 0xaf, 0x9a, 0x10, 0x00, 0xb5, 0x02, 0x48, 0xfa, 0xf7, 0xba, 0xf8, 
+0x08, 0xbc, 0x18, 0x47, 0xb4, 0x57, 0xff, 0xff, 0xf0, 0xb5, 0x24, 0x4c, 
+0x01, 0x21, 0x09, 0x04, 0x20, 0x68, 0x01, 0x40, 0x09, 0x20, 0x22, 0x4e, 
+0x22, 0x4d, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1, 
+0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 0x00, 0xe0, 0x28, 0x64, 
+0x1d, 0x48, 0xfa, 0xf7, 0x9f, 0xf8, 0x1d, 0x4f, 0x1d, 0x49, 0x88, 0x69, 
+0x01, 0x30, 0x88, 0x61, 0x38, 0x7a, 0x00, 0x28, 0x02, 0xd1, 0x78, 0x7a, 
+0x00, 0x28, 0x1f, 0xd0, 0x19, 0x48, 0xfa, 0xf7, 0x91, 0xf8, 0x19, 0x48, 
+0xfa, 0xf7, 0x8e, 0xf8, 0x00, 0x28, 0xfa, 0xd1, 0x38, 0x7a, 0x00, 0x28, 
+0x02, 0xd0, 0x16, 0x48, 0xfa, 0xf7, 0x86, 0xf8, 0x01, 0x21, 0x09, 0x04, 
+0x20, 0x68, 0x01, 0x40, 0x14, 0x20, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 
+0x09, 0x0c, 0x04, 0xd1, 0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 
+0x01, 0xe0, 0x28, 0x64, 0xff, 0xe7, 0xfe, 0xe7, 0xff, 0xf7, 0xdd, 0xfc, 
+0x0b, 0x48, 0xfa, 0xf7, 0x6f, 0xf8, 0xff, 0xf7, 0xaf, 0xff, 0xcd, 0xe7, 
 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 
-0xb0, 0xb5, 0x24, 0x4f, 0x01, 0x21, 0x09, 0x04, 0x38, 0x68, 0x01, 0x40, 
-0x06, 0x20, 0x22, 0x4d, 0x22, 0x4c, 0x00, 0x29, 0x05, 0xd1, 0x39, 0x68, 
-0x09, 0x0c, 0x04, 0xd1, 0x39, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xe8, 0x60, 
-0x00, 0xe0, 0x20, 0x64, 0x03, 0x20, 0xfe, 0xf7, 0xc5, 0xfa, 0xfb, 0xf7, 
-0xa1, 0xf9, 0x01, 0x23, 0x18, 0x43, 0xfb, 0xf7, 0x6b, 0xfa, 0x00, 0xf0, 
-0x31, 0xf8, 0x01, 0x21, 0x09, 0x04, 0x38, 0x68, 0x01, 0x40, 0x07, 0x20, 
-0x00, 0x29, 0x05, 0xd1, 0x39, 0x68, 0x09, 0x0c, 0x04, 0xd1, 0x39, 0x68, 
-0x89, 0x0a, 0x01, 0xd3, 0xe8, 0x60, 0x00, 0xe0, 0x20, 0x64, 0x00, 0xf0, 
-0x89, 0xf8, 0x00, 0xf0, 0x69, 0xf8, 0x00, 0xf0, 0xd3, 0xf8, 0x01, 0x21, 
-0x09, 0x04, 0x38, 0x68, 0x01, 0x40, 0x09, 0x20, 0x00, 0x29, 0x05, 0xd1, 
-0x39, 0x68, 0x09, 0x0c, 0x04, 0xd1, 0x39, 0x68, 0x89, 0x0a, 0x01, 0xd3, 
-0xe8, 0x60, 0x00, 0xe0, 0x20, 0x64, 0xff, 0xf7, 0xdf, 0xfe, 0xb0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 
-0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x21, 0x48, 0xfa, 0xf7, 0x14, 0xfd, 
-0xfd, 0xf7, 0x4a, 0xf8, 0x00, 0xf0, 0xa6, 0xf8, 0xfd, 0xf7, 0x58, 0xf8, 
-0x00, 0xf0, 0xc0, 0xf8, 0xfc, 0xf7, 0x9f, 0xfc, 0xff, 0xf7, 0x5c, 0xfd, 
-0xfd, 0xf7, 0x3c, 0xfa, 0xfd, 0xf7, 0xc4, 0xf9, 0xfd, 0xf7, 0xdc, 0xfa, 
-0xfd, 0xf7, 0x60, 0xf9, 0xfd, 0xf7, 0x1a, 0xf9, 
-0xfd, 0xf7, 0xa2, 0xf9, 0x00, 0xf0, 0x8a, 0xf9, 0xfd, 0xf7, 0xb6, 0xfb, 
-0xfd, 0xf7, 0x24, 0xfb, 0xfd, 0xf7, 0xec, 0xfa, 0xfd, 0xf7, 0x46, 0xf8, 
-0xfa, 0xf7, 0xf2, 0xfb, 0xff, 0xf7, 0x18, 0xfd, 0x00, 0x20, 0xff, 0xf7, 
-0xef, 0xfd, 0x00, 0xf0, 0x29, 0xf8, 0x00, 0x20, 0x0a, 0x49, 0x71, 0x23, 
-0x5b, 0x01, 0xca, 0x18, 0x10, 0x71, 0x50, 0x71, 0x07, 0x23, 0x5b, 0x02, 
-0xc9, 0x18, 0xc8, 0x62, 0x06, 0x49, 0xc0, 0x46, 0x48, 0x62, 0x00, 0xf0, 
-0x87, 0xf9, 0x05, 0x48, 0xfa, 0xf7, 0xd6, 0xfc, 0x08, 0xbc, 0x18, 0x47, 
-0xff, 0xb8, 0x21, 0x40, 0xe8, 0x0d, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x00, 
-0x31, 0x98, 0x21, 0x40, 0x00, 0xb5, 0x04, 0x48, 0xfa, 0xf7, 0xc8, 0xfc, 
-0xfd, 0xf7, 0x7c, 0xfb, 0xfd, 0xf7, 0x34, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
-0x11, 0xa2, 0x21, 0x40, 0x00, 0xb5, 0xfd, 0xf7, 0x81, 0xfa, 0x06, 0x48, 
-0xfa, 0xf7, 0xba, 0xfc, 0xfd, 0xf7, 0x56, 0xfa, 0xfd, 0xf7, 0x8c, 0xfb, 
-0xfd, 0xf7, 0x9e, 0xfb, 0xfd, 0xf7, 0xac, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
-0x91, 0x03, 0xff, 0xff, 0xf8, 0xb5, 0x1a, 0x48, 0xc1, 0x6b, 0xff, 0x29, 
-0xfc, 0xd1, 0x81, 0x6b, 0x42, 0x6b, 0x0d, 0x1c, 0x16, 0x1c, 0x17, 0x4c, 
-0x10, 0x23, 0x60, 0x69, 0x18, 0x43, 0x60, 0x61, 0xa1, 0x69, 0x99, 0x43, 
-0x1f, 0x04, 0xa1, 0x61, 0xf8, 0x60, 0xa0, 0x69, 0xc0, 0x46, 0x38, 0x61, 
-0x11, 0x4a, 0x12, 0x49, 0x64, 0x20, 0xfa, 0xf7, 0x95, 0xfc, 0x11, 0x4a, 
-0xc0, 0x46, 0x00, 0x92, 0x10, 0x4b, 0x00, 0x20, 0x29, 0x1c, 0x32, 0x1c, 
-0xfa, 0xf7, 0x94, 0xfc, 0x0e, 0x48, 0xc1, 0x68, 0x08, 0x29, 0xfc, 0xd1, 
-0x10, 0x23, 0x60, 0x69, 0x98, 0x43, 0x60, 0x61, 0xf8, 0x60, 0x01, 0x20, 
-0xe3, 0x23, 0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x70, 0xf8, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x00, 0x01, 0x18, 0x40, 0xe8, 0x0d, 0x00, 0x80, 
-0xa0, 0x54, 0xff, 0xff, 0x11, 0xc8, 0x21, 0x40, 0x64, 0x00, 0x30, 0x02, 
-0x44, 0x80, 0x20, 0x40, 0x40, 0x01, 0x18, 0x40, 0xfa, 0x21, 0x03, 0x48, 
-0xc0, 0x46, 0x41, 0x62, 0x40, 0x21, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 
-0xc0, 0x00, 0x18, 0x00, 0x07, 0x48, 0x41, 0x69, 0x07, 0x4b, 0x19, 0x43, 
-0x41, 0x61, 0x82, 0x69, 0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 
-0xd1, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x10, 0x61, 0x70, 0x47, 0x00, 0x00, 
-0xe8, 0x0d, 0x00, 0x80, 0xfe, 0xaf, 0x9a, 0x10, 0xf0, 0xb4, 0x4b, 0x4a, 
-0x4b, 0x48, 0x00, 0x68, 0x00, 0x0c, 0x4b, 0x4d, 0x4b, 0x4b, 0x98, 0x42, 
-0x02, 0xd0, 0x01, 0x33, 0x98, 0x42, 0x01, 0xd1, 0x01, 0x20, 0x28, 0x80, 
-0x01, 0x21, 0xc9, 0x03, 0x19, 0x23, 0xdb, 0x01, 0xec, 0x18, 0x61, 0x61, 
-0x28, 0x88, 0x40, 0x04, 0x44, 0x4b, 0xc0, 0x18, 0x87, 0x1a, 0x06, 0x20, 
-0xaf, 0x60, 0x43, 0x4e, 0xc0, 0x46, 0xb0, 0x61, 0x20, 0x20, 0xc8, 0x23, 
-0x43, 0x43, 0xbb, 0x42, 0x21, 0xd9, 0x41, 0x00, 0x3e, 0x4e, 0xc0, 0x46, 
-0x31, 0x61, 0xb6, 0x69, 0x20, 0x23, 0x9b, 0x1b, 0x3b, 0x4e, 0xc0, 0x46, 
-0xf3, 0x61, 0x10, 0x3b, 0x33, 0x62, 0x8b, 0x00, 0xff, 0x1a, 0x40, 0x08, 
-0x81, 0x42, 0x17, 0xd3, 0xb8, 0x23, 0x43, 0x43, 0xbb, 0x42, 0x08, 0xd9, 
-0x41, 0x1e, 0x34, 0x4b, 0xc0, 0x46, 0x99, 0x81, 0xd9, 0x81, 0x40, 0x00, 
-0x02, 0x38, 0x58, 0x61, 0x0a, 0xe0, 0x01, 0x30, 0x81, 0x42, 0xef, 0xd2, 
-0x06, 0xe0, 0x2e, 0x4e, 0xb3, 0x69, 0x01, 0x33, 0xb3, 0x61, 0x40, 0x00, 
-0x88, 0x42, 0xd2, 0xd9, 0x2b, 0x49, 0x00, 0x20, 
-0x63, 0x69, 0x9b, 0x08, 0x07, 0xd0, 0x2a, 0x4b, 0x87, 0x00, 0xcb, 0x51, 
-0x67, 0x69, 0xbf, 0x08, 0x01, 0x30, 0x87, 0x42, 0xf8, 0xd8, 0x24, 0x49, 
-0xc0, 0x46, 0x8a, 0x62, 0x8c, 0x89, 0x58, 0x20, 0x60, 0x43, 0x87, 0x18, 
-0x00, 0x20, 0x00, 0x22, 0x00, 0x2c, 0x0a, 0xdd, 0x58, 0x23, 0x43, 0x43, 
-0x8c, 0x6a, 0xe3, 0x18, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x9a, 0x60, 
-0x8b, 0x89, 0x83, 0x42, 0xf4, 0xdc, 0xcf, 0x62, 0xcc, 0x89, 0x60, 0x00, 
-0x00, 0x19, 0x40, 0x01, 0xc7, 0x19, 0x00, 0x20, 0x00, 0x2c, 0x0b, 0xdd, 
-0x43, 0x00, 0x1b, 0x18, 0x5b, 0x01, 0xcc, 0x6a, 0xe3, 0x18, 0x01, 0x30, 
-0x00, 0x04, 0x00, 0x0c, 0x9a, 0x60, 0xcb, 0x89, 0x83, 0x42, 0xf3, 0xdc, 
-0x4f, 0x62, 0x00, 0x20, 0x0b, 0x69, 0x00, 0x2b, 0x07, 0xd9, 0x87, 0x00, 
-0x4b, 0x6a, 0xc0, 0x46, 0xda, 0x51, 0x0b, 0x69, 0x01, 0x30, 0x83, 0x42, 
-0xf7, 0xd8, 0x49, 0x6a, 0x80, 0x00, 0x08, 0x18, 0x04, 0x38, 0x28, 0x61, 
-0xf0, 0xbc, 0x70, 0x47, 0xb8, 0xce, 0x21, 0x40, 0x00, 0x00, 0x18, 0x40, 
-0xe8, 0x0d, 0x00, 0x80, 0x02, 0x99, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 
-0xc8, 0x29, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0xad, 0xde, 0x00, 
+0x04, 0x02, 0xff, 0xff, 0x88, 0x1c, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40, 
+0xf4, 0x01, 0xff, 0xff, 0xb5, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 
+0xe9, 0xaf, 0x21, 0x40, 0x00, 0xb5, 0x16, 0x49, 0x01, 0x22, 0x12, 0x04, 
+0x08, 0x68, 0x02, 0x40, 0x06, 0x20, 0x00, 0x2a, 0x05, 0xd1, 0x0a, 0x68, 
+0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x10, 0x49, 
+0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x0f, 0x49, 0xc0, 0x46, 0x08, 0x64, 
+0x03, 0x20, 0xfe, 0xf7, 0x55, 0xf9, 0xfa, 0xf7, 
+0x9d, 0xfc, 0x01, 0x23, 0x18, 0x43, 0xfa, 0xf7, 0x77, 0xfd, 0xff, 0xf7, 
+0xd7, 0xfe, 0xff, 0xf7, 0x5b, 0xfe, 0xff, 0xf7, 0x4b, 0xff, 0xff, 0xf7, 
+0x5f, 0xff, 0xff, 0xf7, 0xf1, 0xfd, 0xff, 0xf7, 0x77, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 
+0x00, 0x00, 0x00, 0x80, 0xf0, 0xb4, 0x46, 0x4a, 0x01, 0x21, 0xc9, 0x03, 
+0x45, 0x4d, 0x19, 0x23, 0xdb, 0x01, 0xec, 0x18, 0xa1, 0x61, 0x28, 0x88, 
+0x40, 0x04, 0x43, 0x4b, 0xc0, 0x18, 0x87, 0x1a, 0x04, 0x20, 0xaf, 0x60, 
+0x41, 0x4e, 0xc0, 0x46, 0xb0, 0x61, 0x08, 0x20, 0xc8, 0x23, 0x43, 0x43, 
+0xbb, 0x42, 0x21, 0xd9, 0x41, 0x00, 0x3d, 0x4e, 0xc0, 0x46, 0x31, 0x61, 
+0xb6, 0x69, 0x20, 0x23, 0x9b, 0x1b, 0x3a, 0x4e, 0xc0, 0x46, 0xf3, 0x61, 
+0x10, 0x3b, 0x33, 0x62, 0x8b, 0x00, 0xff, 0x1a, 0x40, 0x08, 0x81, 0x42, 
+0x17, 0xd3, 0xb8, 0x23, 0x43, 0x43, 0xbb, 0x42, 0x08, 0xd9, 0x41, 0x1e, 
+0x32, 0x4b, 0xc0, 0x46, 0x99, 0x81, 0xd9, 0x81, 0x40, 0x00, 0x02, 0x38, 
+0x58, 0x61, 0x0a, 0xe0, 0x01, 0x30, 0x81, 0x42, 0xef, 0xd2, 0x06, 0xe0, 
+0x2c, 0x4e, 0xb3, 0x69, 0x01, 0x33, 0xb3, 0x61, 0x40, 0x00, 0x88, 0x42, 
+0xd2, 0xd9, 0x2a, 0x49, 0x00, 0x20, 0xa3, 0x69, 0x9b, 0x08, 0x07, 0xd0, 
+0x28, 0x4b, 0x87, 0x00, 0xcb, 0x51, 0xa7, 0x69, 0xbf, 0x08, 0x01, 0x30, 
+0x87, 0x42, 0xf8, 0xd8, 0x22, 0x49, 0xc0, 0x46, 0x8a, 0x62, 0x8c, 0x89, 
+0x58, 0x20, 0x60, 0x43, 0x87, 0x18, 0x00, 0x20, 0x00, 0x22, 0x00, 0x2c, 
+0x0a, 0xdd, 0x58, 0x23, 0x43, 0x43, 0x8c, 0x6a, 0xe3, 0x18, 0x01, 0x30, 
+0x00, 0x04, 0x00, 0x0c, 0x9a, 0x60, 0x8b, 0x89, 0x83, 0x42, 0xf4, 0xdc, 
+0xcf, 0x62, 0xcc, 0x89, 0x60, 0x00, 0x00, 0x19, 0x40, 0x01, 0xc7, 0x19, 
+0x00, 0x20, 0x00, 0x2c, 0x0b, 0xdd, 0x43, 0x00, 0x1b, 0x18, 0x5b, 0x01, 
+0xcc, 0x6a, 0xe3, 0x18, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x9a, 0x60, 
+0xcb, 0x89, 0x83, 0x42, 0xf3, 0xdc, 0x4f, 0x62, 0x00, 0x20, 0x0b, 0x69, 
+0x00, 0x2b, 0x07, 0xd9, 0x87, 0x00, 0x4b, 0x6a, 0xc0, 0x46, 0xda, 0x51, 
+0x0b, 0x69, 0x01, 0x30, 0x83, 0x42, 0xf7, 0xd8, 0x49, 0x6a, 0x80, 0x00, 
+0x08, 0x18, 0x04, 0x38, 0x28, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0xec, 0xd6, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0xad, 0xde, 0x00, 
 0x0a, 0x48, 0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 0x1a, 0x09, 
 0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x91, 0x61, 
-0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x61, 0x01, 0x20, 0x00, 0x06, 
-0x59, 0x05, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
+0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x81, 0x61, 0x01, 0x20, 0x00, 0x06, 
+0x59, 0x05, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
 0x80, 0xb4, 0x02, 0x1c, 0x0b, 0x48, 0x1b, 0x23, 0xdb, 0x01, 0xc3, 0x18, 
-0x5a, 0x61, 0x01, 0x23, 0x1b, 0x06, 0x42, 0x69, 0x1a, 0x43, 0x42, 0x61, 
+0x9a, 0x61, 0x01, 0x23, 0x1b, 0x06, 0x42, 0x69, 0x1a, 0x43, 0x42, 0x61, 
 0x87, 0x69, 0x9f, 0x43, 0x01, 0x23, 0x1b, 0x05, 0x87, 0x61, 0xda, 0x60, 
 0x80, 0x69, 0xc0, 0x46, 0x18, 0x61, 0xa1, 0x20, 0x40, 0x03, 0x81, 0x61, 
-0x80, 0xbc, 0x70, 0x47, 0xe8, 0x0d, 0x00, 0x80, 0x80, 0xb5, 0xff, 0xf7, 
+0x80, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0xff, 0xf7, 
 0xc9, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0x20, 0x09, 0x49, 
 0x00, 0x22, 0x03, 0x01, 0x5f, 0x18, 0x33, 0x23, 0x9b, 0x01, 0xfb, 0x18, 
-0x5a, 0x62, 0x01, 0x30, 0x0b, 0x28, 0xf6, 0xd3, 0x04, 0x48, 0x01, 0x22, 
-0x00, 0x21, 0x00, 0xf0, 0x33, 0xf8, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xe8, 0x0d, 0x00, 0x80, 0x91, 0x3d, 0xff, 0xff, 0x00, 0xb5, 0x02, 0x48, 
-0x00, 0xf0, 0x04, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0xa8, 0x61, 0x00, 0x00, 
-0x80, 0xb4, 0x01, 0x22, 0x12, 0x05, 0x0f, 0x4b, 0xa1, 0x21, 0x49, 0x03, 
-0x00, 0x28, 0x0e, 0xd0, 0xc8, 0x61, 0x18, 0x1c, 0x59, 0x69, 0x53, 0x01, 
-0x19, 0x43, 0x41, 0x61, 0x87, 0x69, 0x9f, 0x43, 0x87, 0x61, 0xd1, 0x60, 
-0x80, 0x69, 0xc0, 0x46, 0x10, 0x61, 0x80, 0xbc, 0x70, 0x47, 0x18, 0x1c, 
-0x5f, 0x69, 0x01, 0x23, 0x5b, 0x06, 0x9f, 0x43, 0x47, 0x61, 0xd7, 0x60, 
-0x00, 0x20, 0xc8, 0x61, 0xf3, 0xe7, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
-0xb0, 0xb4, 0x07, 0x1c, 0x00, 0x20, 0x17, 0x4c, 0x03, 0x01, 0x1d, 0x19, 
-0x33, 0x23, 0x9b, 0x01, 0xeb, 0x18, 0x5d, 0x6a, 0xbd, 0x42, 0x05, 0xd1, 
-0xdd, 0x6a, 0x95, 0x42, 0x02, 0xd1, 0x9b, 0x6a, 0x8b, 0x42, 0x1c, 0xd0, 
-0x01, 0x30, 0x0b, 0x28, 0xee, 0xd3, 0x00, 0x20, 0x03, 0x01, 0x1d, 0x19, 
-0x33, 0x23, 0x9b, 0x01, 0xeb, 0x18, 0x5b, 0x6a, 0x00, 0x2b, 0x09, 0xd1, 
-0x03, 0x01, 0x1c, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xe3, 0x18, 0xda, 0x62, 
-0x99, 0x62, 0x1a, 0x63, 0x5f, 0x62, 0x02, 0xe0, 
+0x9a, 0x62, 0x01, 0x30, 0x0b, 0x28, 0xf6, 0xd3, 0x04, 0x48, 0x01, 0x22, 
+0x00, 0x21, 0x00, 0xf0, 0x33, 0xf8, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x09, 0x3e, 0xff, 0xff, 
+0x00, 0xb5, 0x02, 0x48, 0x00, 0xf0, 0x04, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
+0xa8, 0x61, 0x00, 0x00, 0x80, 0xb4, 0x01, 0x22, 0x12, 0x05, 0x0f, 0x4b, 
+0xa1, 0x21, 0x49, 0x03, 0x00, 0x28, 0x0e, 0xd0, 0xc8, 0x61, 0x18, 0x1c, 
+0x59, 0x69, 0x53, 0x01, 0x19, 0x43, 0x41, 0x61, 0x87, 0x69, 0x9f, 0x43, 
+0x87, 0x61, 0xd1, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x10, 0x61, 0x80, 0xbc, 
+0x70, 0x47, 0x18, 0x1c, 0x5f, 0x69, 0x01, 0x23, 0x5b, 0x06, 0x9f, 0x43, 
+0x47, 0x61, 0xd7, 0x60, 0x00, 0x20, 0xc8, 0x61, 0xf3, 0xe7, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb4, 0x07, 0x1c, 0x00, 0x20, 0x17, 0x4c, 
+0x03, 0x01, 0x1d, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xeb, 0x18, 0x9d, 0x6a, 
+0xbd, 0x42, 0x05, 0xd1, 0x1d, 0x6b, 0x95, 0x42, 0x02, 0xd1, 0xdb, 0x6a, 
+0x8b, 0x42, 0x1c, 0xd0, 0x01, 0x30, 0x0b, 0x28, 0xee, 0xd3, 0x00, 0x20, 
+0x03, 0x01, 0x1d, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xeb, 0x18, 0x9b, 0x6a, 
+0x00, 0x2b, 0x09, 0xd1, 0x03, 0x01, 0x1c, 0x19, 0x33, 0x23, 0x9b, 0x01, 
+0xe3, 0x18, 0x1a, 0x63, 0xd9, 0x62, 0x5a, 0x63, 0x9f, 0x62, 0x02, 0xe0, 
 0x01, 0x30, 0x0b, 0x28, 0xea, 0xd3, 0x0b, 0x28, 0x01, 0xd1, 0x00, 0x20, 
-0xc0, 0x43, 0xb0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x00, 0x80, 
+0xc0, 0x43, 0xb0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
 0x90, 0xb4, 0x01, 0x1c, 0x00, 0x22, 0x01, 0x20, 0x16, 0x4f, 0x01, 0xe0, 
 0x00, 0x2a, 0x07, 0xd1, 0x03, 0x01, 0xdc, 0x19, 0x33, 0x23, 0x9b, 0x01, 
-0xe3, 0x18, 0x5b, 0x69, 0x8b, 0x42, 0x11, 0xd1, 0x02, 0x01, 0xd2, 0x19, 
-0x33, 0x23, 0x9b, 0x01, 0xd2, 0x18, 0x53, 0x6a, 0xc0, 0x46, 0x53, 0x61, 
-0x93, 0x6a, 0xc0, 0x46, 0x93, 0x61, 0xd3, 0x6a, 0xc0, 0x46, 0xd3, 0x61, 
-0x13, 0x6b, 0xc0, 0x46, 0x13, 0x62, 0x01, 0x22, 0x01, 0x30, 0x0b, 0x28, 
-0xe0, 0xd3, 0x07, 0x4b, 0x00, 0x2a, 0x02, 0xd1, 0x5a, 0x68, 0x8a, 0x42, 
-0x03, 0xd1, 0x00, 0x21, 0x59, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 
-0xc0, 0x43, 0xfa, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 0x68, 0x1b, 0x00, 0x80, 
+0xe3, 0x18, 0x9b, 0x69, 0x8b, 0x42, 0x11, 0xd1, 0x02, 0x01, 0xd2, 0x19, 
+0x33, 0x23, 0x9b, 0x01, 0xd2, 0x18, 0x93, 0x6a, 0xc0, 0x46, 0x93, 0x61, 
+0xd3, 0x6a, 0xc0, 0x46, 0xd3, 0x61, 0x13, 0x6b, 0xc0, 0x46, 0x13, 0x62, 
+0x53, 0x6b, 0xc0, 0x46, 0x53, 0x62, 0x01, 0x22, 0x01, 0x30, 0x0b, 0x28, 
+0xe0, 0xd3, 0x07, 0x4b, 0x00, 0x2a, 0x02, 0xd1, 0x9a, 0x68, 0x8a, 0x42, 
+0x03, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 
+0xc0, 0x43, 0xfa, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0xe8, 0x1b, 0x00, 0x80, 
 0x0b, 0x28, 0x17, 0xda, 0x0c, 0x49, 0x01, 0x23, 0x5b, 0x06, 0x8a, 0x69, 
 0x13, 0x43, 0x01, 0x22, 0x12, 0x05, 0x8b, 0x61, 0x13, 0x61, 0x00, 0x01, 
-0x40, 0x18, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0xc3, 0x6a, 0xc0, 0x46, 
-0x03, 0x63, 0x53, 0x01, 0x88, 0x69, 0x98, 0x43, 0x88, 0x61, 0x10, 0x61, 
-0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7, 0xe8, 0x0d, 0x00, 0x80, 
+0x40, 0x18, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x03, 0x6b, 0xc0, 0x46, 
+0x43, 0x63, 0x53, 0x01, 0x88, 0x69, 0x98, 0x43, 0x88, 0x61, 0x10, 0x61, 
+0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7, 0x68, 0x0e, 0x00, 0x80, 
 0x90, 0xb4, 0x08, 0x4a, 0xd0, 0x69, 0x00, 0x21, 0x07, 0x4f, 0xd3, 0x69, 
 0x83, 0x42, 0x02, 0xd9, 0xfc, 0x1a, 0x20, 0x18, 0x00, 0xe0, 0xc0, 0x1a, 
 0x09, 0x18, 0x18, 0x1c, 0xb9, 0x42, 0xf4, 0xd9, 0x90, 0xbc, 0x70, 0x47, 
@@ -4100,9 +4288,9 @@ const u8 typhoon_firmware_image[] = {
 0x08, 0xc9, 0x08, 0xc0, 0x12, 0x1f, 0xfb, 0xd2, 0x0a, 0xe0, 0x08, 0xc9, 
 0x03, 0x70, 0x1b, 0x0a, 0x43, 0x70, 0x1b, 0x0a, 0x83, 0x70, 0x1b, 0x0a, 
 0xc3, 0x70, 0x00, 0x1d, 0x12, 0x1f, 0xf4, 0xd2, 0xd2, 0x1c, 0x05, 0xd3, 
-0x0b, 0x78, 0x03, 0x70, 0x49, 0x1c, 0x40, 0x1c, 0x52, 0x1e, 0xf9, 0xd2, 
-0x60, 0x46, 0x70, 0x47, 0x03, 0x1c, 0x0b, 0x43, 0x13, 0x43, 0x9b, 0x07, 
-0x04, 0xd1, 0x12, 0x1f, 0x8b, 0x58, 0x83, 0x50, 0xfb, 0xd1, 0x70, 0x47, 
-0x52, 0x1e, 0x8b, 0x5c, 0x83, 0x54, 0xfb, 0xd1, 0x70, 0x47, 0x00, 0x00, 
-0x00, 0x20, 0x70, 0x47, 
+0x0b, 0x78, 0x03, 0x70, 0x49, 0x1c, 0x40, 0x1c, 
+0x52, 0x1e, 0xf9, 0xd2, 0x60, 0x46, 0x70, 0x47, 0x03, 0x1c, 0x0b, 0x43, 
+0x13, 0x43, 0x9b, 0x07, 0x04, 0xd1, 0x12, 0x1f, 0x8b, 0x58, 0x83, 0x50, 
+0xfb, 0xd1, 0x70, 0x47, 0x52, 0x1e, 0x8b, 0x5c, 0x83, 0x54, 0xfb, 0xd1, 
+0x70, 0x47, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47, 
 };
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/typhoon.c linux-2.4.26-pre6/drivers/net/typhoon.c
--- linux-2.4.25/drivers/net/typhoon.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/typhoon.c	2004-03-25 00:21:20.000000000 +0000
@@ -85,8 +85,8 @@ static const int multicast_filter_limit 
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.4.2"
-#define DRV_MODULE_RELDATE	"03/11/25"
+#define DRV_MODULE_VERSION 	"1.4.3"
+#define DRV_MODULE_RELDATE	"03/12/15"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -157,6 +157,7 @@ enum typhoon_cards {
 	TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR,
 	TYPHOON_SVR95, TYPHOON_SVR97, TYPHOON_TXM, TYPHOON_BSVR,
 	TYPHOON_FX95, TYPHOON_FX97, TYPHOON_FX95SVR, TYPHOON_FX97SVR,
+	TYPHOON_FXM,
 };
 
 /* directly indexed by enum typhoon_cards, above */
@@ -185,6 +186,8 @@ static struct typhoon_card_info typhoon_
 	 	TYPHOON_CRYPTO_DES | TYPHOON_FIBER},
 	{ "3Com Typhoon (3CR990-FX-97 Server)",
 	 	TYPHOON_CRYPTO_DES | TYPHOON_CRYPTO_3DES | TYPHOON_FIBER},
+	{ "3Com Typhoon2 (3C990B-FX-97)",
+		TYPHOON_CRYPTO_VARIABLE | TYPHOON_FIBER},
 };
 
 /* Notes on the new subsystem numbering scheme:
@@ -203,6 +206,8 @@ static struct pci_device_id typhoon_pci_
 	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990B,
 	  PCI_ANY_ID, 0x1000, 0, 0, TYPHOON_TXM },
 	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990B,
+	  PCI_ANY_ID, 0x1102, 0, 0, TYPHOON_FXM },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990B,
 	  PCI_ANY_ID, 0x2000, 0, 0, TYPHOON_BSVR },
 	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_FX,
 	  PCI_ANY_ID, 0x1101, 0, 0, TYPHOON_FX95 },
@@ -1363,6 +1368,7 @@ typhoon_download_firmware(struct typhoon
 	u32 section_len;
 	u32 len;
 	u32 load_addr;
+	u32 hmac;
 	int i;
 	int err;
 
@@ -1406,6 +1412,16 @@ typhoon_download_firmware(struct typhoon
 
 	writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
 	writel(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
+	hmac = le32_to_cpu(fHdr->hmacDigest[0]);
+	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
+	hmac = le32_to_cpu(fHdr->hmacDigest[1]);
+	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
+	hmac = le32_to_cpu(fHdr->hmacDigest[2]);
+	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
+	hmac = le32_to_cpu(fHdr->hmacDigest[3]);
+	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
+	hmac = le32_to_cpu(fHdr->hmacDigest[4]);
+	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
 	typhoon_post_pci_writes(ioaddr);
 	writel(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/typhoon.h linux-2.4.26-pre6/drivers/net/typhoon.h
--- linux-2.4.25/drivers/net/typhoon.h	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/typhoon.h	2004-03-25 00:21:30.000000000 +0000
@@ -512,6 +512,7 @@ struct typhoon_file_header {
 	u32 version;
 	u32 numSections;
 	u32 startAddr;
+	u32 hmacDigest[5];
 } __attribute__ ((packed));
 
 struct typhoon_section_header {
@@ -548,6 +549,11 @@ struct typhoon_section_header {
 #define TYPHOON_REG_BOOT_LENGTH			TYPHOON_REG_HOST2ARM1
 
 #define TYPHOON_REG_DOWNLOAD_BOOT_ADDR		TYPHOON_REG_HOST2ARM1
+#define TYPHOON_REG_DOWNLOAD_HMAC_0		TYPHOON_REG_HOST2ARM2
+#define TYPHOON_REG_DOWNLOAD_HMAC_1		TYPHOON_REG_HOST2ARM3
+#define TYPHOON_REG_DOWNLOAD_HMAC_2		TYPHOON_REG_HOST2ARM4
+#define TYPHOON_REG_DOWNLOAD_HMAC_3		TYPHOON_REG_HOST2ARM5
+#define TYPHOON_REG_DOWNLOAD_HMAC_4		TYPHOON_REG_HOST2ARM6
 
 #define TYPHOON_REG_BOOT_RECORD_ADDR_HI		TYPHOON_REG_HOST2ARM2
 #define TYPHOON_REG_BOOT_RECORD_ADDR_LO		TYPHOON_REG_HOST2ARM1
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/wireless/Config.in linux-2.4.26-pre6/drivers/net/wireless/Config.in
--- linux-2.4.25/drivers/net/wireless/Config.in	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/wireless/Config.in	2004-03-25 00:18:40.000000000 +0000
@@ -24,6 +24,7 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
 
    dep_tristate '  Hermes PCMCIA card support' CONFIG_PCMCIA_HERMES $CONFIG_HERMES
    tristate '  Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards' CONFIG_AIRO_CS
+   dep_tristate '  Atmel at76c502/at76c504 PCMCIA cards' CONFIG_PCMCIA_ATMEL $CONFIG_FW_LOADER
 fi
 
 # yes, this works even when no drivers are selected
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/wireless/Makefile linux-2.4.26-pre6/drivers/net/wireless/Makefile
--- linux-2.4.25/drivers/net/wireless/Makefile	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/wireless/Makefile	2004-03-25 00:22:36.000000000 +0000
@@ -12,7 +12,7 @@ obj-n		:=
 obj-		:=
 
 # Things that need to export symbols
-export-objs	:= airo.o orinoco.o hermes.o
+export-objs	:= airo.o orinoco.o hermes.o atmel.o
 
 obj-$(CONFIG_HERMES)		+= orinoco.o hermes.o
 obj-$(CONFIG_PCMCIA_HERMES)	+= orinoco_cs.o
@@ -23,5 +23,6 @@ obj-$(CONFIG_PCI_HERMES)	+= orinoco_pci.
 
 obj-$(CONFIG_AIRO)		+= airo.o
 obj-$(CONFIG_AIRO_CS)		+= airo_cs.o airo.o
+obj-$(CONFIG_PCMCIA_ATMEL)	+= atmel_cs.o atmel.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/wireless/airo.c linux-2.4.26-pre6/drivers/net/wireless/airo.c
--- linux-2.4.25/drivers/net/wireless/airo.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/wireless/airo.c	2004-03-25 00:17:32.000000000 +0000
@@ -18,7 +18,6 @@
 ======================================================================*/
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/init.h>
 
 #include <linux/kernel.h>
@@ -41,12 +40,11 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_PCI
-static struct pci_device_id card_ids[] __devinitdata = {
+static struct pci_device_id card_ids[] = {
 	{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
 	{ 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
@@ -60,10 +58,10 @@ static int airo_pci_probe(struct pci_dev
 static void airo_pci_remove(struct pci_dev *);
 
 static struct pci_driver airo_driver = {
-	name:     "airo",
-	id_table: card_ids,
-	probe:    airo_pci_probe,
-	remove:   __devexit_p(airo_pci_remove),
+	.name     = "airo",
+	.id_table = card_ids,
+	.probe    = airo_pci_probe,
+	.remove   = __devexit_p(airo_pci_remove),
 };
 #endif /* CONFIG_PCI */
 
@@ -202,12 +200,6 @@ static char *statsLabels[] = {
 #ifndef RUN_AT
 #define RUN_AT(x) (jiffies+(x))
 #endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
-static inline struct proc_dir_entry *PDE(const struct inode *inode)
-{
-	return inode->u.generic_ip;
-}
-#endif
 
 
 /* These variables are for insmod, since it seems that the rates
@@ -982,7 +974,7 @@ static u16 transmit_allocate(struct airo
 static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);
 static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);
 
-static void airo_interrupt( int irq, void* dev_id, struct pt_regs
+static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
 			    *regs);
 static int airo_thread(void *data);
 static void timer_func( struct net_device *dev );
@@ -1034,6 +1026,7 @@ struct airo_info {
 #define FLAG_802_11	7
 #define FLAG_PENDING_XMIT 9
 #define FLAG_PENDING_XMIT11 10
+#define FLAG_PCI	11
 #define JOB_MASK	0x1ff0000
 #define JOB_DIE		16
 #define JOB_XMIT	17
@@ -2077,7 +2070,7 @@ void stop_airo_card( struct net_device *
 		unregister_netdev( dev );
 		if (ai->wifidev) {
 			unregister_netdev(ai->wifidev);
-			kfree(ai->wifidev);
+			free_netdev(ai->wifidev);
 			ai->wifidev = 0;
 		}
 		ai->registered = 0;
@@ -2098,7 +2091,7 @@ void stop_airo_card( struct net_device *
 		crypto_free_tfm(ai->tfm);
 #endif
 	del_airo_dev( dev );
-	kfree( dev );
+	free_netdev( dev );
 }
 
 EXPORT_SYMBOL(stop_airo_card);
@@ -2447,20 +2440,23 @@ static int airo_thread(void *data) {
 	complete_and_exit (&ai->thr_exited, 0);
 }
 
-static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
+static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
 	struct net_device *dev = (struct net_device *)dev_id;
 	u16 status;
 	u16 fid;
 	struct airo_info *apriv = dev->priv;
 	u16 savedInterrupts = 0;
+	int handled = 0;
 
 	if (!netif_device_present(dev))
-		return;
+		return IRQ_NONE;
 
 	for (;;) {
 		status = IN4500( apriv, EVSTAT );
 		if ( !(status & STATUS_INTS) || status == 0xffff ) break;
 
+		handled = 1;
+
 		if ( status & EV_AWAKE ) {
 			OUT4500( apriv, EVACK, EV_AWAKE );
 			OUT4500( apriv, EVACK, EV_AWAKE );
@@ -2790,7 +2786,7 @@ exitrx:
 		OUT4500( apriv, EVINTEN, savedInterrupts );
 
 	/* done.. */
-	return;
+	return IRQ_RETVAL(handled);
 }
 
 /*
@@ -3476,56 +3472,56 @@ static int proc_config_open( struct inod
 static int proc_wepkey_open( struct inode *inode, struct file *file );
 
 static struct file_operations proc_statsdelta_ops = {
-	read:           proc_read,
-	open:           proc_statsdelta_open,
-	release:        proc_close
+	.read		= proc_read,
+	.open		= proc_statsdelta_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_stats_ops = {
-	read:           proc_read,
-	open:           proc_stats_open,
-	release:        proc_close
+	.read		= proc_read,
+	.open		= proc_stats_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_status_ops = {
-	read:            proc_read,
-	open:            proc_status_open,
-	release:         proc_close
+	.read		= proc_read,
+	.open		= proc_status_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_SSID_ops = {
-	read:          proc_read,
-	write:         proc_write,
-	open:          proc_SSID_open,
-	release:       proc_close
+	.read		= proc_read,
+	.write		= proc_write,
+	.open		= proc_SSID_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_BSSList_ops = {
-	read:          proc_read,
-	write:         proc_write,
-	open:          proc_BSSList_open,
-	release:       proc_close
+	.read		= proc_read,
+	.write		= proc_write,
+	.open		= proc_BSSList_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_APList_ops = {
-	read:          proc_read,
-	write:         proc_write,
-	open:          proc_APList_open,
-	release:       proc_close
+	.read		= proc_read,
+	.write		= proc_write,
+	.open		= proc_APList_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_config_ops = {
-	read:          proc_read,
-	write:         proc_write,
-	open:          proc_config_open,
-	release:       proc_close
+	.read		= proc_read,
+	.write		= proc_write,
+	.open		= proc_config_open,
+	.release	= proc_close
 };
 
 static struct file_operations proc_wepkey_ops = {
-	read:          proc_read,
-	write:         proc_write,
-	open:          proc_wepkey_open,
-	release:       proc_close
+	.read		= proc_read,
+	.write		= proc_write,
+	.open		= proc_wepkey_open,
+	.release	= proc_close
 };
 
 static struct proc_dir_entry *airo_entry = 0;
@@ -3553,6 +3549,7 @@ static int setup_proc_entry( struct net_
 					      airo_entry);
         apriv->proc_entry->uid = proc_uid;
         apriv->proc_entry->gid = proc_gid;
+	apriv->proc_entry->owner = THIS_MODULE;
 
 	/* Setup the StatsDelta */
 	entry = create_proc_entry("StatsDelta",
@@ -3561,6 +3558,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_statsdelta_ops);
 
 	/* Setup the Stats */
@@ -3570,6 +3568,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_stats_ops);
 
 	/* Setup the Status */
@@ -3579,6 +3578,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_status_ops);
 
 	/* Setup the Config */
@@ -3588,6 +3588,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_config_ops);
 
 	/* Setup the SSID */
@@ -3597,6 +3598,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_SSID_ops);
 
 	/* Setup the APList */
@@ -3606,6 +3608,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_APList_ops);
 
 	/* Setup the BSSList */
@@ -3615,6 +3618,7 @@ static int setup_proc_entry( struct net_
 	entry->uid = proc_uid;
 	entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_BSSList_ops);
 
 	/* Setup the WepKey */
@@ -3624,6 +3628,7 @@ static int setup_proc_entry( struct net_
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_wepkey_ops);
 
 	return 0;
@@ -3714,8 +3719,6 @@ static int proc_status_open( struct inod
 	StatusRid status_rid;
 	int i;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3795,8 +3798,6 @@ static int proc_stats_rid_open( struct i
 	StatsRid stats;
 	int i, j;
 	int *vals = stats.vals;
-	MOD_INC_USE_COUNT;
-
 
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
@@ -4064,8 +4065,6 @@ static int proc_config_open( struct inod
 	struct airo_info *ai = dev->priv;
 	int i;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -4337,8 +4336,6 @@ static int proc_wepkey_open( struct inod
 	int j=0;
 	int rc;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -4387,8 +4384,6 @@ static int proc_SSID_open( struct inode 
 	char *ptr;
 	SsidRid SSID_rid;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -4433,8 +4428,6 @@ static int proc_APList_open( struct inod
 	char *ptr;
 	APListRid APList_rid;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -4485,8 +4478,6 @@ static int proc_BSSList_open( struct ino
 	/* If doLoseSync is not 1, we won't do a Lose Sync */
 	int doLoseSync = -1;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -4549,7 +4540,6 @@ static int proc_close( struct inode *ino
 {
 	struct proc_data *data = (struct proc_data *)file->private_data;
 	if ( data->on_close != NULL ) data->on_close( inode, file );
-	MOD_DEC_USE_COUNT;
 	if ( data->rbuffer ) kfree( data->rbuffer );
 	if ( data->wbuffer ) kfree( data->wbuffer );
 	kfree( data );
@@ -4638,6 +4628,7 @@ static int __devinit airo_pci_probe(stru
 		return -ENODEV;
 
 	pci_set_drvdata(pdev, dev);
+	set_bit (FLAG_PCI, &((struct airo_info *)dev->priv)->flags);
 	return 0;
 }
 
@@ -4667,7 +4658,7 @@ static int __init airo_init_module( void
 
 #ifdef CONFIG_PCI
 	printk( KERN_INFO "airo:  Probing for PCI adapters\n" );
-	pci_register_driver(&airo_driver);
+	pci_module_init(&airo_driver);		/* FIXME: check return val */
 	printk( KERN_INFO "airo:  Finished probing for PCI adapters\n" );
 #endif
 
@@ -4679,15 +4670,22 @@ static int __init airo_init_module( void
 
 static void __exit airo_cleanup_module( void )
 {
+	int is_pci = 0;
 	while( airo_devices ) {
 		printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name );
+#ifdef CONFIG_PCI
+		if (test_bit(FLAG_PCI, &((struct airo_info *)airo_devices->dev->priv)->flags))
+			is_pci = 1;
+#endif
 		stop_airo_card( airo_devices->dev, 1 );
 	}
 	remove_proc_entry("aironet", proc_root_driver);
 
+	if (is_pci) {
 #ifdef CONFIG_PCI
-	pci_unregister_driver(&airo_driver);
+		pci_unregister_driver(&airo_driver);
 #endif
+	}
 }
 
 #ifdef WIRELESS_EXT
@@ -6183,16 +6181,17 @@ static const iw_handler		airo_private_ha
 
 static const struct iw_handler_def	airo_handler_def =
 {
-	num_standard:	sizeof(airo_handler)/sizeof(iw_handler),
-	num_private:	sizeof(airo_private_handler)/sizeof(iw_handler),
-	num_private_args: sizeof(airo_private_args)/sizeof(struct iw_priv_args),
-	standard:	(iw_handler *) airo_handler,
-	private:	(iw_handler *) airo_private_handler,
-	private_args:	(struct iw_priv_args *) airo_private_args,
+	.num_standard	= sizeof(airo_handler)/sizeof(iw_handler),
+	.num_private	= sizeof(airo_private_handler)/sizeof(iw_handler),
+	.num_private_args = sizeof(airo_private_args)/sizeof(struct iw_priv_args),
+	.standard	= (iw_handler *) airo_handler,
+	.private	= (iw_handler *) airo_private_handler,
+	.private_args	= (struct iw_priv_args *) airo_private_args,
 #if WIRELESS_EXT > 15
-	spy_offset:	((void *) (&((struct airo_info *) NULL)->spy_data) -
+	.spy_offset	= ((void *) (&((struct airo_info *) NULL)->spy_data) -
 			   (void *) NULL),
 #endif /* WIRELESS_EXT > 15 */
+
 };
 
 #endif /* WIRELESS_EXT > 12 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/wireless/atmel.c linux-2.4.26-pre6/drivers/net/wireless/atmel.c
--- linux-2.4.25/drivers/net/wireless/atmel.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/wireless/atmel.c	2004-03-25 00:20:15.000000000 +0000
@@ -0,0 +1,3926 @@
+/*** -*- linux-c -*- **********************************************************
+
+     Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+        Copyright 2000-2001 ATMEL Corporation.
+        Copyright 2003 Simon Kelley.
+
+    This code was developed from version 2.1.1 of the Atmel drivers, 
+    released by Atmel corp. under the GPL in December 2002. It also 
+    includes code from the Linux aironet drivers (C) Benjamin Reed, 
+    and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
+    extensions, (C) Jean Tourrilhes.
+
+    The firmware module for reading the MAC address of the card comes from
+    net.russotto.AtmelMACFW, written by Matthew T. Russotto and copyright
+    by him. net.russotto.AtmelMACFW is used under the GPL license version 2.
+    This file contains the module in binary form and, under the terms
+    of the GPL, in source form. The source is located at the end of the file.
+
+    For all queries about this code, please contact the current author, 
+    Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This software is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Atmel wireless lan drivers; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+******************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/byteorder/generic.h>
+#include <linux/crc32.h>
+#include <linux/proc_fs.h>
+#include <linux/firmware.h>
+#include "ieee802_11.h"
+
+#define DRIVER_MAJOR 0
+#define DRIVER_MINOR 8
+
+MODULE_AUTHOR("Simon Kelley");
+MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
+
+/* The name of the firmware file to be loaded 
+   over-rides any automatic selection */
+static char *firmware = NULL;
+
+#define MAX_SSID_LENGTH 32
+#define MGMT_JIFFIES (256 * HZ / 100)
+
+#define MAX_BSS_ENTRIES	64	
+
+/* registers */
+#define GCR  0x00    //      (SIR0)  General Configuration Register        
+#define BSR  0x02    //      (SIR1)  Bank Switching Select Register 
+#define AR   0x04
+#define DR   0x08
+#define MR1  0x12    //      Mirror Register 1                  
+#define MR2  0x14    //      Mirror Register 2  
+#define MR3  0x16    //      Mirror Register 3  
+#define MR4  0x18    //      Mirror Register 4   
+
+#define GPR1                            0x0c
+#define GPR2                            0x0e
+#define GPR3                            0x10
+//
+// Constants for the GCR register.
+//
+#define GCR_REMAP     0x0400          // Remap internal SRAM to 0
+#define GCR_SWRES     0x0080          // BIU reset (ARM and PAI are NOT reset) 
+#define GCR_CORES     0x0060          // Core Reset (ARM and PAI are reset)
+#define GCR_ENINT     0x0002          // Enable Interrupts    
+#define GCR_ACKINT    0x0008          // Acknowledge Interrupts
+
+#define BSS_SRAM      0x0200          // AMBA module selection --> SRAM
+#define BSS_IRAM      0x0100          // AMBA module selection --> IRAM
+//
+// Constants for the MR registers.
+//
+#define MAC_INIT_COMPLETE       0x0001        // MAC init has been completed
+#define MAC_BOOT_COMPLETE       0x0010        // MAC boot has been completed
+#define MAC_INIT_OK             0x0002        // MAC boot has been completed
+
+#define C80211_SUBTYPE_MGMT_ASS_REQUEST                 0x00
+#define C80211_SUBTYPE_MGMT_ASS_RESPONSE                0x10
+#define C80211_SUBTYPE_MGMT_REASS_REQUEST               0x20
+#define C80211_SUBTYPE_MGMT_REASS_RESPONSE              0x30
+#define C80211_SUBTYPE_MGMT_ProbeRequest                0x40
+#define C80211_SUBTYPE_MGMT_ProbeResponse               0x50
+#define C80211_SUBTYPE_MGMT_BEACON                      0x80
+#define C80211_SUBTYPE_MGMT_ATIM                        0x90
+#define C80211_SUBTYPE_MGMT_DISASSOSIATION              0xA0
+#define C80211_SUBTYPE_MGMT_Authentication              0xB0
+#define C80211_SUBTYPE_MGMT_Deauthentication    0xC0
+
+#define C80211_MGMT_AAN_OPENSYSTEM              0x0000
+#define C80211_MGMT_AAN_SHAREDKEY               0x0001
+
+#define C80211_MGMT_CAPABILITY_ESS              0x0001  // see 802.11 p.58
+#define C80211_MGMT_CAPABILITY_IBSS             0x0002  //      - " -
+#define C80211_MGMT_CAPABILITY_CFPollable       0x0004  //      - " -
+#define C80211_MGMT_CAPABILITY_CFPollRequest    0x0008  //      - " -
+#define C80211_MGMT_CAPABILITY_Privacy          0x0010  //      - " -
+
+#define C80211_MGMT_SC_Success                  0
+#define C80211_MGMT_SC_Unspecified              1
+#define C80211_MGMT_SC_SupportCapabilities      10
+#define C80211_MGMT_SC_ReassDenied              11
+#define C80211_MGMT_SC_AssDenied                12
+#define C80211_MGMT_SC_AuthAlgNotSupported      13
+#define C80211_MGMT_SC_AuthTransSeqNumError     14
+#define C80211_MGMT_SC_AuthRejectChallenge      15
+#define C80211_MGMT_SC_AuthRejectTimeout        16
+#define C80211_MGMT_SC_AssDeniedHandleAP        17
+#define C80211_MGMT_SC_AssDeniedBSSRate         18
+
+#define C80211_MGMT_ElementID_SSID              0
+#define C80211_MGMT_ElementID_SupportedRates    1
+#define C80211_MGMT_ElementID_ChallengeText     16
+#define C80211_MGMT_CAPABILITY_ShortPreamble    0x0020
+
+struct get_set_mib {
+        u8 type;
+        u8 size;
+        u8 index;
+        u8 reserved;
+        u8 data[72];
+};
+
+struct rx_desc {
+        u32          Next;
+        u16          MsduPos;
+        u16          MsduSize;
+	
+        u8           State;
+        u8           Status;
+        u8           Rate;
+        u8           Rssi;
+        u8           LinkQuality;
+        u8           PreambleType;
+        u16          Duration;
+        u32          RxTime;
+
+};
+
+#define RX_DESC_FLAG_VALID       0x80
+#define RX_DESC_FLAG_CONSUMED    0x40
+#define RX_DESC_FLAG_IDLE        0x00
+
+#define RX_STATUS_SUCCESS        0x00
+
+#define RX_DESC_MSDU_POS_OFFSET      4
+#define RX_DESC_MSDU_SIZE_OFFSET     6
+#define RX_DESC_FLAGS_OFFSET         8
+#define RX_DESC_STATUS_OFFSET        9
+#define RX_DESC_RSSI_OFFSET          11
+#define RX_DESC_LINK_QUALITY_OFFSET  12
+#define RX_DESC_PREAMBLE_TYPE_OFFSET 13
+#define RX_DESC_DURATION_OFFSET      14
+#define RX_DESC_RX_TIME_OFFSET       16
+
+
+struct tx_desc {
+   u32       NextDescriptor;
+   u16       TxStartOfFrame;
+   u16       TxLength;
+   
+   u8        TxState;
+   u8        TxStatus;
+   u8        RetryCount;
+
+   u8        TxRate;
+   u32       TxTime;
+   u8        Reserved;
+   u8        PacketType;
+   u16       HostTxLength;
+
+};
+
+
+#define TX_DESC_NEXT_OFFSET        0
+#define TX_DESC_POS_OFFSET         4
+#define TX_DESC_SIZE_OFFSET        6
+#define TX_DESC_FLAGS_OFFSET       8
+#define TX_DESC_STATUS_OFFSET      9
+#define TX_DESC_RETRY_OFFSET       10
+#define TX_DESC_RATE_OFFSET        11
+#define TX_DESC_PACKET_TYPE_OFFSET 17
+#define TX_DESC_HOST_LENGTH_OFFSET 18
+
+
+
+///////////////////////////////////////////////////////
+// Host-MAC interface
+///////////////////////////////////////////////////////
+
+#define TX_STATUS_SUCCESS       0x00
+
+#define TX_FIRM_OWN             0x80
+#define TX_DONE                 0x40
+
+
+#define TX_ERROR                0x01
+
+#define TX_PACKET_TYPE_DATA     0x01
+#define TX_PACKET_TYPE_MGMT     0x02
+
+#define ISR_EMPTY               0x00        // no bits set in ISR
+#define ISR_TxCOMPLETE          0x01        // packet transmitted
+#define ISR_RxCOMPLETE          0x02        // packet received
+#define ISR_RxFRAMELOST         0x04        // Rx Frame lost
+#define ISR_FATAL_ERROR         0x08        // Fatal error
+#define ISR_COMMAND_COMPLETE    0x10        // command completed
+#define ISR_OUT_OF_RANGE        0x20        // command completed
+#define ISR_IBSS_MERGE          0x40        // (4.1.2.30): IBSS merge
+#define ISR_GENERIC_IRQ         0x80                
+
+
+#define Local_Mib_Type          0x01
+#define Mac_Address_Mib_Type    0x02
+#define Mac_Mib_Type            0x03
+#define Statistics_Mib_Type     0x04
+#define Mac_Mgmt_Mib_Type       0x05
+#define Mac_Wep_Mib_Type        0x06
+#define Phy_Mib_Type            0x07
+#define Multi_Domain_MIB        0x08
+
+#define MAC_MGMT_MIB_CUR_BSSID_POS            14
+#define MAC_MIB_FRAG_THRESHOLD_POS            8
+#define MAC_MIB_RTS_THRESHOLD_POS             10
+#define MAC_MIB_SHORT_RETRY_POS               16
+#define MAC_MIB_LONG_RETRY_POS                17
+#define MAC_MIB_SHORT_RETRY_LIMIT_POS         16
+#define MAC_MGMT_MIB_BEACON_PER_POS           0
+#define MAC_MGMT_MIB_STATION_ID_POS           6
+#define MAC_MGMT_MIB_CUR_PRIVACY_POS          11
+#define MAC_MGMT_MIB_CUR_BSSID_POS            14
+#define MAC_MGMT_MIB_PS_MODE_POS              53
+#define MAC_MGMT_MIB_LISTEN_INTERVAL_POS      54
+#define MAC_MGMT_MIB_MULTI_DOMAIN_IMPLEMENTED 56
+#define MAC_MGMT_MIB_MULTI_DOMAIN_ENABLED     57
+#define PHY_MIB_CHANNEL_POS                   14
+#define PHY_MIB_RATE_SET_POS                  20
+#define PHY_MIB_REG_DOMAIN_POS                26
+#define LOCAL_MIB_AUTO_TX_RATE_POS            3
+#define LOCAL_MIB_SSID_SIZE                   5
+#define LOCAL_MIB_TX_PROMISCUOUS_POS          6
+#define LOCAL_MIB_TX_MGMT_RATE_POS            7
+#define LOCAL_MIB_TX_CONTROL_RATE_POS         8
+#define LOCAL_MIB_PREAMBLE_TYPE               9
+#define MAC_ADDR_MIB_MAC_ADDR_POS             0
+
+
+#define         CMD_Set_MIB_Vars              0x01
+#define         CMD_Get_MIB_Vars              0x02
+#define         CMD_Scan                      0x03
+#define         CMD_Join                      0x04
+#define         CMD_Start                     0x05
+#define         CMD_EnableRadio               0x06
+#define         CMD_DisableRadio              0x07
+#define         CMD_SiteSurvey                0x0B
+
+#define         CMD_STATUS_IDLE                   0x00
+#define         CMD_STATUS_COMPLETE               0x01
+#define         CMD_STATUS_UNKNOWN                0x02
+#define         CMD_STATUS_INVALID_PARAMETER      0x03
+#define         CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
+#define         CMD_STATUS_TIME_OUT               0x07
+#define         CMD_STATUS_IN_PROGRESS            0x08
+#define         CMD_STATUS_REJECTED_RADIO_OFF     0x09
+#define         CMD_STATUS_HOST_ERROR             0xFF
+#define         CMD_STATUS_BUSY                   0xFE
+
+
+#define CMD_BLOCK_COMMAND_OFFSET        0
+#define CMD_BLOCK_STATUS_OFFSET         1
+#define CMD_BLOCK_PARAMETERS_OFFSET     4
+
+#define SCAN_OPTIONS_SITE_SURVEY        0x80
+
+#define MGMT_FRAME_BODY_OFFSET		24
+#define MAX_AUTHENTICATION_RETRIES	3
+#define MAX_ASSOCIATION_RETRIES 	3
+
+#define AUTHENTICATION_RESPONSE_TIME_OUT  1000
+
+#define MAX_WIRELESS_BODY  2316 /* mtu is 2312, CRC is 4 */
+#define LOOP_RETRY_LIMIT   500000
+
+#define ACTIVE_MODE 	1
+#define PS_MODE 	2
+
+///////////////////////////////////////////////////////////////////////////
+// 802.11 related definitions
+///////////////////////////////////////////////////////////////////////////
+
+//
+// Regulatory Domains
+//
+
+#define REG_DOMAIN_FCC		0x10	//Channels	1-11	USA
+#define REG_DOMAIN_DOC		0x20	//Channel	1-11	Canada
+#define REG_DOMAIN_ETSI		0x30	//Channel	1-13	Europe (ex Spain/France)
+#define REG_DOMAIN_SPAIN	0x31	//Channel	10-11	Spain
+#define REG_DOMAIN_FRANCE	0x32	//Channel	10-13	France
+#define REG_DOMAIN_MKK		0x40	//Channel	14	Japan
+#define REG_DOMAIN_MKK1		0x41	//Channel	1-14	Japan(MKK1)
+#define REG_DOMAIN_ISRAEL	0x50	//Channel	3-9	ISRAEL
+
+#define BSS_TYPE_AD_HOC 	1
+#define BSS_TYPE_INFRASTRUCTURE 2
+
+#define SCAN_TYPE_ACTIVE	0
+#define SCAN_TYPE_PASSIVE	1
+
+#define LONG_PREAMBLE		0
+#define SHORT_PREAMBLE		1
+#define AUTO_PREAMBLE		2
+
+#define DATA_FRAME_WS_HEADER_SIZE   30
+
+/* promiscuous mode control */ 
+#define PROM_MODE_OFF			0x0
+#define PROM_MODE_UNKNOWN		0x1
+#define PROM_MODE_CRC_FAILED		0x2
+#define PROM_MODE_DUPLICATED		0x4
+#define PROM_MODE_MGMT			0x8
+#define PROM_MODE_CTRL			0x10
+#define PROM_MODE_BAD_PROTOCOL		0x20
+
+
+#define IFACE_INT_STATUS_OFFSET 	0
+#define IFACE_INT_MASK_OFFSET		1
+#define IFACE_LOCKOUT_HOST_OFFSET	2
+#define IFACE_LOCKOUT_MAC_OFFSET	3
+#define IFACE_FUNC_CTRL_OFFSET		28
+#define IFACE_MAC_STAT_OFFSET		30
+#define IFACE_GENERIC_INT_TYPE_OFFSET	32
+//
+// IFACE MACROS & definitions
+//
+//
+
+// FuncCtrl field: 
+//
+#define FUNC_CTRL_TxENABLE		0x10
+#define FUNC_CTRL_RxENABLE		0x20
+#define FUNC_CTRL_INIT_COMPLETE 	0x01
+
+/* A stub firmware image which reads the MAC address from NVRAM on the card.
+   For copyright information and source see the end of this file. */
+static u8 mac_reader[] = {
+	0x06,0x00,0x00,0xea,0x04,0x00,0x00,0xea,0x03,0x00,0x00,0xea,0x02,0x00,0x00,0xea,
+	0x01,0x00,0x00,0xea,0x00,0x00,0x00,0xea,0xff,0xff,0xff,0xea,0xfe,0xff,0xff,0xea,
+	0xd3,0x00,0xa0,0xe3,0x00,0xf0,0x21,0xe1,0x0e,0x04,0xa0,0xe3,0x00,0x10,0xa0,0xe3,
+	0x81,0x11,0xa0,0xe1,0x00,0x10,0x81,0xe3,0x00,0x10,0x80,0xe5,0x1c,0x10,0x90,0xe5,
+	0x10,0x10,0xc1,0xe3,0x1c,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3,0x08,0x10,0x80,0xe5,
+	0x02,0x03,0xa0,0xe3,0x00,0x10,0xa0,0xe3,0xb0,0x10,0xc0,0xe1,0xb4,0x10,0xc0,0xe1,
+	0xb8,0x10,0xc0,0xe1,0xbc,0x10,0xc0,0xe1,0x56,0xdc,0xa0,0xe3,0x21,0x00,0x00,0xeb,
+	0x0a,0x00,0xa0,0xe3,0x1a,0x00,0x00,0xeb,0x10,0x00,0x00,0xeb,0x07,0x00,0x00,0xeb,
+	0x02,0x03,0xa0,0xe3,0x02,0x14,0xa0,0xe3,0xb4,0x10,0xc0,0xe1,0x4c,0x10,0x9f,0xe5,
+	0xbc,0x10,0xc0,0xe1,0x10,0x10,0xa0,0xe3,0xb8,0x10,0xc0,0xe1,0xfe,0xff,0xff,0xea,
+	0x00,0x40,0x2d,0xe9,0x00,0x20,0xa0,0xe3,0x02,0x3c,0xa0,0xe3,0x00,0x10,0xa0,0xe3,
+	0x28,0x00,0x9f,0xe5,0x37,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,
+	0x00,0x40,0x2d,0xe9,0x12,0x2e,0xa0,0xe3,0x06,0x30,0xa0,0xe3,0x00,0x10,0xa0,0xe3,
+	0x02,0x04,0xa0,0xe3,0x2f,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,
+	0x00,0x02,0x00,0x02,0x80,0x01,0x90,0xe0,0x01,0x00,0x00,0x0a,0x01,0x00,0x50,0xe2,
+	0xfc,0xff,0xff,0xea,0x1e,0xff,0x2f,0xe1,0x80,0x10,0xa0,0xe3,0xf3,0x06,0xa0,0xe3,
+	0x00,0x10,0x80,0xe5,0x00,0x10,0xa0,0xe3,0x00,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3,
+	0x04,0x10,0x80,0xe5,0x00,0x10,0x80,0xe5,0x0e,0x34,0xa0,0xe3,0x1c,0x10,0x93,0xe5,
+	0x02,0x1a,0x81,0xe3,0x1c,0x10,0x83,0xe5,0x58,0x11,0x9f,0xe5,0x30,0x10,0x80,0xe5,
+	0x54,0x11,0x9f,0xe5,0x34,0x10,0x80,0xe5,0x38,0x10,0x80,0xe5,0x3c,0x10,0x80,0xe5,
+	0x10,0x10,0x90,0xe5,0x08,0x00,0x90,0xe5,0x1e,0xff,0x2f,0xe1,0xf3,0x16,0xa0,0xe3,
+	0x08,0x00,0x91,0xe5,0x05,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5,0x10,0x00,0x91,0xe5,
+	0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0xff,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5,
+	0x10,0x00,0x91,0xe5,0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5,
+	0x10,0x00,0x91,0xe5,0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5,
+	0xff,0x00,0x00,0xe2,0x1e,0xff,0x2f,0xe1,0x30,0x40,0x2d,0xe9,0x00,0x50,0xa0,0xe1,
+	0x03,0x40,0xa0,0xe1,0xa2,0x02,0xa0,0xe1,0x08,0x00,0x00,0xe2,0x03,0x00,0x80,0xe2,
+	0xd8,0x10,0x9f,0xe5,0x00,0x00,0xc1,0xe5,0x01,0x20,0xc1,0xe5,0xe2,0xff,0xff,0xeb,
+	0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x1a,0x14,0x00,0xa0,0xe3,0xc4,0xff,0xff,0xeb,
+	0x04,0x20,0xa0,0xe1,0x05,0x10,0xa0,0xe1,0x02,0x00,0xa0,0xe3,0x01,0x00,0x00,0xeb,
+	0x30,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x70,0x40,0x2d,0xe9,0xf3,0x46,0xa0,0xe3,
+	0x00,0x30,0xa0,0xe3,0x00,0x00,0x50,0xe3,0x08,0x00,0x00,0x9a,0x8c,0x50,0x9f,0xe5,
+	0x03,0x60,0xd5,0xe7,0x0c,0x60,0x84,0xe5,0x10,0x60,0x94,0xe5,0x02,0x00,0x16,0xe3,
+	0xfc,0xff,0xff,0x0a,0x01,0x30,0x83,0xe2,0x00,0x00,0x53,0xe1,0xf7,0xff,0xff,0x3a,
+	0xff,0x30,0xa0,0xe3,0x0c,0x30,0x84,0xe5,0x08,0x00,0x94,0xe5,0x10,0x00,0x94,0xe5,
+	0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x94,0xe5,0x00,0x00,0xa0,0xe3,
+	0x00,0x00,0x52,0xe3,0x0b,0x00,0x00,0x9a,0x10,0x50,0x94,0xe5,0x02,0x00,0x15,0xe3,
+	0xfc,0xff,0xff,0x0a,0x0c,0x30,0x84,0xe5,0x10,0x50,0x94,0xe5,0x01,0x00,0x15,0xe3,
+	0xfc,0xff,0xff,0x0a,0x08,0x50,0x94,0xe5,0x01,0x50,0xc1,0xe4,0x01,0x00,0x80,0xe2,
+	0x02,0x00,0x50,0xe1,0xf3,0xff,0xff,0x3a,0xc8,0x00,0xa0,0xe3,0x98,0xff,0xff,0xeb,
+	0x70,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x01,0x0c,0x00,0x02,0x01,0x02,0x00,0x02,
+	0x00,0x01,0x00,0x02
+};
+
+struct atmel_private {
+	void *card; /* Bus dependent stucture varies for PCcard */
+	int (*present_callback)(void *); /* And callback which uses it */
+	char firmware_id[32];
+	unsigned char *firmware;
+	int firmware_length;
+	struct timer_list management_timer;
+	struct net_device *dev;
+	struct iw_statistics wstats;
+	struct net_device_stats	stats;	// device stats
+	spinlock_t irqlock, timerlock;	// spinlocks
+	enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
+	enum { 
+		CARD_TYPE_PARALLEL_FLASH, 
+		CARD_TYPE_SPI_FLASH,
+		CARD_TYPE_EEPROM 
+	} card_type;
+	int is3com; /* is this a 3com card? they are uniquely borken */
+	int do_rx_crc; /* If we need to CRC incoming packets */
+	int probe_crc; /* set if we don't yet know */
+	int crc_ok_cnt, crc_ko_cnt; /* counters for probing */
+	u16 rx_desc_head;
+	u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
+	u16 tx_free_mem, tx_buff_head, tx_buff_tail;
+	
+	u16 frag_seq, frag_len, frag_no;
+	u8 frag_source[6]; 
+	
+	int wep_key_len[4]; /* need to know these and not stored in Mib. */
+	struct { /* NB this is matched to the hardware, don't change. */
+		u8 wep_is_on;                 
+		u8 default_key; /* 0..3 */
+		u8 reserved;
+		u8 exclude_unencrypted;
+		
+		u32 WEPICV_error_count;
+		u32 WEP_excluded_count;
+		
+		u8 wep_keys[4][13];
+		u8 encryption_level; /* 0, 1, 2 */
+		u8 reserved2[3];
+	} wep;
+
+	u16 host_info_base;
+	struct host_info_struct { 
+		/* NB this is matched to the hardware, don't change. */
+		u8 volatile int_status;
+		u8 volatile int_mask;
+		u8 volatile lockout_host;
+		u8 volatile lockout_mac;
+
+		u16 tx_buff_pos;
+		u16 tx_buff_size;
+		u16 tx_desc_pos;
+		u16 tx_desc_count;
+
+		u16 rx_buff_pos;
+		u16 rx_buff_size;
+		u16 rx_desc_pos;
+		u16 rx_desc_count;
+		
+		u16 build_version;
+		u16 command_pos; 	
+		
+		u16 major_version;
+		u16 minor_version;
+		
+		u16 func_ctrl;
+		u16 mac_status;
+		u16 generic_IRQ_type;
+		u8  reserved[2];
+	} host_info;
+
+	enum { 
+		STATION_STATE_INITIALIZING,
+		STATION_STATE_SCANNING,
+		STATION_STATE_JOINNING,
+		STATION_STATE_AUTHENTICATING,
+		STATION_STATE_ASSOCIATING,
+		STATION_STATE_READY,
+		STATION_STATE_REASSOCIATING,
+		STATION_STATE_FORCED_JOINNING,
+		STATION_STATE_FORCED_JOIN_FAILURE,
+		STATION_STATE_DOWN,
+		STATION_STATE_NO_CARD,
+		STATION_STATE_MGMT_ERROR 
+	} station_state;
+	
+	int operating_mode, power_mode;
+	time_t last_qual;
+	int beacons_this_sec;
+	int channel;
+	int reg_domain;
+	int tx_rate;
+	int auto_tx_rate;;
+	int rts_threshold;
+	int frag_threshold;
+	int long_retry, short_retry;
+	int preamble;
+	int default_beacon_period, beacon_period, listen_interval;
+	int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;	
+	int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
+	enum {
+		SITE_SURVEY_IDLE,
+		SITE_SURVEY_IN_PROGRESS,
+		SITE_SURVEY_COMPLETED 
+	} site_survey_state;
+	time_t last_survey;
+
+	int station_was_associated, station_is_associated;
+	int fast_scan;
+				
+	struct bss_info {
+		int channel;
+		int SSIDsize;
+		int RSSI;
+		int UsingWEP;
+		int preamble;
+		int beacon_period;
+		int BSStype;
+		u8 BSSID[6];
+		u8 SSID[MAX_SSID_LENGTH];
+	} BSSinfo[MAX_BSS_ENTRIES];
+	int BSS_list_entries, current_BSS;
+	int connect_to_any_BSS; 
+	int SSID_size, new_SSID_size;
+	u8 CurrentBSSID[6], BSSID[6];
+	u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
+	u64 last_beacon_timestamp;
+	u8 rx_buf[MAX_WIRELESS_BODY];
+	
+};
+
+static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
+
+static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len);
+static void atmel_set_gcr(struct net_device *dev, u16 mask);
+static void atmel_clear_gcr(struct net_device *dev, u16 mask);
+static int atmel_lock_mac(struct atmel_private *priv);
+static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
+static void atmel_command_irq(struct atmel_private *priv);
+static int atmel_validate_channel(struct atmel_private *priv, int channel);
+static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header, 
+				   u16 frame_len, u8 rssi);
+static void atmel_management_timer(u_long a);
+static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
+static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+					    u8 *body, int body_len);
+
+static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
+static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data);
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data);
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
+static void atmel_scan(struct atmel_private *priv, int specific_ssid);
+static void atmel_join_bss(struct atmel_private *priv, int bss_index);
+static void atmel_smooth_qual(struct atmel_private *priv);
+static void atmel_writeAR(struct net_device *dev, u16 data);
+static int probe_atmel_card(struct net_device *dev);
+int reset_atmel_card(struct net_device *dev );
+static void atmel_enter_state(struct atmel_private *priv, int new_state);
+
+static inline u16 atmel_hi(struct atmel_private *priv, u16 offset)
+{
+	return priv->host_info_base + offset;
+}
+
+static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
+{
+	return priv->host_info.command_pos + offset;
+}
+
+static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16  desc)
+{
+	return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
+}
+
+static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16  desc)
+{
+	return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
+}
+
+static inline u8 atmel_read8(struct net_device *dev, u16 offset)
+{
+	return inb(dev->base_addr + offset);
+}
+
+static inline void atmel_write8(struct net_device *dev, u16 offset, u8 data)
+{
+	outb(data, dev->base_addr + offset);
+}
+
+static inline u16 atmel_read16(struct net_device *dev, u16 offset)
+{
+	return inw(dev->base_addr + offset);
+}
+
+static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
+{
+	outw(data, dev->base_addr + offset);
+}
+
+
+static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
+{
+	atmel_writeAR(priv->dev, pos);	
+	return atmel_read8(priv->dev, DR);
+}
+
+static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
+{
+	atmel_writeAR(priv->dev, pos);	
+	atmel_write8(priv->dev, DR, data);
+}
+
+static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
+{
+       	atmel_writeAR(priv->dev, pos);	
+	return atmel_read16(priv->dev, DR);
+}
+
+static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
+{
+       	atmel_writeAR(priv->dev, pos);	
+	atmel_write16(priv->dev, DR, data);
+}
+
+static const struct iw_handler_def atmel_handler_def;
+
+static void tx_done_irq(struct atmel_private *priv)
+{
+	int i;
+
+	for (i = 0; 
+	     atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
+		     i < priv->host_info.tx_desc_count;
+	     i++) {
+		
+		u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
+		u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
+		u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
+
+		atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head), 0);
+
+		priv->tx_free_mem += msdu_size;
+		priv->tx_desc_free++;
+
+		if (priv->tx_buff_head + msdu_size > (priv->host_info.tx_buff_pos + priv->host_info.tx_buff_size))
+			priv->tx_buff_head = 0;
+		else
+			priv->tx_buff_head += msdu_size;
+			
+		if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
+			priv->tx_desc_head++ ;					
+		else
+			priv->tx_desc_head = 0;
+		
+		if (type == TX_PACKET_TYPE_DATA) {
+			if (status == TX_STATUS_SUCCESS)
+				priv->stats.tx_packets++;
+			else 
+				priv->stats.tx_errors++;
+			netif_wake_queue(priv->dev);
+		}
+	}
+}
+
+static u16 find_tx_buff(struct atmel_private *priv, u16 len)
+{
+	u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
+
+	if (priv->tx_desc_free == 3 || priv->tx_free_mem < len) 
+		return 0;
+	
+	if (bottom_free >= len)
+		return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
+	
+	if (priv->tx_free_mem - bottom_free >= len) {
+		priv->tx_buff_tail = 0;
+		return priv->host_info.tx_buff_pos;
+	}
+	
+	return 0;
+}
+
+static void tx_update_descriptor(struct atmel_private *priv, u16 len, u16 buff, u8 type)
+{
+	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
+	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
+	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len);
+	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_tail), type);
+	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RATE_OFFSET, priv->tx_desc_tail), priv->tx_rate);
+	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RETRY_OFFSET, priv->tx_desc_tail), 0);
+	atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_tail), 0x80000000L);
+	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_tail), TX_FIRM_OWN);
+	if (priv->tx_desc_previous != priv->tx_desc_tail)
+		atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
+	priv->tx_desc_previous = priv->tx_desc_tail;
+	if (priv->tx_desc_tail < (priv->host_info.tx_desc_count -1 ))
+		priv->tx_desc_tail++;
+	else
+		priv->tx_desc_tail = 0;
+	priv->tx_desc_free--;
+	priv->tx_free_mem -= len;
+
+}
+
+static int start_tx (struct sk_buff *skb, struct net_device *dev)
+{
+	struct atmel_private *priv = (struct atmel_private *)dev->priv;
+	struct ieee802_11_hdr header;
+	unsigned long flags;
+	u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+	
+	if(priv->station_state != STATION_STATE_READY) {
+		priv->stats.tx_errors++;
+		return 0;
+	}
+	
+	if (priv->card && priv->present_callback && 
+	    !(*priv->present_callback)(priv->card)) {
+		priv->stats.tx_errors++;
+		return 0;
+	}
+	
+	/* first ensure the timer func cannot run */
+	spin_lock_bh(&priv->timerlock); 
+	/* then stop the hardware ISR */
+	spin_lock_irqsave(&priv->irqlock, flags); 
+	/* nb doing the above in the opposite order will deadlock */
+	
+	/* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
+	   12 first bytes (containing DA/SA) and put them in the appropriate fields of
+	   the Wireless Header. Thus the packet length is then the initial + 18 (+30-12) */
+	
+	if (!(buff = find_tx_buff(priv, len + 18))) {
+		priv->stats.tx_dropped++;
+		spin_unlock_irqrestore(&priv->irqlock, flags);
+		spin_unlock_bh(&priv->timerlock);
+		netif_stop_queue(dev);
+		return 1;
+	}
+	
+	frame_ctl = IEEE802_11_FTYPE_DATA;
+	header.duration_id = 0;
+	header.seq_ctl = 0;
+	if (priv->wep.wep_is_on)
+		frame_ctl |= IEEE802_11_FCTL_WEP;
+	if (priv->operating_mode == IW_MODE_ADHOC) {
+		memcpy(&header.addr1, skb->data, 6);
+		memcpy(&header.addr2, dev->dev_addr, 6);
+		memcpy(&header.addr3, priv->BSSID, 6);
+	} else {
+		frame_ctl |= IEEE802_11_FCTL_TODS;
+		memcpy(&header.addr1, priv->CurrentBSSID, 6);
+		memcpy(&header.addr2, dev->dev_addr, 6);
+		memcpy(&header.addr3, skb->data, 6);
+	}
+	
+	header.frame_ctl = cpu_to_le16(frame_ctl);
+	/* Copy the wireless header into the card */
+	atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
+	/* Copy the packet sans its 802.3 header addresses which have been replaced */
+	atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
+	priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
+	
+	tx_update_descriptor(priv, len + 18, buff, TX_PACKET_TYPE_DATA);
+	dev->trans_start = jiffies;
+	priv->stats.tx_bytes += len;
+	
+	spin_unlock_irqrestore(&priv->irqlock, flags);
+	spin_unlock_bh(&priv->timerlock);
+	dev_kfree_skb(skb);
+	
+	return 0;	
+}
+
+static void atmel_transmit_management_frame(struct atmel_private *priv, 
+				     struct ieee802_11_hdr *header,
+				     u8 *body, int body_len)
+{
+	u16 buff;
+	int len =  MGMT_FRAME_BODY_OFFSET + body_len;
+	
+	if (!(buff = find_tx_buff(priv, len))) 
+		return;
+
+	atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
+	atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len);
+	priv->tx_buff_tail += len;
+	tx_update_descriptor(priv, len, buff, TX_PACKET_TYPE_MGMT);
+}
+	
+static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header, 
+			 u16 msdu_size, u16 rx_packet_loc, u32 crc)
+{
+	/* fast path: unfragmented packet copy directly into skbuf */
+	u8 mac4[6]; 
+	struct sk_buff 	*skb;
+	unsigned char *skbp;
+	
+	/* get the final, mac 4 header field, this tells us encapsulation */
+	atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
+	msdu_size -= 6;
+	
+	if (priv->do_rx_crc) {
+		crc = crc32_le(crc, mac4, 6);
+		msdu_size -= 4;
+	}
+	
+	if (!(skb = dev_alloc_skb(msdu_size + 14))) {
+		priv->stats.rx_dropped++;
+		return;
+	}
+
+	skb_reserve(skb, 2);
+	skbp = skb_put(skb, msdu_size + 12);
+	atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
+	
+	if (priv->do_rx_crc) {
+		u32 netcrc;
+		crc = crc32_le(crc, skbp + 12, msdu_size);
+		atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);
+		if ((crc ^ 0xffffffff) != netcrc) {
+			priv->stats.rx_crc_errors++;
+			dev_kfree_skb(skb);
+			return;
+		}
+	}
+	
+	memcpy(skbp, header->addr1, 6); /* destination address */
+	if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS) 
+		memcpy(&skbp[6], header->addr3, 6);
+	else
+		memcpy(&skbp[6], header->addr2, 6); /* source address */
+	
+	priv->dev->last_rx=jiffies;
+	skb->dev = priv->dev;
+	skb->protocol = eth_type_trans(skb, priv->dev);
+	skb->ip_summed = CHECKSUM_NONE;	
+	netif_rx(skb);
+	priv->stats.rx_bytes += 12 + msdu_size;
+	priv->stats.rx_packets++;
+}
+
+/* Test to see if the packet in card memory at packet_loc has a valid CRC
+   It doesn't matter that this is slow: it is only used to proble the first few packets. */
+static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
+{
+	int i = msdu_size - 4;
+	u32 netcrc, crc = 0xffffffff;
+
+	if (msdu_size < 4)
+		return 0;
+
+	atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
+	
+	atmel_writeAR(priv->dev, packet_loc);
+	while (i--) {
+		u8 octet = atmel_read8(priv->dev, DR);
+		crc = crc32_le(crc, &octet, 1);
+	}
+
+	return (crc ^ 0xffffffff) == netcrc;
+}
+
+static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header, 
+			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
+{
+	u8 mac4[6]; 
+	u8 source[6];
+	struct sk_buff *skb;
+
+	if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS) 
+		memcpy(source, header->addr3, 6);
+	else
+		memcpy(source, header->addr2, 6); 
+	
+	rx_packet_loc += 24; /* skip header */
+	
+	if (priv->do_rx_crc)
+		msdu_size -= 4;
+
+	if (frag_no == 0) { /* first fragment */
+		atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, 6);
+		msdu_size -= 6;
+		rx_packet_loc += 6;
+
+		if (priv->do_rx_crc) 
+			crc = crc32_le(crc, mac4, 6);
+	       
+		priv->frag_seq = seq_no;
+		priv->frag_no = 1;
+		priv->frag_len = msdu_size;
+		memcpy(priv->frag_source, source, 6); 
+		memcpy(&priv->rx_buf[6], source, 6);
+		memcpy(priv->rx_buf, header->addr1, 6);
+				
+		atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
+
+		if (priv->do_rx_crc) {
+			u32 netcrc;
+			crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);
+			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
+			if ((crc ^ 0xffffffff) != netcrc) {
+				priv->stats.rx_crc_errors++;
+				memset(priv->frag_source, 0xff, 6);
+			}
+		}
+		
+	} else if (priv->frag_no == frag_no &&
+		   priv->frag_seq == seq_no &&
+		   memcmp(priv->frag_source, source, 6) == 0) {
+		
+		atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len], 
+				   rx_packet_loc, msdu_size);
+		if (priv->do_rx_crc) {
+			u32 netcrc;
+			crc = crc32_le(crc, 
+				       &priv->rx_buf[12 + priv->frag_len], 
+				       msdu_size);
+			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
+			if ((crc ^ 0xffffffff) != netcrc) {
+				priv->stats.rx_crc_errors++;
+				memset(priv->frag_source, 0xff, 6);
+				more_frags = 1; /* don't send broken assembly */
+			}
+		}
+		
+		priv->frag_len += msdu_size;
+		priv->frag_no++;
+
+		if (!more_frags) { /* last one */
+			memset(priv->frag_source, 0xff, 6);
+			if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {
+				priv->stats.rx_dropped++;
+			} else {
+				skb_reserve(skb, 2);
+				memcpy(skb_put(skb, priv->frag_len + 12), 
+				       priv->rx_buf,
+				       priv->frag_len + 12);
+				priv->dev->last_rx = jiffies;
+				skb->dev = priv->dev;
+				skb->protocol = eth_type_trans(skb, priv->dev);
+				skb->ip_summed = CHECKSUM_NONE;	
+				netif_rx(skb);
+				priv->stats.rx_bytes += priv->frag_len + 12;
+				priv->stats.rx_packets++;
+			}
+		}
+		
+	} else
+		priv->wstats.discard.fragment++;
+}
+		
+static void rx_done_irq(struct atmel_private *priv)
+{
+	int i;
+	struct ieee802_11_hdr header;
+	
+	for (i = 0; 
+	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
+		     i < priv->host_info.rx_desc_count;
+	     i++) {
+				
+		u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
+		u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
+		u32 crc = 0xffffffff;
+		
+		if (status != RX_STATUS_SUCCESS) {
+			if (status == 0xc1) /* determined by experiment */
+				priv->wstats.discard.nwid++;
+			else
+				priv->stats.rx_errors++; 
+			goto next;
+		}
+
+		msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
+		rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
+		
+		if (msdu_size < 30) {
+			priv->stats.rx_errors++; 
+			goto next;
+		}
+		
+		/* Get header as far as end of seq_ctl */
+		atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
+		frame_ctl = le16_to_cpu(header.frame_ctl);
+		seq_control = le16_to_cpu(header.seq_ctl);
+
+		/* probe for CRC use here if needed  once five packets have arrived with
+		   the same crc status, we assume we know what's happening and stop probing */
+		if (priv->probe_crc) {
+			if (!priv->wep.wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
+				priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
+			} else {
+				priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
+			}
+			if (priv->do_rx_crc) {
+				if (priv->crc_ok_cnt++ > 5)
+					priv->probe_crc = 0;
+			} else {
+				if (priv->crc_ko_cnt++ > 5)
+					priv->probe_crc = 0;
+			}
+		}
+		    
+		/* don't CRC header when WEP in use */
+		if (priv->do_rx_crc && (!priv->wep.wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
+			crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
+		}
+		msdu_size -= 24; /* header */
+
+		if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_DATA) { 
+			
+			int more_fragments = frame_ctl & IEEE802_11_FCTL_MOREFRAGS;
+			u8 packet_fragment_no = seq_control & IEEE802_11_SCTL_FRAG;
+			u16 packet_sequence_no = (seq_control & IEEE802_11_SCTL_SEQ) >> 4;
+			
+			if (!more_fragments && packet_fragment_no == 0 ) {
+				fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
+			} else {
+				frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
+					     packet_sequence_no, packet_fragment_no, more_fragments);
+			}
+		}
+		
+		if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_MGMT) {
+			/* copy rest of packet into buffer */
+			atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
+			
+			/* we use the same buffer for frag reassembly and control packets */
+			memset(priv->frag_source, 0xff, 6);
+			
+			if (priv->do_rx_crc) {
+				/* last 4 octets is crc */
+				msdu_size -= 4;
+				crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);
+				if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {
+					priv->stats.rx_crc_errors++;
+					goto next;
+				}
+			}
+
+			atmel_management_frame(priv, &header, msdu_size,
+					       atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
+		} 
+
+	next:
+		/* release descriptor */
+		atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);  
+		
+		if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
+			priv->rx_desc_head++;					
+		else
+			priv->rx_desc_head = 0;
+	}
+}	
+
+static void reset_irq_status(struct atmel_private *priv, u8 mask)
+{
+	u8 isr;
+	
+	atmel_lock_mac(priv);
+	isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
+	isr ^= mask;
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+}
+
+static void service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct atmel_private *priv = (struct atmel_private *) dev->priv;
+	u8 isr;
+	
+	if (priv->card && priv->present_callback && 
+	    !(*priv->present_callback)(priv->card))
+		return;
+     	
+	atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
+	
+	while (1) {
+		if (!atmel_lock_mac(priv)) {
+			printk(KERN_ALERT "%s: MAC gone away in ISR.\n", dev->name);
+			/* bad things - don't re-enable interrupts */
+			return;
+		}
+			
+		isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
+		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+		if (isr)
+			atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
+		else
+			break; /* no pending irqs */
+
+		if (isr & ISR_OUT_OF_RANGE) {
+			reset_irq_status(priv, ISR_OUT_OF_RANGE);
+			if(priv->operating_mode == IW_MODE_INFRA && 
+			   priv->station_state == STATION_STATE_READY) {
+				priv->station_is_associated = 0;
+				atmel_scan(priv, 1);
+			}
+		} else if (isr & ISR_RxCOMPLETE) {
+			reset_irq_status(priv, ISR_RxCOMPLETE);
+			rx_done_irq(priv); 
+		} else if (isr & ISR_TxCOMPLETE) {
+			reset_irq_status(priv, ISR_TxCOMPLETE);
+			tx_done_irq(priv); 
+		} else if (isr & ISR_RxFRAMELOST) {
+			reset_irq_status(priv, ISR_RxFRAMELOST);
+			priv->wstats.discard.misc++;
+			rx_done_irq(priv);
+		} else if (isr & ISR_FATAL_ERROR) {
+			reset_irq_status(priv, ISR_FATAL_ERROR);
+			printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
+			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+		} else if (isr & ISR_COMMAND_COMPLETE) {
+			reset_irq_status(priv, ISR_COMMAND_COMPLETE);
+			atmel_command_irq(priv);	
+		} else if (isr & ISR_IBSS_MERGE) {
+			reset_irq_status(priv, ISR_IBSS_MERGE);
+			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, 
+				      priv->CurrentBSSID, 6);
+		} else if (isr & ISR_GENERIC_IRQ) {
+			reset_irq_status(priv, ISR_GENERIC_IRQ);
+			printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name);
+		}
+	}	
+
+	atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+	return;
+}
+
+
+static struct net_device_stats *atmel_get_stats (struct net_device *dev)
+{
+	struct atmel_private *priv = (struct atmel_private *)dev->priv;
+	return &priv->stats;
+}
+
+static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
+{
+	struct atmel_private *priv = (struct atmel_private *)dev->priv;
+
+	/* update the link quality here in case we are seeing no beacons 
+	   at all to drive the process */
+	atmel_smooth_qual(priv);
+	
+	priv->wstats.status = priv->station_state;
+
+	if (priv->operating_mode == IW_MODE_INFRA) {
+		if (priv->station_state != STATION_STATE_READY) {
+			priv->wstats.qual.qual = 0;
+			priv->wstats.qual.level	= 0;
+		}
+		priv->wstats.qual.noise = 0;
+		priv->wstats.qual.updated = 7;
+	} else {
+		// Quality levels cannot be determined in ad-hoc mode,
+		// because we can 'hear' more than one remote station.
+		priv->wstats.qual.qual = 0;
+		priv->wstats.qual.level	= 0;
+		priv->wstats.qual.noise	= 0;
+		priv->wstats.qual.updated = 0;
+		priv->wstats.miss.beacon = 0;
+	}
+	
+	return (&priv->wstats);
+}
+
+static int atmel_change_mtu(struct net_device *dev, int new_mtu)
+{
+        if ((new_mtu < 68) || (new_mtu > 2312))
+                return -EINVAL;
+        dev->mtu = new_mtu;
+        return 0;
+}
+
+static int atmel_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+        
+        memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
+	reset_atmel_card(dev);
+	return 0;
+}
+
+static int atmel_open (struct net_device *dev)
+{
+	struct atmel_private *priv = (struct atmel_private *) dev->priv;
+	priv->station_state = STATION_STATE_INITIALIZING;
+	if (!reset_atmel_card(dev)) {
+		priv->station_state = STATION_STATE_DOWN;
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static int atmel_close (struct net_device *dev)
+{
+	struct atmel_private *priv = (struct atmel_private *) dev->priv;
+		
+	if (netif_running(dev))
+		netif_stop_queue(dev);
+	
+	priv->station_state = STATION_STATE_DOWN;
+	if (priv->bus_type == BUS_TYPE_PCCARD) 
+		atmel_write16(dev, GCR, 0x0060);
+	atmel_write16(dev, GCR, 0x0040);
+	return 0;
+}
+
+static int atmel_proc_output (char *buf, struct atmel_private *priv)
+{
+	char *p = buf;
+	char *s, *r, *c;
+	
+	p += sprintf(p, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
+	
+	if (priv->station_state != STATION_STATE_DOWN) {
+		p += sprintf(p, "Firmware version:\t%d.%d build %d ", 
+			     priv->host_info.major_version,
+			     priv->host_info.minor_version,
+			     priv->host_info.build_version);
+		
+		if (priv->card_type != CARD_TYPE_EEPROM) 
+			p += sprintf(p, "[built-in]\n");
+		else if (priv->firmware) 
+			p += sprintf(p, "[%s loaded by host]\n", priv->firmware_id);
+		else
+			p += sprintf(p, "[%s loaded by hotplug]\n", priv->firmware_id);
+		
+		switch(priv->card_type) {
+		case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;
+		case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break;
+		case CARD_TYPE_EEPROM: c = "EEPROM"; break;
+		default: c = "<unknown>";
+		}
+
+		switch (priv->reg_domain) {
+		case REG_DOMAIN_FCC: r = "USA"; break;
+		case REG_DOMAIN_DOC: r = "Canada"; break;
+		case REG_DOMAIN_ETSI: r = "Europe"; break;
+		case REG_DOMAIN_SPAIN: r = "Spain"; break;
+		case REG_DOMAIN_FRANCE: r = "France"; break;
+		case REG_DOMAIN_MKK: r = "Japan (MKK)"; break;
+		case REG_DOMAIN_MKK1: r = "Japan (MKK1)"; break;
+		case REG_DOMAIN_ISRAEL: r = "Israel"; break;
+		default: r = "<unknown>";
+		}
+		p += sprintf(p, "MAC memory type:\t%s\n", c);
+		p += sprintf(p, "Regulatory domain:\t%s\n", r);
+		p += sprintf(p, "Host CRC checking:\t%s\n", 
+			     priv->do_rx_crc ? "On" : "Off");
+	}
+	
+	switch(priv->station_state) {
+	case STATION_STATE_INITIALIZING: s = "Initialising"; break;
+	case STATION_STATE_SCANNING: s = "Scanning"; break;
+	case STATION_STATE_JOINNING: s = "Joining"; break;
+	case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break;
+	case STATION_STATE_ASSOCIATING: s = "Associating"; break;
+	case STATION_STATE_READY: s = "Ready"; break;
+	case STATION_STATE_REASSOCIATING: s = "Reassociating"; break;
+	case STATION_STATE_FORCED_JOINNING: s = "Forced joining"; break;
+	case STATION_STATE_FORCED_JOIN_FAILURE: s = "Forced join failure"; break;
+	case STATION_STATE_NO_CARD: s = "No card"; break;
+	case STATION_STATE_MGMT_ERROR: s = "Management error"; break;
+	case STATION_STATE_DOWN: s = "Down"; break;
+	default: s = "<unknown>";
+	}
+      
+	p += sprintf(p, "Current state:\t\t%s\n", s);
+	return  p - buf;
+}
+
+static int atmel_read_proc(char *page, char **start, off_t off,
+			   int count, int *eof, void *data)
+{
+        struct atmel_private *priv = (struct atmel_private *)data;
+	int len = atmel_proc_output (page, priv);
+        if (len <= off+count) *eof = 1;
+        *start = page + off;
+        len -= off;
+        if (len>count) len = count;
+        if (len<0) len = 0;
+        return len;
+}
+
+struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware_id, int is3com,  
+				    int (*card_present)(void *), void *card)
+{
+	struct net_device *dev;
+	struct atmel_private *priv;
+	int rc;
+
+	/* Create the network device object. */
+        dev = alloc_etherdev(sizeof(*priv));
+        if (!dev) {
+		printk(KERN_ERR "atmel:  Couldn't alloc_etherdev\n");
+		return NULL;
+        }
+	if (dev_alloc_name(dev, dev->name) < 0) {
+		printk(KERN_ERR "atmel:  Couldn't get name!\n");
+		goto err_out_free;
+	}
+
+	priv = dev->priv;
+	priv->dev = dev;
+	priv->present_callback = card_present;
+	priv->card = card;
+	priv->firmware = NULL;
+	if (firmware) /* module parameter */
+		strcpy(priv->firmware_id, firmware);
+	else if (firmware_id) /* from PCMCIA card-matching or PCI */
+		strcpy(priv->firmware_id, firmware_id);
+	else
+		priv->firmware_id[0] = '\0';
+	priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
+	priv->station_state = STATION_STATE_DOWN;
+	priv->is3com = is3com;
+	priv->do_rx_crc = 0;
+	/* For PCMCIA cards, some chips need CRC, some don't
+	   so we have to probe. */
+	if (priv->bus_type == BUS_TYPE_PCCARD) {
+		priv->probe_crc = 1;
+		priv->crc_ok_cnt = priv->crc_ko_cnt = 0;
+	} else
+		priv->probe_crc = 0;
+	memset(&priv->stats, 0, sizeof(priv->stats));
+	memset(&priv->wstats, 0, sizeof(priv->wstats));
+	priv->last_qual = jiffies;
+	priv->last_beacon_timestamp = 0;
+	memset(priv->frag_source, 0xff, sizeof(priv->frag_source));
+	memset(priv->BSSID, 0, 6);
+	priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
+	priv->station_was_associated = 0;
+	
+	priv->last_survey = jiffies;
+	priv->preamble = LONG_PREAMBLE;
+	priv->operating_mode = IW_MODE_INFRA;
+	priv->connect_to_any_BSS = 0;
+	priv->tx_rate = 3;
+	priv->auto_tx_rate = 1;
+	priv->channel = 4;
+	priv->power_mode = 0;
+	priv->SSID[0] = '\0';
+	priv->SSID_size = 0;
+	priv->new_SSID_size = 0;
+	priv->frag_threshold = 2346;
+	priv->rts_threshold = 2347;
+	priv->short_retry = 7;
+	priv->long_retry = 4;
+	priv->wep.wep_is_on = 0;
+	priv->wep.default_key = 0;
+	priv->wep.encryption_level = 0;
+	priv->default_beacon_period = priv->beacon_period = 100;
+	priv->listen_interval = 1;
+
+	init_timer(&priv->management_timer);
+	spin_lock_init(&priv->irqlock);
+	spin_lock_init(&priv->timerlock);
+	priv->management_timer.function = atmel_management_timer;
+	priv->management_timer.data = (unsigned long) dev;
+	
+	dev->open = atmel_open;
+	dev->stop = atmel_close;
+	dev->change_mtu = atmel_change_mtu;
+	dev->set_mac_address = atmel_set_mac_address;
+	dev->hard_start_xmit = start_tx;
+	dev->get_stats = atmel_get_stats;
+	dev->get_wireless_stats = atmel_get_wireless_stats;
+	dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def;
+	dev->do_ioctl = atmel_ioctl;
+	dev->irq = irq;
+	dev->base_addr = port;
+	
+	if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) {
+		printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc );
+		goto err_out_free;
+	}
+
+	if (priv->bus_type == BUS_TYPE_PCI &&
+	    !request_region( dev->base_addr, 64, dev->name )) {
+		goto err_out_irq;
+	}
+	
+	if (register_netdev(dev))
+		goto err_out_res;
+	
+	if (!probe_atmel_card(dev))
+		goto err_out_res;
+	
+	create_proc_read_entry ("driver/atmel", 0, 0, atmel_read_proc, priv);	
+	
+	printk(KERN_INFO "%s: Atmel at76c50x wireless. Version %d.%d simon@thekelleys.org.uk\n",
+	       dev->name, DRIVER_MAJOR, DRIVER_MINOR);
+	
+	SET_MODULE_OWNER(dev);
+	return dev;
+	
+ err_out_res:
+	if (priv->bus_type == BUS_TYPE_PCI)
+	        release_region( dev->base_addr, 64 );
+ err_out_irq:
+	free_irq(dev->irq, dev);
+ err_out_free:
+	kfree(dev);
+	return NULL;
+}
+
+EXPORT_SYMBOL(init_atmel_card);
+
+void stop_atmel_card(struct net_device *dev, int freeres)
+{
+	struct atmel_private *priv = dev->priv;
+	unregister_netdev(dev);
+	
+	/* put a brick on it... */
+
+	if (priv->bus_type == BUS_TYPE_PCCARD) 
+		atmel_write16(dev, GCR, 0x0060);
+	atmel_write16(dev, GCR, 0x0040);
+
+	remove_proc_entry("driver/atmel", NULL);
+	del_timer_sync(&priv->management_timer);
+	free_irq(dev->irq, dev);
+	if (priv->firmware)
+		kfree(priv->firmware);
+	if (freeres) {
+		/* PCMCIA frees this stuff, so only for PCI */
+	        release_region(dev->base_addr, 64);
+        }
+	kfree( dev );
+}
+
+EXPORT_SYMBOL(stop_atmel_card);
+
+static const struct {
+	int reg_domain;
+	int min, max;
+} channel_table[] = { { REG_DOMAIN_FCC, 1, 11},
+		      { REG_DOMAIN_DOC, 1, 11},
+		      { REG_DOMAIN_ETSI, 1, 13},
+		      { REG_DOMAIN_SPAIN, 10, 11},
+		      { REG_DOMAIN_FRANCE, 10, 13},
+		      { REG_DOMAIN_MKK, 14, 14},
+		      { REG_DOMAIN_MKK1, 1, 14},
+		      { REG_DOMAIN_ISRAEL, 9} };
+
+
+static int atmel_validate_channel(struct atmel_private *priv, int channel)
+{
+	/* check that channel is OK, if so return zero,
+	   else return suitable default channel */
+	int i;
+
+	for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+		if (priv->reg_domain == channel_table[i].reg_domain) {
+			if (channel >= channel_table[i].min &&
+			    channel <= channel_table[i].max)
+				return 0;
+			else
+				return channel_table[i].min;
+		}
+	return 1;
+}
+
+static int atmel_set_essid(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_point *dwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	/* Check if we asked for `any' */
+	if(dwrq->flags == 0) {
+		priv->connect_to_any_BSS = 1;
+	} else {
+		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+		priv->connect_to_any_BSS = 0;
+		
+		/* Check the size of the string */
+		if (dwrq->length > MAX_SSID_LENGTH + 1)
+			 return -E2BIG ;
+		if (index != 0)
+			return -EINVAL;
+		
+		memcpy(priv->new_SSID, extra, dwrq->length - 1);
+		priv->new_SSID_size = dwrq->length - 1;
+	}
+
+	return -EINPROGRESS;
+}
+
+static int atmel_get_essid(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_point *dwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	/* Get the current SSID */
+	if (priv->SSID_size == 0) {
+		memcpy(extra, priv->new_SSID, priv->new_SSID_size);
+		extra[priv->new_SSID_size] = '\0';
+		dwrq->length = priv->new_SSID_size + 1;
+	} else {
+		memcpy(extra, priv->SSID, priv->SSID_size);
+		extra[priv->SSID_size] = '\0';
+		dwrq->length = priv->SSID_size + 1;
+	}
+	
+	dwrq->flags = !priv->connect_to_any_BSS; /* active */
+
+	return 0;
+}
+
+static int atmel_get_wap(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct sockaddr *awrq,
+			 char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	memcpy(awrq->sa_data, priv->CurrentBSSID, 6);
+	awrq->sa_family = ARPHRD_ETHER;
+
+	return 0;
+}
+
+static int atmel_set_encode(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_point *dwrq,
+			    char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	/* Basic checking: do we have a key to set ?
+	 * Note : with the new API, it's impossible to get a NULL pointer.
+	 * Therefore, we need to check a key size == 0 instead.
+	 * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
+	 * when no key is present (only change flags), but older versions
+	 * don't do it. - Jean II */
+	if (dwrq->length > 0) {
+		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+		int current_index = priv->wep.default_key;
+		/* Check the size of the key */
+		if (dwrq->length > 13) {
+			return -EINVAL;
+		}
+		/* Check the index (none -> use current) */
+		if (index < 0 || index >= 4)
+			index = current_index;
+		else
+			priv->wep.default_key = index;
+		/* Set the length */
+		if (dwrq->length > 5)
+			priv->wep_key_len[index] = 13;
+		else
+			if (dwrq->length > 0)
+				priv->wep_key_len[index] = 5;
+			else
+				/* Disable the key */
+				priv->wep_key_len[index] = 0;
+		/* Check if the key is not marked as invalid */
+		if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
+			/* Cleanup */
+			memset(priv->wep.wep_keys[index], 0, 13);
+			/* Copy the key in the driver */
+			memcpy(priv->wep.wep_keys[index], extra, dwrq->length);
+		}
+		/* WE specify that if a valid key is set, encryption
+		 * should be enabled (user may turn it off later)
+		 * This is also how "iwconfig ethX key on" works */
+		if (index == current_index && 
+		    priv->wep_key_len[index] > 0) {
+			priv->wep.wep_is_on = 1;
+			priv->wep.exclude_unencrypted = 1;
+			if (priv->wep_key_len[index] > 5)
+				priv->wep.encryption_level = 2;
+			else
+				priv->wep.encryption_level = 1;
+		}
+	} else {
+		/* Do we want to just set the transmit key index ? */
+		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+		if ( index>=0 && index < 4 ) {
+			priv->wep.default_key = index;
+		} else
+			/* Don't complain if only change the mode */
+			if(!dwrq->flags & IW_ENCODE_MODE) {
+				return -EINVAL;
+			}
+	}
+	/* Read the flags */
+	if(dwrq->flags & IW_ENCODE_DISABLED) {
+		priv->wep.wep_is_on = 0;
+		priv->wep.encryption_level = 0; 
+	} else {
+		priv->wep.wep_is_on = 1;
+		if (priv->wep_key_len[priv->wep.default_key] > 5)
+			priv->wep.encryption_level = 2;
+		else
+			priv->wep.encryption_level = 1;
+	}
+	if(dwrq->flags & IW_ENCODE_RESTRICTED)
+		priv->wep.exclude_unencrypted = 1;
+	if(dwrq->flags & IW_ENCODE_OPEN)
+		priv->wep.exclude_unencrypted = 0;
+	
+	return -EINPROGRESS;		/* Call commit handler */
+}
+
+
+static int atmel_get_encode(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_point *dwrq,
+			    char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+	
+	if (!priv->wep.wep_is_on)
+		dwrq->flags = IW_ENCODE_DISABLED;
+	else if (priv->wep.exclude_unencrypted)
+		dwrq->flags = IW_ENCODE_RESTRICTED;
+	else
+		dwrq->flags = IW_ENCODE_OPEN;
+		
+		/* Which key do we want ? -1 -> tx index */
+	if (index < 0 || index >= 4)
+		index = priv->wep.default_key;
+	dwrq->flags |= index + 1;
+	/* Copy the key to the user buffer */
+	dwrq->length = priv->wep_key_len[index];
+	if (dwrq->length > 16) {
+		dwrq->length=0;
+	} else {
+		memset(extra, 0, 16);
+		memcpy(extra, priv->wep.wep_keys[index], dwrq->length);
+	}
+	
+	return 0;
+}
+
+static int atmel_get_name(struct net_device *dev,
+			  struct iw_request_info *info,
+			  char *cwrq,
+			  char *extra)
+{
+	strcpy(cwrq, "IEEE 802.11-DS");
+	return 0;
+}
+
+static int atmel_set_rate(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_param *vwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	
+	if (vwrq->fixed == 0) {
+		priv->tx_rate = 3;
+		priv->auto_tx_rate = 1;
+	} else {
+		priv->auto_tx_rate = 0;
+		
+		/* Which type of value ? */
+		if((vwrq->value < 4) && (vwrq->value >= 0)) {
+			/* Setting by rate index */
+		priv->tx_rate = vwrq->value;
+		} else {
+		/* Setting by frequency value */
+			switch (vwrq->value) {
+			case (int)1e6: priv->tx_rate = 0; break;
+			case (int)2e6: priv->tx_rate = 1; break;
+			case (int)5.5e6: priv->tx_rate = 2; break;
+			case (int)11e6:  priv->tx_rate = 3; break;
+			default: return -EINVAL;
+			}
+		}
+	}
+
+	return -EINPROGRESS;
+}
+
+static int atmel_set_mode(struct net_device *dev,
+			  struct iw_request_info *info,
+			  __u32 *uwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	if (*uwrq != IW_MODE_ADHOC && *uwrq != IW_MODE_INFRA)
+		return -EINVAL;
+
+	priv->operating_mode = *uwrq;
+	return -EINPROGRESS;  
+}
+
+static int atmel_get_mode(struct net_device *dev,
+			  struct iw_request_info *info,
+			  __u32 *uwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	
+	*uwrq = priv->operating_mode;
+	return 0;
+}
+
+static int atmel_get_rate(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct iw_param *vwrq,
+			 char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	if (priv->auto_tx_rate) {
+		vwrq->fixed = 0;
+		vwrq->value = 11e6;
+	} else {
+		vwrq->fixed = 1;
+		switch(priv->tx_rate) {
+		case 0: vwrq->value = 1e6; break;
+		case 1: vwrq->value = 2e6; break;
+		case 2: vwrq->value = 5.5e6; break;
+		case 3: vwrq->value = 11e6; break;
+		}
+	}
+	return 0;
+}
+
+static int atmel_set_power(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_param *vwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	priv->power_mode = vwrq->disabled ? 0 : 1;
+	return -EINPROGRESS;
+}
+
+static int atmel_get_power(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_param *vwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	vwrq->disabled = priv->power_mode ? 0 : 1;
+	vwrq->flags = IW_POWER_ON;
+	return 0;
+}
+
+static int atmel_set_retry(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_param *vwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	
+	if(!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
+		if(vwrq->flags & IW_RETRY_MAX)
+			priv->long_retry = vwrq->value;
+		else if (vwrq->flags & IW_RETRY_MIN)
+			priv->short_retry = vwrq->value;
+		else {
+			/* No modifier : set both */
+			priv->long_retry = vwrq->value;
+			priv->short_retry = vwrq->value;
+		}
+		return -EINPROGRESS;		
+	}
+	   
+	return -EINVAL;
+}
+
+static int atmel_get_retry(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_param *vwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	vwrq->disabled = 0;      /* Can't be disabled */
+
+	/* Note : by default, display the min retry number */
+	if((vwrq->flags & IW_RETRY_MAX)) {
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+		vwrq->value = priv->long_retry;
+	} else {
+		vwrq->flags = IW_RETRY_LIMIT;
+		vwrq->value = priv->short_retry;
+		if(priv->long_retry != priv->short_retry)
+			vwrq->flags |= IW_RETRY_MIN;
+	}
+
+	return 0;
+}
+
+static int atmel_set_rts(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct iw_param *vwrq,
+			 char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	int rthr = vwrq->value;
+
+	if(vwrq->disabled)
+		rthr = 2347;
+	if((rthr < 0) || (rthr > 2347)) {
+		return -EINVAL;
+	}
+	priv->rts_threshold = rthr;
+	
+	return -EINPROGRESS;		/* Call commit handler */
+}
+
+static int atmel_get_rts(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct iw_param *vwrq,
+			 char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	
+	vwrq->value = priv->rts_threshold;
+	vwrq->disabled = (vwrq->value >= 2347);
+	vwrq->fixed = 1;
+
+	return 0;
+}
+
+static int atmel_set_frag(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_param *vwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	int fthr = vwrq->value;
+
+	if(vwrq->disabled)
+		fthr = 2346;
+	if((fthr < 256) || (fthr > 2346)) {
+		return -EINVAL;
+	}
+	fthr &= ~0x1;	/* Get an even value - is it really needed ??? */
+	priv->frag_threshold = fthr;
+	
+	return -EINPROGRESS;		/* Call commit handler */
+}
+
+static int atmel_get_frag(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_param *vwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	vwrq->value = priv->frag_threshold;
+	vwrq->disabled = (vwrq->value >= 2346);
+	vwrq->fixed = 1;
+
+	return 0;
+}
+
+static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+				2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+
+static int atmel_set_freq(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_freq *fwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	int rc = -EINPROGRESS;		/* Call commit handler */
+	
+	/* If setting by frequency, convert to a channel */
+	if((fwrq->e == 1) &&
+	   (fwrq->m >= (int) 2.412e8) &&
+	   (fwrq->m <= (int) 2.487e8)) {
+		int f = fwrq->m / 100000;
+		int c = 0;
+		while((c < 14) && (f != frequency_list[c]))
+			c++;
+		/* Hack to fall through... */
+		fwrq->e = 0;
+		fwrq->m = c + 1;
+	}
+	/* Setting by channel number */
+	if((fwrq->m > 1000) || (fwrq->e > 0))
+		rc = -EOPNOTSUPP;
+	else {
+		int channel = fwrq->m;
+		if (atmel_validate_channel(priv, channel) == 0) {
+			priv->channel = channel;
+		} else {
+			rc = -EINVAL;
+		} 
+	}
+	return rc;
+}
+
+static int atmel_get_freq(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_freq *fwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	fwrq->m = priv->channel;
+	fwrq->e = 0;
+	return 0;
+}
+
+static int atmel_set_scan(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_param *vwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+
+	/* Note : you may have realised that, as this is a SET operation,
+	 * this is privileged and therefore a normal user can't
+	 * perform scanning.
+	 * This is not an error, while the device perform scanning,
+	 * traffic doesn't flow, so it's a perfect DoS...
+	 * Jean II */
+	
+	if (priv->station_state == STATION_STATE_DOWN ||
+	    priv->station_state == STATION_STATE_NO_CARD)
+		return -EAGAIN;
+
+	/* Timeout old surveys. */
+	if ((jiffies - priv->last_survey) > (20 * HZ))
+		priv->site_survey_state = SITE_SURVEY_IDLE;
+	priv->last_survey = jiffies;
+
+	/* Initiate a scan command */
+	if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
+		return -EBUSY;
+	
+	priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
+	
+	atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
+	del_timer_sync(&priv->management_timer);
+	atmel_scan(priv, 0);
+	atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+	
+	return 0;
+}
+
+static int atmel_get_scan(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_point *dwrq,
+			  char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	int i;
+	char *current_ev = extra;
+	struct iw_event	iwe;
+	
+	if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
+		return -EAGAIN;
+	
+	for(i=0; i<priv->BSS_list_entries; i++) { 
+		iwe.cmd = SIOCGIWAP;
+		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
+		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN);
+
+		iwe.u.data.length =  priv->BSSinfo[i].SSIDsize;
+		if (iwe.u.data.length > 32)
+			iwe.u.data.length = 32;
+		iwe.cmd = SIOCGIWESSID;
+		iwe.u.data.flags = 1;
+		current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
+		
+		iwe.cmd = SIOCGIWMODE;
+		iwe.u.mode = priv->BSSinfo[i].BSStype;
+		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
+	
+		iwe.cmd = SIOCGIWFREQ;
+		iwe.u.freq.m = priv->BSSinfo[i].channel;
+		iwe.u.freq.e = 0;
+		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
+		
+		iwe.cmd = SIOCGIWENCODE;
+		if (priv->BSSinfo[i].UsingWEP)
+			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+		else
+			iwe.u.data.flags = IW_ENCODE_DISABLED;
+		iwe.u.data.length = 0;
+		current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
+		
+	}
+
+	/* Length of data */
+	dwrq->length = (current_ev - extra);
+	dwrq->flags = 0;	/* todo */
+	
+	return 0;
+}
+
+static int atmel_get_range(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_point *dwrq,
+			   char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	struct iw_range *range = (struct iw_range *) extra;
+	int k,i,j;
+
+	dwrq->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(range));
+	range->min_nwid = 0x0000;
+	range->max_nwid = 0x0000;
+	range->num_channels = 0;
+	for (j = 0; j < sizeof(channel_table)/sizeof(channel_table[0]); j++)
+		if (priv->reg_domain == channel_table[j].reg_domain) {
+			range->num_channels = channel_table[j].max - channel_table[j].min + 1;
+			break;
+		}
+	if (range->num_channels != 0) {
+		for(k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
+			range->freq[k].i = i; /* List index */
+			range->freq[k].m = frequency_list[i-1] * 100000;
+			range->freq[k++].e = 1;	/* Values in table in MHz -> * 10^5 * 10 */
+		}
+		range->num_frequency = k;
+	}
+	
+	range->max_qual.qual = 100;
+	range->max_qual.level = 100;
+	range->max_qual.noise = 0;
+	range->sensitivity = 0;
+
+	range->bitrate[0] = 1e6;
+	range->bitrate[1] = 2e6;
+	range->bitrate[2] = 5.5e6;
+	range->bitrate[3] = 11e6;
+	range->num_bitrates = 4;
+
+	range->min_rts = 0;
+	range->max_rts = 2347;
+	range->min_frag = 256;
+	range->max_frag = 2346;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = 4;
+	
+	range->pmp_flags = IW_POWER_ON;
+	range->pmt_flags = IW_POWER_ON;
+	range->pm_capa = 0;
+	
+	range->we_version_source = WIRELESS_EXT;
+	range->we_version_compiled = WIRELESS_EXT;
+	range->retry_capa = IW_RETRY_LIMIT ;
+	range->retry_flags = IW_RETRY_LIMIT;
+	range->r_time_flags = 0;
+	range->min_retry = 1;
+	range->max_retry = 65535;
+	range->avg_qual.qual = 50;
+	range->avg_qual.level = 50;
+	range->avg_qual.noise = 0;
+
+	return 0;
+}
+
+static int atmel_set_wap(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct sockaddr *awrq,
+			 char *extra)
+{
+	struct atmel_private *priv = dev->priv;
+	int i;
+	static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 };
+	
+	if (awrq->sa_family != ARPHRD_ETHER)
+		return -EINVAL;
+	
+	if (memcmp(bcast, awrq->sa_data, 6) == 0) {
+		atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
+		del_timer_sync(&priv->management_timer);
+		atmel_scan(priv, 1);
+		atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+		return 0;
+	}
+	
+	for(i=0; i<priv->BSS_list_entries; i++) {
+		if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
+			if (!priv->wep.wep_is_on && priv->BSSinfo[i].UsingWEP) {
+				return -EINVAL;
+			} else if  (priv->wep.wep_is_on && !priv->BSSinfo[i].UsingWEP) {
+				return -EINVAL;
+			} else 
+				atmel_join_bss(priv, i);  
+			return 0;
+		}
+	}
+		
+	return -EINVAL;
+}
+	
+static int atmel_config_commit(struct net_device *dev,
+			       struct iw_request_info *info,	/* NULL */
+			       void *zwrq,			/* NULL */
+			       char *extra)			/* NULL */
+{
+	reset_atmel_card(dev);
+	return 0;
+}
+
+static const iw_handler		atmel_handler[] =
+{
+	(iw_handler) atmel_config_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) atmel_get_name,    	/* SIOCGIWNAME */
+	(iw_handler) NULL,			/* SIOCSIWNWID */
+	(iw_handler) NULL,			/* SIOCGIWNWID */
+	(iw_handler) atmel_set_freq,		/* SIOCSIWFREQ */
+	(iw_handler) atmel_get_freq,		/* SIOCGIWFREQ */
+	(iw_handler) atmel_set_mode,		/* SIOCSIWMODE */
+	(iw_handler) atmel_get_mode,		/* SIOCGIWMODE */
+	(iw_handler) NULL,                  	/* SIOCSIWSENS */
+	(iw_handler) NULL,           		/* SIOCGIWSENS */
+	(iw_handler) NULL,			/* SIOCSIWRANGE */
+	(iw_handler) atmel_get_range,           /* SIOCGIWRANGE */
+	(iw_handler) NULL,			/* SIOCSIWPRIV */
+	(iw_handler) NULL,			/* SIOCGIWPRIV */
+	(iw_handler) NULL,			/* SIOCSIWSTATS */
+	(iw_handler) NULL,			/* SIOCGIWSTATS */
+	(iw_handler) NULL,			/* SIOCSIWSPY */
+	(iw_handler) NULL,			/* SIOCGIWSPY */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) atmel_set_wap,		/* SIOCSIWAP */
+	(iw_handler) atmel_get_wap,		/* SIOCGIWAP */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,       		/* SIOCGIWAPLIST */
+	(iw_handler) atmel_set_scan,		/* SIOCSIWSCAN */
+	(iw_handler) atmel_get_scan,		/* SIOCGIWSCAN */
+	(iw_handler) atmel_set_essid,		/* SIOCSIWESSID */
+	(iw_handler) atmel_get_essid,		/* SIOCGIWESSID */
+	(iw_handler) NULL,         		/* SIOCSIWNICKN */
+	(iw_handler) NULL,          		/* SIOCGIWNICKN */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) atmel_set_rate,		/* SIOCSIWRATE */
+	(iw_handler) atmel_get_rate,		/* SIOCGIWRATE */
+	(iw_handler) atmel_set_rts,		/* SIOCSIWRTS */
+	(iw_handler) atmel_get_rts,		/* SIOCGIWRTS */
+	(iw_handler) atmel_set_frag,		/* SIOCSIWFRAG */
+	(iw_handler) atmel_get_frag,		/* SIOCGIWFRAG */
+	(iw_handler) NULL,         		/* SIOCSIWTXPOW */
+	(iw_handler) NULL,          		/* SIOCGIWTXPOW */
+	(iw_handler) atmel_set_retry,		/* SIOCSIWRETRY */
+	(iw_handler) atmel_get_retry,		/* SIOCGIWRETRY */
+	(iw_handler) atmel_set_encode,		/* SIOCSIWENCODE */
+	(iw_handler) atmel_get_encode,		/* SIOCGIWENCODE */
+	(iw_handler) atmel_set_power,		/* SIOCSIWPOWER */
+	(iw_handler) atmel_get_power,		/* SIOCGIWPOWER */
+};
+
+
+static const iw_handler		atmel_private_handler[] =
+{
+	NULL,				/* SIOCIWFIRSTPRIV */
+};
+
+typedef struct atmel_priv_ioctl {
+	char id[32];
+	unsigned char *data;		
+	unsigned short len;		
+} atmel_priv_ioctl;
+
+	
+#define ATMELFWL SIOCIWFIRSTPRIV
+#define ATMELIDIFC ATMELFWL + 1
+#define ATMELMAGIC 0x51807 
+
+static const struct iw_priv_args atmel_private_args[] = {
+/*{ cmd,         set_args,                            get_args, name } */
+  { ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
+  { ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
+};
+
+static const struct iw_handler_def	atmel_handler_def =
+{
+	.num_standard	= sizeof(atmel_handler)/sizeof(iw_handler),
+	.num_private	= sizeof(atmel_private_handler)/sizeof(iw_handler), 
+	.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args), 
+	.standard	= (iw_handler *) atmel_handler,
+	.private	= (iw_handler *) atmel_private_handler, 
+	.private_args	= (struct iw_priv_args *) atmel_private_args
+};
+
+static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+	struct atmel_private *priv = (struct atmel_private *) dev->priv;
+	atmel_priv_ioctl com;
+	struct iwreq *wrq = (struct iwreq *) rq;
+	unsigned char *new_firmware;
+
+	switch (cmd) {
+	case SIOCGIWPRIV:
+		if(wrq->u.data.pointer) {
+			/* Set the number of ioctl available */
+			wrq->u.data.length = sizeof(atmel_private_args) / sizeof(atmel_private_args[0]);
+			
+			/* Copy structure to the user buffer */
+			if (copy_to_user(wrq->u.data.pointer,
+					 (u_char *) atmel_private_args,
+					 sizeof(atmel_private_args)))
+				rc = -EFAULT;
+		}
+		break;
+
+	case ATMELIDIFC:
+		wrq->u.param.value = ATMELMAGIC;		
+		break;
+	
+	case ATMELFWL:
+		if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
+			rc = -EFAULT;
+			break;
+		}
+
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+
+		if (!(new_firmware = kmalloc(com.len, GFP_KERNEL))) {
+			rc = -ENOMEM;
+			break;
+		}
+		
+		if (copy_from_user(new_firmware, com.data, com.len)) {
+			rc = -EFAULT;
+			break;
+		}
+		
+		if (priv->firmware)
+			kfree(priv->firmware);
+		
+		priv->firmware = new_firmware;
+		priv->firmware_length = com.len;
+		strncpy(priv->firmware_id, com.id, 31);
+		priv->firmware_id[31] = '\0';
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+	}
+	
+	return rc;
+}
+
+struct auth_body {
+	u16 alg;
+	u16 trans_seq;
+	u16 status;
+	u8 el_id;
+	u8 chall_text_len;
+	u8 chall_text[253];
+}; 
+
+static void atmel_enter_state(struct atmel_private *priv, int new_state)
+{
+	int old_state = priv->station_state;
+
+	if (new_state == old_state)
+		return;
+
+	if (new_state == STATION_STATE_READY)
+		netif_start_queue(priv->dev);
+
+	if (old_state == STATION_STATE_READY) {
+		netif_stop_queue(priv->dev);
+		priv->last_beacon_timestamp = 0;
+	}
+
+	priv->station_state = new_state;
+
+}
+
+static void atmel_scan(struct atmel_private *priv, int specific_ssid)
+{
+	struct {
+		u8 BSSID[6];
+		u8 SSID[MAX_SSID_LENGTH];
+		u8 scan_type;
+		u8 channel;
+		u16 BSS_type;
+		u16 min_channel_time;
+		u16 max_channel_time;
+		u8 options;
+		u8 SSID_size;
+	} cmd;
+	
+	atmel_enter_state(priv, STATION_STATE_SCANNING);
+	
+	memset(cmd.BSSID, 0xff, 6);
+
+	if (priv->fast_scan) {
+		cmd.SSID_size = priv->SSID_size;
+		memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
+		cmd.min_channel_time = cpu_to_le16(10);
+		cmd.max_channel_time = cpu_to_le16(50);
+	} else {
+		priv->BSS_list_entries = 0;
+		cmd.SSID_size = 0;
+		cmd.min_channel_time = cpu_to_le16(10);
+		cmd.max_channel_time = cpu_to_le16(120);
+	}
+	
+	cmd.options = 0;
+	
+	if (!specific_ssid)
+		cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
+	
+	cmd.channel = (priv->channel & 0x7f); 
+	cmd.scan_type = SCAN_TYPE_ACTIVE;
+	cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ? 
+		BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
+	
+	atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
+}
+
+static void join(struct atmel_private *priv, int type)
+{
+	struct {
+		u8 BSSID[6];
+		u8 SSID[MAX_SSID_LENGTH];
+		u8 BSS_type; /* this is a short in a scan command - wierd */                                
+		u8 channel;
+		u16 timeout;
+		u8 SSID_size;
+		u8 reserved;
+	} cmd;
+
+	cmd.SSID_size = priv->SSID_size;
+	memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
+	memcpy(cmd.BSSID, priv->CurrentBSSID, 6);
+	cmd.channel = (priv->channel & 0x7f);
+	cmd.BSS_type = type;
+	cmd.timeout = cpu_to_le16(2000);
+
+ 	atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
+}
+
+
+static void start(struct atmel_private *priv, int type)
+{
+	struct {
+		u8 BSSID[6];
+		u8 SSID[MAX_SSID_LENGTH];
+		u8 BSS_type;                                
+		u8 channel;
+		u8 SSID_size;
+		u8 reserved[3];
+	} cmd;
+
+	cmd.SSID_size = priv->SSID_size;
+	memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
+	memcpy(cmd.BSSID, priv->BSSID, 6);
+	cmd.BSS_type = type;
+	cmd.channel = (priv->channel & 0x7f);
+
+	atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd)); 
+}
+
+static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 channel)
+{
+	int rejoin = 0;
+	int new = capability  & C80211_MGMT_CAPABILITY_ShortPreamble ? 
+		SHORT_PREAMBLE : LONG_PREAMBLE;
+
+	if (priv->preamble != new) {
+		priv->preamble = new;
+		rejoin = 1;
+		atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
+	}
+		
+	if (priv->channel != channel) {
+		priv->channel = channel;
+		rejoin = 1;
+		atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
+	}
+	
+	if (rejoin) {
+		priv->station_is_associated = 0;
+		atmel_enter_state(priv, STATION_STATE_JOINNING);
+		
+		if (priv->operating_mode == IW_MODE_INFRA)
+			join(priv, BSS_TYPE_INFRASTRUCTURE);
+		else 
+			join(priv, BSS_TYPE_AD_HOC);
+	} 
+}
+
+ 
+static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
+{
+	struct ieee802_11_hdr header;
+	struct auth_body auth;
+	
+	header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | IEEE802_11_STYPE_AUTH); 
+	header.duration_id	= cpu_to_le16(0x8000);	
+	header.seq_ctl = 0;
+	memcpy(header.addr1, priv->CurrentBSSID, 6);
+	memcpy(header.addr2, priv->dev->dev_addr, 6);
+	memcpy(header.addr3, priv->CurrentBSSID, 6);
+	
+	if (priv->wep.wep_is_on) {
+		auth.alg = C80211_MGMT_AAN_SHAREDKEY; 
+		/* no WEP for authentication frames with TrSeqNo 1 */
+		if (priv->CurrentAuthentTransactionSeqNum != 1)
+			header.frame_ctl |=  cpu_to_le16(IEEE802_11_FCTL_WEP); 
+	} else {
+		auth.alg = C80211_MGMT_AAN_OPENSYSTEM;
+	}
+
+	auth.status = 0;
+	auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
+	priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1; 
+	priv->CurrentAuthentTransactionSeqNum += 2;
+	
+	if (challenge_len != 0)	{
+		auth.el_id = 16; /* challenge_text */
+		auth.chall_text_len = challenge_len;
+		memcpy(auth.chall_text, challenge, challenge_len);
+		atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 8 + challenge_len);
+	} else {
+		atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 6);
+	}
+}
+
+static void send_association_request(struct atmel_private *priv, int is_reassoc)
+{
+	u8 *ssid_el_p;
+	int bodysize;
+	struct ieee802_11_hdr header;
+	struct ass_req_format {
+		u16 capability;
+		u16 listen_interval; 
+		u8 ap[6]; /* nothing after here directly accessible */
+		u8 ssid_el_id;
+		u8 ssid_len;
+		u8 ssid[MAX_SSID_LENGTH];
+		u8 sup_rates_el_id;
+		u8 sup_rates_len;
+		u8 rates[4];
+	} body;
+		
+	header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | 
+		(is_reassoc ? IEEE802_11_STYPE_REASSOC_REQ : IEEE802_11_STYPE_ASSOC_REQ));
+	header.duration_id = cpu_to_le16(0x8000);
+	header.seq_ctl = 0;
+
+	memcpy(header.addr1, priv->CurrentBSSID, 6); 
+	memcpy(header.addr2, priv->dev->dev_addr, 6);
+	memcpy(header.addr3, priv->CurrentBSSID, 6); 
+
+	body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
+	if (priv->wep.wep_is_on)
+		body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_Privacy);
+	if (priv->preamble == SHORT_PREAMBLE)
+		body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
+
+	body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
+	
+	/* current AP address - only in reassoc frame */
+	if (is_reassoc) {
+		memcpy(body.ap,  priv->CurrentBSSID, 6);
+		ssid_el_p = (u8 *)&body.ssid_el_id;
+		bodysize = 18 + priv->SSID_size;
+	} else {
+		ssid_el_p = (u8 *)&body.ap[0];
+		bodysize = 12 + priv->SSID_size;
+	}
+		
+	ssid_el_p[0]= C80211_MGMT_ElementID_SSID;
+	ssid_el_p[1] = priv->SSID_size;
+	memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
+	ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
+	ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
+	memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
+
+	atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
+}
+
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee802_11_hdr *header)
+{
+	if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+		return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
+	else
+		return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
+}
+
+static int retrieve_bss(struct atmel_private *priv)
+{
+	int i;
+	int max_rssi = -128;
+	int max_index = -1;
+	
+	if (priv->BSS_list_entries == 0)
+		return -1;
+			
+	if (priv->connect_to_any_BSS) {
+		/* Select a BSS with the max-RSSI but of the same type and of the same WEP mode
+		   and that it is not marked as 'bad' (i.e. we had previously failed to connect to
+		   this BSS with the settings that we currently use) */
+		priv->current_BSS = 0;
+		for(i=0; i<priv->BSS_list_entries; i++) { 
+			if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
+			    ((!priv->wep.wep_is_on && !priv->BSSinfo[i].UsingWEP) || 
+			     (priv->wep.wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
+			    !(priv->BSSinfo[i].channel & 0x80)) {
+				max_rssi = priv->BSSinfo[i].RSSI;
+				priv->current_BSS = max_index = i;
+			}
+			
+		}
+		return max_index;
+	}
+		
+	for(i=0; i<priv->BSS_list_entries; i++) {
+		if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
+		    memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
+		    priv->operating_mode == priv->BSSinfo[i].BSStype &&
+		    atmel_validate_channel(priv, priv->BSSinfo[i].channel) == 0) {
+			if (priv->BSSinfo[i].RSSI >= max_rssi) {
+				max_rssi = priv->BSSinfo[i].RSSI;
+				max_index = i;
+			}
+		}
+	}
+	return max_index;
+}
+
+
+static void store_bss_info(struct atmel_private *priv, struct ieee802_11_hdr *header,
+			   u16 capability, u16 beacon_period, u8 channel, u8 rssi, 
+			   u8 ssid_len, u8 *ssid, int is_beacon)
+{
+	u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
+	int i, index;
+		
+	for (index = -1, i = 0; i < priv->BSS_list_entries; i++) 
+		if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) 
+			index = i;
+
+        /* If we process a probe and an entry from this BSS exists 
+	   we will update the BSS entry with the info from this BSS.
+	   If we process a beacon we will only update RSSI */
+
+	if (index == -1) {
+		if (priv->BSS_list_entries == MAX_BSS_ENTRIES)
+			return;
+		index = priv->BSS_list_entries++;
+		memcpy(priv->BSSinfo[index].BSSID, bss, 6);
+		priv->BSSinfo[index].RSSI = rssi;
+	} else {
+		if (rssi > priv->BSSinfo[index].RSSI)
+			priv->BSSinfo[index].RSSI = rssi;
+		if (is_beacon)
+			return;
+	}
+
+	priv->BSSinfo[index].channel = channel;
+	priv->BSSinfo[index].beacon_period = beacon_period;
+	priv->BSSinfo[index].UsingWEP = capability & C80211_MGMT_CAPABILITY_Privacy;
+	memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len);
+	priv->BSSinfo[index].SSIDsize = ssid_len;
+
+	if (capability & C80211_MGMT_CAPABILITY_IBSS)
+		priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
+	else if (capability & C80211_MGMT_CAPABILITY_ESS)
+		priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
+	
+	priv->BSSinfo[index].preamble = capability  & C80211_MGMT_CAPABILITY_ShortPreamble ? 
+		SHORT_PREAMBLE : LONG_PREAMBLE;
+}
+
+static void authenticate(struct atmel_private *priv, u16 frame_len)
+{
+	struct auth_body *auth = (struct auth_body *)priv->rx_buf;
+	u16 status = le16_to_cpu(auth->status);
+	u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
+	
+	if (status == C80211_MGMT_SC_Success && !priv->wep.wep_is_on) { 
+		/* no WEP */
+		if (priv->station_was_associated) {
+			atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
+			send_association_request(priv, 1);
+			return;
+		} else {
+			atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
+			send_association_request(priv, 0);
+			return;
+		} 
+	}
+		
+	if (status == C80211_MGMT_SC_Success && priv->wep.wep_is_on) { 
+		/* WEP */
+		if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
+			return;
+				
+		if (trans_seq_no == 0x0002 &&
+		    auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
+			send_authentication_request(priv, auth->chall_text, auth->chall_text_len);
+			return;
+		}
+		
+		if (trans_seq_no == 0x0004) {
+			if(priv->station_was_associated) {
+				atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
+				send_association_request(priv, 1);
+				return;
+			} else {
+				atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
+				send_association_request(priv, 0);
+				return;
+			} 
+		}
+	}			
+	
+	if (status == C80211_MGMT_SC_AuthAlgNotSupported && priv->connect_to_any_BSS) {
+		int bss_index;
+		
+		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+		
+		if ((bss_index  = retrieve_bss(priv)) != -1) {
+			atmel_join_bss(priv, bss_index);
+			return;
+		}
+	}
+	
+	
+	priv->AuthenticationRequestRetryCnt = 0;
+	atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
+	priv->station_is_associated = 0;
+}
+
+static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
+{
+	struct ass_resp_format {
+		u16 capability;
+		u16 status;
+		u16 ass_id;
+		u8 el_id;
+		u8 length;
+		u8 rates[4];
+	} *ass_resp = (struct ass_resp_format *)priv->rx_buf;
+	
+       	u16 status = le16_to_cpu(ass_resp->status);
+	u16 ass_id = le16_to_cpu(ass_resp->ass_id);
+   	u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
+	
+	if (frame_len < 8 + rates_len)
+		return;
+	
+	if (status == C80211_MGMT_SC_Success) {
+		if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
+			priv->AssociationRequestRetryCnt = 0;
+		else
+			priv->ReAssociationRequestRetryCnt = 0;
+		
+		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
+		atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
+		if (priv->power_mode == 0) {
+			priv->listen_interval = 1;
+			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
+			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+		} else {
+			priv->listen_interval = 2;
+			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS,  PS_MODE);
+			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
+		}
+		
+		priv->station_is_associated = 1;
+		priv->station_was_associated = 1;
+		atmel_enter_state(priv, STATION_STATE_READY);
+		return;
+	}
+	
+	if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
+	    status != C80211_MGMT_SC_AssDeniedBSSRate &&
+	    status != C80211_MGMT_SC_SupportCapabilities &&
+	    priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
+		mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+		priv->AssociationRequestRetryCnt++;
+		send_association_request(priv, 0);
+		return;
+	}
+		
+	if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
+	    status != C80211_MGMT_SC_AssDeniedBSSRate &&
+	    status != C80211_MGMT_SC_SupportCapabilities &&
+	    priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
+		mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+		priv->ReAssociationRequestRetryCnt++;
+		send_association_request(priv, 1);
+		return;
+	}
+	
+	atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
+	priv->station_is_associated = 0;
+	
+	if(priv->connect_to_any_BSS) {
+		int bss_index;
+		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+		
+		if ((bss_index = retrieve_bss(priv)) != -1) 
+			atmel_join_bss(priv, bss_index);
+		
+	}
+}
+
+void atmel_join_bss(struct atmel_private *priv, int bss_index)
+{
+	struct bss_info *bss =  &priv->BSSinfo[bss_index];
+
+	memcpy(priv->CurrentBSSID, bss->BSSID, 6);
+	memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize);
+	
+	/* When switching to AdHoc turn OFF Power Save if needed */
+
+	if (bss->BSStype == IW_MODE_ADHOC &&
+	    priv->operating_mode != IW_MODE_ADHOC &&
+	    priv->power_mode) {
+		priv->power_mode = 0;
+		priv->listen_interval = 1;
+		atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
+		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+	}
+		
+	priv->operating_mode = bss->BSStype;
+	priv->channel = bss->channel & 0x7f; 	
+	priv->beacon_period = bss->beacon_period;
+	
+	if (priv->preamble != bss->preamble) {
+		priv->preamble = bss->preamble;
+		atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
+	}
+	
+	if (!priv->wep.wep_is_on && bss->UsingWEP) {
+		atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+		priv->station_is_associated = 0;
+		return;
+	}
+		
+	if (priv->wep.wep_is_on && !bss->UsingWEP) {
+		atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+		priv->station_is_associated = 0;
+		return;
+	}
+
+	atmel_enter_state(priv, STATION_STATE_JOINNING);
+	
+	if (priv->operating_mode == IW_MODE_INFRA)
+		join(priv, BSS_TYPE_INFRASTRUCTURE);
+	else 
+		join(priv, BSS_TYPE_AD_HOC);
+}
+
+
+static void restart_search(struct atmel_private *priv)
+{
+	int bss_index;
+	
+	if (!priv->connect_to_any_BSS) {
+		atmel_scan(priv, 1);
+	} else {
+		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+		
+		if ((bss_index = retrieve_bss(priv)) != -1) 
+			atmel_join_bss(priv, bss_index);
+		else
+			atmel_scan(priv, 0);
+		
+	} 
+}	
+
+static void smooth_rssi(struct atmel_private *priv, u8 rssi)
+{
+	u8 old = priv->wstats.qual.level;
+
+	/* 502-rmfd-revd gives max signal level as 42, by experiment.
+	   This is going to break for other hardware variants. */
+
+	rssi = rssi * 100 / 42;
+	if((rssi + old) % 2)
+		priv->wstats.qual.level =  ((rssi + old)/2) + 1;
+	else
+		priv->wstats.qual.level =  ((rssi + old)/2);		
+	
+}
+
+static void atmel_smooth_qual(struct atmel_private *priv)
+{
+	unsigned long time_diff = (jiffies - priv->last_qual)/HZ;
+	while (time_diff--) {
+		priv->last_qual += HZ;
+		priv->wstats.qual.qual = priv->wstats.qual.qual/2;
+		priv->wstats.qual.qual += 
+			priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
+		priv->beacons_this_sec = 0;
+	}
+}
+	
+/* deals with incoming managment frames. */
+static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header, 
+		      u16 frame_len, u8 rssi)
+{
+	u16 subtype;
+	
+	switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_STYPE) {
+	case C80211_SUBTYPE_MGMT_BEACON :
+	case C80211_SUBTYPE_MGMT_ProbeResponse:
+		
+		/* beacon frame has multiple variable-length fields -
+		   never let an engineer loose with a data structure design. */
+		{
+			struct beacon_format {
+				u64 timestamp;
+				u16 interval;
+				u16 capability;
+				u8 ssid_el_id;
+				u8 ssid_length;
+				/* ssid here */
+				u8 rates_el_id;
+				u8 rates_length;
+				/* rates here */
+				u8 ds_el_id;
+				u8 ds_length;
+				/* ds here */
+			} *beacon = (struct beacon_format *)priv->rx_buf;
+			
+			u8 channel, rates_length, ssid_length;
+			u64 timestamp = le64_to_cpu(beacon->timestamp);
+			u16 beacon_interval = le16_to_cpu(beacon->interval);
+			u16 capability = le16_to_cpu(beacon->capability);
+			u8 *beaconp = priv->rx_buf;
+			ssid_length = beacon->ssid_length;
+			/* this blows chunks. */
+			if (frame_len < 14 || frame_len < ssid_length + 15) 
+				return;
+			rates_length = beaconp[beacon->ssid_length + 15];
+			if (frame_len < ssid_length + rates_length + 18)
+				return;
+			if (ssid_length >  MAX_SSID_LENGTH)
+				return;
+			channel = beaconp[ssid_length + rates_length + 18];
+		       
+			if (priv->station_state == STATION_STATE_READY) {
+				smooth_rssi(priv, rssi);
+				if (is_frame_from_current_bss(priv, header)) { 
+					priv->beacons_this_sec++;
+					atmel_smooth_qual(priv);
+					if (priv->last_beacon_timestamp) {
+						/* Note truncate this to 32 bits - kernel can't divide a long long */
+						u32 beacon_delay = timestamp - priv->last_beacon_timestamp;
+						int beacons = beacon_delay / (beacon_interval * 1000);
+						if (beacons > 1)
+							priv->wstats.miss.beacon += beacons - 1;
+					}
+					priv->last_beacon_timestamp = timestamp;
+					handle_beacon_probe(priv, capability, channel);
+				}
+			}
+			
+			if (priv->station_state == STATION_STATE_SCANNING ) 
+				store_bss_info(priv, header, capability, beacon_interval, channel,
+					       rssi, ssid_length, &beacon->rates_el_id,
+					       subtype == C80211_SUBTYPE_MGMT_BEACON) ;
+		}
+		break;
+		
+	case C80211_SUBTYPE_MGMT_Authentication:
+
+		if (priv->station_state == STATION_STATE_AUTHENTICATING)
+			authenticate(priv, frame_len);
+	
+		break;
+		
+	case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
+	case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
+		
+		if (priv->station_state == STATION_STATE_ASSOCIATING || 
+		    priv->station_state == STATION_STATE_REASSOCIATING)
+			associate(priv, frame_len, subtype);
+		
+		break;
+
+	case C80211_SUBTYPE_MGMT_DISASSOSIATION:
+		if (priv->station_is_associated && 
+		    priv->operating_mode == IW_MODE_INFRA && 
+		    is_frame_from_current_bss(priv, header)) {
+			priv->station_was_associated = 0;
+			priv->station_is_associated = 0;
+			
+			atmel_enter_state(priv, STATION_STATE_JOINNING);
+			join(priv, BSS_TYPE_INFRASTRUCTURE);
+		}
+		
+		break;
+
+	case C80211_SUBTYPE_MGMT_Deauthentication:
+		if (priv->operating_mode == IW_MODE_INFRA &&
+		    is_frame_from_current_bss(priv, header)) {
+			priv->station_was_associated = 0;
+
+			atmel_enter_state(priv, STATION_STATE_JOINNING);
+			join(priv, BSS_TYPE_INFRASTRUCTURE);
+		}
+		
+		break;
+	}
+}
+
+/* run when timer expires */
+static void atmel_management_timer(u_long a)
+{
+  struct net_device *dev = (struct net_device *) a;
+  struct atmel_private *priv = (struct atmel_private *)dev->priv;
+  unsigned long flags;
+  
+  /* Check if the card has been yanked. */
+  if (priv->card && priv->present_callback && 
+      !(*priv->present_callback)(priv->card))
+	  return;
+
+  if (priv->station_state == STATION_STATE_NO_CARD)
+	  return;
+
+  spin_lock_irqsave(&priv->irqlock, flags);
+
+  switch (priv->station_state) {
+	  
+  case STATION_STATE_AUTHENTICATING:
+	  
+	  if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
+		  atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+		  priv->station_is_associated = 0;
+		  priv->AuthenticationRequestRetryCnt = 0;
+		  restart_search(priv);
+	  } else {
+		  priv->AuthenticationRequestRetryCnt++;
+		  priv->CurrentAuthentTransactionSeqNum = 0x0001;
+		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+		  send_authentication_request(priv, NULL, 0);
+	  }
+	  
+	  break;
+
+  case STATION_STATE_ASSOCIATING:
+
+	  if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+		  atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+		  priv->station_is_associated = 0;
+		  priv->AssociationRequestRetryCnt = 0;
+		  restart_search(priv);
+	  } else {
+		  priv->AssociationRequestRetryCnt++;
+		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+		  send_association_request(priv, 0);
+	  }
+
+	  break;
+		  
+  case STATION_STATE_REASSOCIATING:	
+	  
+	  if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+		  atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+		  priv->station_is_associated = 0;
+		  priv->ReAssociationRequestRetryCnt = 0;
+		  restart_search(priv);
+	  } else {
+		  priv->ReAssociationRequestRetryCnt++;
+		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+		  send_association_request(priv, 1);
+	  }
+
+	  break;
+	  
+  default:
+	  break;
+  }
+  
+  spin_unlock_irqrestore(&priv->irqlock, flags);
+}
+  
+static void atmel_command_irq(struct atmel_private *priv)
+{
+	u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
+	u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
+	int fast_scan;
+	
+	if (status == CMD_STATUS_IDLE || 
+	    status == CMD_STATUS_IN_PROGRESS)
+		return;
+
+	switch (command){
+
+	case CMD_Start:
+		if (status == CMD_STATUS_COMPLETE) {
+			priv->station_was_associated = priv->station_is_associated;
+			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
+				      (u8 *)priv->CurrentBSSID, 6);
+			atmel_enter_state(priv, STATION_STATE_READY);
+		}			
+		break;
+		
+	case CMD_Scan:
+		fast_scan = priv->fast_scan;
+		priv->fast_scan = 0;
+		
+		if (status != CMD_STATUS_COMPLETE) {
+			atmel_scan(priv, 1);
+		} else {
+			int bss_index = retrieve_bss(priv);
+			if (bss_index != -1) {
+				atmel_join_bss(priv, bss_index);
+			} else if (priv->operating_mode == IW_MODE_ADHOC && 
+				   priv->SSID_size != 0) {
+				start(priv, BSS_TYPE_AD_HOC);
+			} else {
+				priv->fast_scan = !fast_scan;
+				atmel_scan(priv, 1);
+			}
+		}
+		break;
+		
+	case CMD_SiteSurvey:
+		priv->fast_scan = 0;
+		
+		if (status != CMD_STATUS_COMPLETE)
+			return;
+		
+		priv->site_survey_state = SITE_SURVEY_COMPLETED;
+		if (priv->station_is_associated) {
+			atmel_enter_state(priv, STATION_STATE_READY);				
+		} else {
+			atmel_scan(priv, 1);
+		}
+		break;
+
+	case CMD_Join:
+		if (status == CMD_STATUS_COMPLETE) {
+			if (priv->operating_mode == IW_MODE_ADHOC) {
+				priv->station_was_associated = priv->station_is_associated;
+				atmel_enter_state(priv, STATION_STATE_READY);
+			} else {
+				priv->AuthenticationRequestRetryCnt = 0;
+				atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
+				
+				mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+				priv->CurrentAuthentTransactionSeqNum = 0x0001;
+				send_authentication_request(priv, NULL, 0);
+			}
+			return;
+		}
+		
+
+		if (priv->station_state == STATION_STATE_FORCED_JOINNING) {
+			atmel_enter_state(priv, STATION_STATE_FORCED_JOIN_FAILURE); 
+		} else {
+			atmel_scan(priv, 1);
+		}
+	}
+}
+
+static int atmel_wakeup_firmware(struct atmel_private *priv)
+{
+	struct host_info_struct *iface = &priv->host_info;
+	u16 mr1, mr3;
+	int i;
+	
+	if (priv->card_type == CARD_TYPE_SPI_FLASH)
+		atmel_set_gcr(priv->dev, GCR_REMAP);
+	
+	/* wake up on-board processor */
+	atmel_clear_gcr(priv->dev, 0x0040);
+	atmel_write16(priv->dev, BSR, BSS_SRAM);
+	
+	if (priv->card_type == CARD_TYPE_SPI_FLASH)
+		mdelay(100);
+
+	/* and wait for it */
+	for (i =  LOOP_RETRY_LIMIT; i; i--) {
+		mr1 = atmel_read16(priv->dev, MR1);
+		mr3 = atmel_read16(priv->dev, MR3);
+		
+		if (mr3 & MAC_BOOT_COMPLETE) 
+			break;
+		if (mr1 & MAC_BOOT_COMPLETE &&
+		    priv->bus_type == BUS_TYPE_PCCARD)
+			break;
+	}
+
+	if (i == 0) {
+		printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
+		return 0;
+	}
+		
+	if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
+		printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
+		priv->station_state = STATION_STATE_NO_CARD;
+		return 0;
+	}
+	
+	/* now check for completion of MAC initialization through  
+	   the FunCtrl field of the IFACE, poll MR1 to detect completion of	  
+	   MAC initialization, check completion status, set interrupt mask,  
+	   enables interrupts and calls Tx and Rx initialization functions */  
+	
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
+	
+	for (i =  LOOP_RETRY_LIMIT; i; i--) {
+		mr1 = atmel_read16(priv->dev, MR1);
+		mr3 = atmel_read16(priv->dev, MR3);
+		
+		if (mr3 & MAC_INIT_COMPLETE) 
+			break;
+		if (mr1 & MAC_INIT_COMPLETE &&
+		    priv->bus_type == BUS_TYPE_PCCARD)
+			break;
+	}
+	
+	if (i == 0) {
+		printk(KERN_ALERT "%s: MAC failed to initialise.\n", priv->dev->name);
+		return 0;
+	}
+	
+	/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
+	if ((mr3 & MAC_INIT_COMPLETE) &&
+	    !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
+		printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name);
+		return 0;
+	}
+	if ((mr1 & MAC_INIT_COMPLETE) &&
+	    !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) {
+		printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
+		return 0;
+	}
+	
+	atmel_copy_to_host(priv->dev, (unsigned char *)iface, 
+			   priv->host_info_base, sizeof(*iface));
+	
+	iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
+	iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
+	iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
+	iface->tx_desc_count = le16_to_cpu(iface->tx_desc_count);
+	iface->rx_buff_pos = le16_to_cpu(iface->rx_buff_pos);
+	iface->rx_buff_size = le16_to_cpu(iface->rx_buff_size);
+	iface->rx_desc_pos = le16_to_cpu(iface->rx_desc_pos);
+	iface->rx_desc_count = le16_to_cpu(iface->rx_desc_count);
+	iface->build_version = le16_to_cpu(iface->build_version);
+	iface->command_pos = le16_to_cpu(iface->command_pos);
+	iface->major_version = le16_to_cpu(iface->major_version);
+	iface->minor_version = le16_to_cpu(iface->minor_version);
+	iface->func_ctrl = le16_to_cpu(iface->func_ctrl);
+	iface->mac_status = le16_to_cpu(iface->mac_status);
+
+	return 1;
+}
+
+/* determine type of memory and MAC address */
+static int probe_atmel_card(struct net_device *dev)
+{
+	int rc = 0;
+	struct atmel_private *priv = dev->priv;
+	 
+	/* reset pccard */
+	if (priv->bus_type == BUS_TYPE_PCCARD) 
+		atmel_write16(dev, GCR, 0x0060);
+	
+	atmel_write16(dev, GCR, 0x0040);
+	mdelay(500);
+	
+	if (atmel_read16(dev, MR2) == 0) {
+		/* No stored firmware so load a small stub which just 
+		   tells us the MAC address */
+		int i;
+		priv->card_type = CARD_TYPE_EEPROM;
+		atmel_write16(dev, BSR, BSS_IRAM);
+		atmel_copy_to_card(dev, 0, mac_reader, sizeof(mac_reader));
+		atmel_set_gcr(dev, GCR_REMAP);
+		atmel_clear_gcr(priv->dev, 0x0040);
+		atmel_write16(dev, BSR, BSS_SRAM);
+		for (i =  LOOP_RETRY_LIMIT; i; i--) 
+			if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
+				break;
+		if (i == 0) {
+			printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
+		} else {
+			atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
+			
+			/* got address, now squash it again until the network
+			   interface is opened */
+			if (priv->bus_type == BUS_TYPE_PCCARD) 
+				atmel_write16(dev, GCR, 0x0060);
+			atmel_write16(dev, GCR, 0x0040);
+			rc = 1;
+		}
+	} else if (atmel_read16(dev, MR4) == 0) {
+		/* Mac address easy in this case. */
+		priv->card_type = CARD_TYPE_PARALLEL_FLASH;
+		atmel_write16(dev,  BSR, 1);	
+		atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
+		atmel_write16(dev,  BSR, 0x200);
+		rc = 1;
+	} else {
+		/* Standard firmware in flash, boot it up and ask
+		   for the Mac Address */
+		priv->card_type = CARD_TYPE_SPI_FLASH;
+		if (atmel_wakeup_firmware(priv)) {
+			atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
+			
+			/* got address, now squash it again until the network
+			   interface is opened */
+			if (priv->bus_type == BUS_TYPE_PCCARD) 
+				atmel_write16(dev, GCR, 0x0060);
+			atmel_write16(dev, GCR, 0x0040);
+			rc = 1;
+		}
+	}
+	
+	if (rc) {
+		if (dev->dev_addr[0] == 0xFF) {
+			u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00};
+			printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
+			memcpy(dev->dev_addr, default_mac, 6);
+		}
+		printk(KERN_INFO "%s: MAC address %x:%x:%x:%x:%x:%x\n",
+		       dev->name,
+		       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
+		
+	}
+	
+	return rc;
+}
+
+int reset_atmel_card(struct net_device *dev) 
+{
+	/* do everything necessary to wake up the hardware, including
+	   waiting for the lightning strike and throwing the knife switch....
+
+	   set all the Mib values which matter in the card to match 
+	   their settings in the atmel_private structure. Some of these
+	   can be altered on the fly, but many (WEP, infrastucture or ad-hoc)
+	   can only be changed by tearing down the world and coming back through
+	   here.
+
+	   This routine is also responsible for initialising some 
+	   hardware-specific fields in the atmel_private structure, 
+	   including a copy of the firmware's hostinfo stucture
+	   which is the route into the rest of the firmare datastructures. */
+
+	int channel;
+	struct atmel_private *priv = dev->priv;
+	u8 configuration;
+	
+	if (priv->station_state == STATION_STATE_NO_CARD ||
+	    priv->station_state == STATION_STATE_DOWN)
+		return 0;
+	
+	/* reset pccard */
+	if (priv->bus_type == BUS_TYPE_PCCARD) 
+		atmel_write16(priv->dev, GCR, 0x0060);
+		
+	/* stop card , disable interrupts */
+	atmel_write16(priv->dev, GCR, 0x0040);
+	
+	/* any scheduled timer is no longer needed and might screw things up.. */
+	del_timer_sync(&priv->management_timer);
+	if (priv->new_SSID_size) {
+		memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
+		priv->SSID_size = priv->new_SSID_size;
+		priv->new_SSID_size = 0;
+	}
+	priv->BSS_list_entries = 0;
+
+	priv->AuthenticationRequestRetryCnt = 0;
+	priv->AssociationRequestRetryCnt = 0;
+	priv->ReAssociationRequestRetryCnt = 0;
+	priv->CurrentAuthentTransactionSeqNum = 0x0001;
+	priv->ExpectedAuthentTransactionSeqNum = 0x0002;
+
+	priv->station_state = STATION_STATE_INITIALIZING;
+	priv->site_survey_state = SITE_SURVEY_IDLE;
+	priv->station_is_associated = 0;
+	
+	if (priv->card_type == CARD_TYPE_EEPROM) {
+		/* copy in firmware if needed */
+		const struct firmware *fw_entry = NULL;
+		unsigned char *fw;
+		int len = priv->firmware_length;
+		if (!(fw = priv->firmware)) { 
+			if (strlen(priv->firmware_id) == 0) {
+				printk(KERN_INFO
+				       "%s: card type is unknown: assuming at76c502 firmware is OK.\n",
+				       dev->name);
+				printk(KERN_INFO
+				       "%s: if not, use the firmware= module parameter.\n", 
+				       dev->name);
+				strcpy(priv->firmware_id, "atmel_at76c502.bin");
+			}
+			if (request_firmware(&fw_entry, priv->firmware_id, "pcmcia") != 0) {
+				printk(KERN_ALERT 
+				       "%s: firmware %s is missing, cannot start.\n", 
+				       dev->name, priv->firmware_id);
+				return 0;
+			}
+			fw = fw_entry->data;
+			len = fw_entry->size;
+		}
+		
+		if (len <= 0x6000) {
+			atmel_write16(priv->dev, BSR, BSS_IRAM);
+			atmel_copy_to_card(priv->dev, 0, fw, len);
+			atmel_set_gcr(priv->dev, GCR_REMAP);
+		} else {
+			/* Remap */ 
+			atmel_set_gcr(priv->dev, GCR_REMAP);
+			atmel_write16(priv->dev, BSR, BSS_IRAM);
+			atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
+			atmel_write16(priv->dev, BSR, 0x2ff);
+			atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000);
+		}
+
+		if (fw_entry)
+			release_firmware(fw_entry);
+	}
+
+	if (!atmel_wakeup_firmware(priv))
+		return 0;
+	
+        /* unmask all irq sources */
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
+	
+	/* int Tx system and enable Tx */
+	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
+	atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
+	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
+	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
+
+	priv->tx_desc_free = priv->host_info.tx_desc_count;		
+	priv->tx_desc_head = 0;									
+	priv->tx_desc_tail = 0;									
+	priv->tx_desc_previous = 0;
+	priv->tx_free_mem = priv->host_info.tx_buff_size;
+	priv->tx_buff_head = 0;	
+	priv->tx_buff_tail = 0;	
+		
+	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); 
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), 
+				   configuration | FUNC_CTRL_TxENABLE);
+
+	/* init Rx system and enable */
+	priv->rx_desc_head = 0;
+	
+	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); 
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), 
+				   configuration | FUNC_CTRL_RxENABLE);
+	
+	priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
+	if (priv->reg_domain != REG_DOMAIN_FCC &&
+	    priv->reg_domain != REG_DOMAIN_DOC &&
+	    priv->reg_domain != REG_DOMAIN_ETSI &&
+	    priv->reg_domain != REG_DOMAIN_SPAIN &&
+	    priv->reg_domain != REG_DOMAIN_FRANCE &&
+	    priv->reg_domain != REG_DOMAIN_MKK &&
+	    priv->reg_domain != REG_DOMAIN_MKK1 &&
+	    priv->reg_domain != REG_DOMAIN_ISRAEL) {
+		priv->reg_domain = REG_DOMAIN_MKK1;
+		printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
+	} 
+	if ((channel = atmel_validate_channel(priv, priv->channel)))
+		priv->channel = channel;
+	
+	if (!priv->is3com) {
+		if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) == 
+		    CMD_STATUS_REJECTED_RADIO_OFF) {
+			printk(KERN_INFO 
+			       "%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
+			       dev->name);
+			return 0;
+		}
+	}
+	
+	/* set up enough MIB values to run. */
+	atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
+	atmel_set_mib8(priv, Local_Mib_Type,  LOCAL_MIB_TX_PROMISCUOUS_POS,  PROM_MODE_OFF);
+	atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_RTS_THRESHOLD_POS, priv->rts_threshold);
+	atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_FRAG_THRESHOLD_POS, priv->frag_threshold);
+	atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
+	atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
+	atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
+	atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS, 
+		      priv->dev->dev_addr, 6);
+	atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+	atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+	atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_BEACON_PER_POS, priv->default_beacon_period);
+	atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, atmel_basic_rates, 4);
+	atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep.wep_is_on);
+	atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&priv->wep, sizeof(priv->wep));
+		
+	atmel_scan(priv, 1);
+	
+	atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
+	
+	return 1;
+}
+
+EXPORT_SYMBOL(reset_atmel_card); 
+
+static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+{
+	if (cmd)
+		atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET), 
+				   cmd, cmd_size);
+	
+	atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
+	atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
+}
+	
+static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+{
+	int i, status;
+	
+	atmel_send_command(priv, command, cmd, cmd_size);
+
+	for (i = LOOP_RETRY_LIMIT; i; i--) {
+		status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
+		if (status != CMD_STATUS_IDLE && 
+		    status != CMD_STATUS_IN_PROGRESS)
+			break;
+	}
+
+	if (i == 0) {
+		printk(KERN_ALERT "%s: command %d failed to complete.\n", priv->dev->name, command);
+		status =  CMD_STATUS_HOST_ERROR;
+	} else { 
+		if (command != CMD_EnableRadio)
+			status = CMD_STATUS_COMPLETE;
+	}
+	
+	return status;
+}
+
+static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index)
+{
+	struct get_set_mib m;
+	m.type = type;
+	m.size = 1;
+	m.index = index;
+
+	atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, sizeof(m));
+	return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + 4));
+}
+
+static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data)
+{
+	struct get_set_mib m;
+	m.type = type;
+	m.size = 1;
+	m.index = index;
+	m.data[0] = data;
+
+	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
+}
+
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data)
+{
+	struct get_set_mib m;
+	m.type = type;
+	m.size = 2;
+	m.index = index;
+	m.data[0] = data;
+	m.data[1] = data >> 8;
+
+	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
+}
+
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+{
+	struct get_set_mib m;
+	m.type = type;
+	m.size = data_len;
+	m.index = index;
+
+	memcpy(m.data, data, data_len);
+	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
+}
+
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+{
+	struct get_set_mib m;
+	m.type = type;
+	m.size = data_len;
+	m.index = index;
+	
+	atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, sizeof(m));
+	atmel_copy_to_host(priv->dev, data, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + 4), data_len);
+}
+	
+static void atmel_writeAR(struct net_device *dev, u16 data)
+{
+	int i;
+	outw(data, dev->base_addr + AR);
+	/* Address register appears to need some convincing..... */
+	for (i = 0; data != inw(dev->base_addr + AR) && i<10; i++)
+		outw(data, dev->base_addr + AR);
+}
+
+static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len)
+{
+	int i;
+	atmel_writeAR(dev, dest);
+	if (dest % 2) {
+		atmel_write8(dev, DR, *src);
+		src++; len--;
+	}
+	for (i = len; i > 1 ; i -= 2) {
+		u8 lb = *src++;
+		u8 hb = *src++;
+		atmel_write16(dev, DR, lb | (hb << 8));
+	}
+	if (i)
+		atmel_write8(dev, DR, *src);
+}
+
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len)
+{
+	int i;
+	atmel_writeAR(dev, src);
+	if (src % 2) {
+		*dest = atmel_read8(dev, DR);
+		dest++; len--;
+	}
+	for (i = len; i > 1 ; i -= 2) {
+		u16 hw = atmel_read16(dev, DR);
+		*dest++ = hw;
+		*dest++ = hw >> 8;
+	}
+	if (i)
+		*dest = atmel_read8(dev, DR);
+}
+
+static void atmel_set_gcr(struct net_device *dev, u16 mask)
+{
+	outw(inw(dev->base_addr + GCR) | mask, dev->base_addr + GCR);
+}
+
+static void atmel_clear_gcr(struct net_device *dev, u16 mask)
+{
+	outw(inw(dev->base_addr + GCR) & ~mask, dev->base_addr + GCR);
+}
+
+static int atmel_lock_mac(struct atmel_private *priv)
+{
+	int i, j = 100;
+ retry:
+	for (i = LOOP_RETRY_LIMIT ; atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)) && i ; i--);
+	
+	if (!i) return 0; /* timed out */
+	
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
+	if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
+		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+		if (!j--) return 0; /* timed out */
+		goto retry;
+	}
+	
+	return 1;
+}
+
+static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
+{
+       	atmel_writeAR(priv->dev, pos);	
+	atmel_write16(priv->dev, DR, data); /* card is little-endian */
+	atmel_write16(priv->dev, DR, data >> 16);
+}
+
+
+/***************************************************************************/
+/* There follows the source form of the MAC address reading firmware       */
+/***************************************************************************/
+#if 0
+
+/* Copyright 2003 Matthew T. Russotto                                      */
+/* But derived from the Atmel 76C502 firmware written by Atmel and         */
+/* included in "atmel wireless lan drivers" package                        */
+/**
+    This file is part of net.russotto.AtmelMACFW, hereto referred to
+    as AtmelMACFW
+
+    AtmelMACFW is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2
+    as published by the Free Software Foundation.
+
+    AtmelMACFW is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with AtmelMACFW; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+****************************************************************************/
+/* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E        */
+/* It will probably work on the 76C504 and 76C502 RFMD_3COM                */
+/* It only works on SPI EEPROM versions of the card.                       */
+
+/* This firmware initializes the SPI controller and clock, reads the MAC   */
+/* address from the EEPROM into SRAM, and puts the SRAM offset of the MAC  */
+/* address in MR2, and sets MR3 to 0x10 to indicate it is done             */
+/* It also puts a complete copy of the EEPROM in SRAM with the offset in   */
+/* MR4, for investigational purposes (maybe we can determine chip type     */
+/* from that?)                                                             */
+
+	.org 0
+    .set MRBASE, 0x8000000
+	.set CPSR_INITIAL, 0xD3 /* IRQ/FIQ disabled, ARM mode, Supervisor state */
+	.set CPSR_USER, 0xD1 /* IRQ/FIQ disabled, ARM mode, USER state */
+	.set SRAM_BASE,  0x02000000
+	.set SP_BASE,    0x0F300000
+	.set UNK_BASE,   0x0F000000 /* Some internal device, but which one? */
+	.set SPI_CGEN_BASE,  0x0E000000 /* Some internal device, but which one? */
+	.set UNK3_BASE,  0x02014000 /* Some internal device, but which one? */
+	.set STACK_BASE, 0x5600
+	.set SP_SR, 0x10
+	.set SP_TDRE, 2 /* status register bit -- TDR empty */
+	.set SP_RDRF, 1 /* status register bit -- RDR full */
+	.set SP_SWRST, 0x80
+	.set SP_SPIEN, 0x1
+	.set SP_CR, 0   /* control register */
+	.set SP_MR, 4   /* mode register */
+	.set SP_RDR, 0x08 /* Read Data Register */
+	.set SP_TDR, 0x0C /* Transmit Data Register */
+	.set SP_CSR0, 0x30 /* chip select registers */
+	.set SP_CSR1, 0x34
+	.set SP_CSR2, 0x38
+	.set SP_CSR3, 0x3C
+	.set NVRAM_CMD_RDSR, 5 /* read status register */
+	.set NVRAM_CMD_READ, 3 /* read data */
+	.set NVRAM_SR_RDY, 1 /* RDY bit.  This bit is inverted */
+	.set SPI_8CLOCKS, 0xFF /* Writing this to the TDR doesn't do anything to the
+				  serial output, since SO is normally high.  But it
+				  does cause 8 clock cycles and thus 8 bits to be
+				  clocked in to the chip.  See Atmel's SPI
+				  controller (e.g. AT91M55800) timing and 4K 
+				  SPI EEPROM manuals */
+				 
+	.set NVRAM_SCRATCH, 0x02000100  /* arbitrary area for scratchpad memory */
+	.set NVRAM_IMAGE, 0x02000200
+	.set NVRAM_LENGTH, 0x0200
+	.set MAC_ADDRESS_MIB, SRAM_BASE
+	.set MAC_ADDRESS_LENGTH, 6
+        .set MAC_BOOT_FLAG, 0x10
+	.set MR1, 0
+	.set MR2, 4
+	.set MR3, 8
+	.set MR4, 0xC
+RESET_VECTOR:
+        b RESET_HANDLER
+UNDEF_VECTOR:  
+        b HALT1
+SWI_VECTOR:            
+        b HALT1
+IABORT_VECTOR: 
+        b HALT1
+DABORT_VECTOR:         
+RESERVED_VECTOR:    
+        b HALT1
+IRQ_VECTOR:    
+        b HALT1
+FIQ_VECTOR:    
+	b HALT1
+HALT1:	b HALT1
+RESET_HANDLER:
+	mov     r0, #CPSR_INITIAL
+	msr	CPSR_c, r0	/* This is probably unnecessary */
+			
+/* I'm guessing this is initializing clock generator electronics for SPI */
+	ldr	r0, =SPI_CGEN_BASE
+	mov	r1, #0
+	mov	r1, r1, lsl #3
+	orr	r1,r1, #0
+	str	r1, [r0]
+	ldr	r1, [r0, #28]
+	bic	r1, r1, #16
+	str	r1, [r0, #28]
+	mov	r1, #1
+	str	r1, [r0, #8]
+	
+	ldr	r0, =MRBASE
+	mov	r1, #0
+	strh	r1, [r0, #MR1]
+	strh	r1, [r0, #MR2]
+	strh	r1, [r0, #MR3]
+	strh	r1, [r0, #MR4]
+
+	mov	sp, #STACK_BASE
+	bl	SP_INIT
+	mov	r0, #10
+	bl	DELAY9
+	bl	GET_MAC_ADDR
+	bl	GET_WHOLE_NVRAM
+	ldr	r0, =MRBASE
+	ldr	r1, =MAC_ADDRESS_MIB
+	strh	r1, [r0, #MR2]
+	ldr	r1, =NVRAM_IMAGE
+	strh	r1, [r0, #MR4]
+	mov	r1, #MAC_BOOT_FLAG
+	strh	r1, [r0, #MR3]
+HALT2:	b HALT2
+.func Get_Whole_NVRAM, GET_WHOLE_NVRAM
+GET_WHOLE_NVRAM:
+	stmdb	sp!, {lr}
+	mov	r2, #0 /* 0th bytes of NVRAM */
+	mov	r3, #NVRAM_LENGTH
+	mov	r1, #0		/* not used in routine */
+	ldr	r0, =NVRAM_IMAGE
+	bl	NVRAM_XFER
+	ldmia	sp!, {lr}
+	bx	lr
+.endfunc
+	
+.func Get_MAC_Addr, GET_MAC_ADDR
+GET_MAC_ADDR:
+	stmdb	sp!, {lr}
+	mov	r2, #0x120	/* address of MAC Address within NVRAM */
+	mov	r3, #MAC_ADDRESS_LENGTH
+	mov	r1, #0		/* not used in routine */
+	ldr	r0, =MAC_ADDRESS_MIB
+	bl	NVRAM_XFER
+	ldmia	sp!, {lr}
+	bx	lr
+.endfunc
+.ltorg
+.func Delay9, DELAY9
+DELAY9:
+	adds	r0, r0, r0, LSL #3   /* r0 = r0 * 9 */
+DELAYLOOP:	
+	beq	DELAY9_done
+	subs	r0, r0, #1
+	b	DELAYLOOP
+DELAY9_done:	
+	bx	lr
+.endfunc	
+
+.func SP_Init, SP_INIT
+SP_INIT:
+	mov	r1, #SP_SWRST
+	ldr	r0, =SP_BASE
+	str	r1, [r0, #SP_CR] /* reset the SPI */
+	mov	r1, #0
+	str	r1, [r0, #SP_CR] /* release SPI from reset state */
+	mov	r1, #SP_SPIEN
+	str	r1, [r0, #SP_MR] /* set the SPI to MASTER mode*/
+	str	r1, [r0, #SP_CR] /* enable the SPI */
+
+/*  My guess would be this turns on the SPI clock */
+	ldr	r3, =SPI_CGEN_BASE
+	ldr	r1, [r3, #28]
+	orr	r1, r1, #0x2000
+	str	r1, [r3, #28]
+
+	ldr	r1, =0x2000c01
+	str	r1, [r0, #SP_CSR0]
+	ldr	r1, =0x2000201
+	str	r1, [r0, #SP_CSR1]
+	str	r1, [r0, #SP_CSR2]
+	str	r1, [r0, #SP_CSR3]
+	ldr	r1, [r0, #SP_SR]
+	ldr	r0, [r0, #SP_RDR]
+	bx	lr
+.endfunc
+.func NVRAM_Init, NVRAM_INIT	
+NVRAM_INIT:
+	ldr	r1, =SP_BASE
+	ldr	r0, [r1, #SP_RDR]
+	mov	r0, #NVRAM_CMD_RDSR
+	str	r0, [r1, #SP_TDR]
+SP_loop1:	
+	ldr	r0, [r1, #SP_SR]
+	tst	r0, #SP_TDRE
+	beq	SP_loop1
+
+	mov	r0, #SPI_8CLOCKS
+	str	r0, [r1, #SP_TDR] 
+SP_loop2:	
+	ldr	r0, [r1, #SP_SR]
+	tst	r0, #SP_TDRE
+	beq	SP_loop2
+
+	ldr	r0, [r1, #SP_RDR]
+SP_loop3:	
+	ldr	r0, [r1, #SP_SR]
+	tst	r0, #SP_RDRF
+	beq	SP_loop3
+
+	ldr	r0, [r1, #SP_RDR]
+	and	r0, r0, #255
+	bx	lr
+.endfunc
+	
+.func NVRAM_Xfer, NVRAM_XFER
+	/* r0 = dest address */
+	/* r1 = not used */
+	/* r2 = src address within NVRAM */
+	/* r3 = length */
+NVRAM_XFER:
+	stmdb	sp!, {r4, r5, lr}
+	mov	r5, r0		/* save r0 (dest address) */
+	mov	r4, r3		/* save r3 (length) */
+	mov	r0, r2, LSR #5 /*  SPI memories put A8 in the command field */
+	and	r0, r0, #8
+	add	r0, r0, #NVRAM_CMD_READ 
+	ldr	r1, =NVRAM_SCRATCH
+	strb	r0, [r1, #0]	/* save command in NVRAM_SCRATCH[0] */
+	strb	r2, [r1, #1]    /* save low byte of source address in NVRAM_SCRATCH[1] */
+_local1:	
+	bl	NVRAM_INIT
+	tst	r0, #NVRAM_SR_RDY
+	bne	_local1
+	mov	r0, #20
+	bl	DELAY9
+	mov	r2, r4		/* length */
+	mov	r1, r5		/* dest address */
+	mov	r0, #2		/* bytes to transfer in command */
+	bl	NVRAM_XFER2
+	ldmia	sp!, {r4, r5, lr}
+	bx	lr
+.endfunc
+
+.func NVRAM_Xfer2, NVRAM_XFER2
+NVRAM_XFER2:
+	stmdb	sp!, {r4, r5, r6, lr}
+	ldr	r4, =SP_BASE
+	mov	r3, #0
+	cmp	r0, #0
+	bls	_local2
+	ldr	r5, =NVRAM_SCRATCH
+_local4:	
+	ldrb	r6, [r5, r3]
+	str	r6, [r4, #SP_TDR]
+_local3:
+	ldr	r6, [r4, #SP_SR]
+	tst	r6, #SP_TDRE
+	beq	_local3
+	add	r3, r3, #1
+	cmp	r3, r0 /* r0 is # of bytes to send out (command+addr) */
+	blo	_local4
+_local2:
+	mov	r3, #SPI_8CLOCKS
+	str	r3, [r4, #SP_TDR]
+	ldr	r0, [r4, #SP_RDR]
+_local5:	
+	ldr	r0, [r4, #SP_SR]
+	tst	r0, #SP_RDRF
+	beq	_local5
+	ldr	r0, [r4, #SP_RDR] /* what's this byte?  It's the byte read while writing the TDR -- nonsense, because the NVRAM doesn't read and write at the same time */
+	mov	r0, #0
+	cmp	r2, #0  /* r2 is # of bytes to copy in */
+	bls	_local6
+_local7:	
+	ldr	r5, [r4, #SP_SR]
+	tst	r5, #SP_TDRE
+	beq	_local7
+	str	r3, [r4, #SP_TDR]  /* r3 has SPI_8CLOCKS */
+_local8:	
+	ldr	r5, [r4, #SP_SR]
+	tst	r5, #SP_RDRF
+	beq	_local8
+	ldr	r5, [r4, #SP_RDR] /* but didn't we read this byte above? */
+	strb	r5, [r1], #1 /* postindexed */
+	add	r0, r0, #1
+	cmp	r0, r2
+	blo	_local7 /* since we don't send another address, the NVRAM must be capable of sequential reads */
+_local6:
+	mov	r0, #200
+	bl	DELAY9
+	ldmia	sp!, {r4, r5, r6, lr}
+	bx	lr
+#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/wireless/atmel_cs.c linux-2.4.26-pre6/drivers/net/wireless/atmel_cs.c
--- linux-2.4.25/drivers/net/wireless/atmel_cs.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/drivers/net/wireless/atmel_cs.c	2004-03-25 00:19:22.000000000 +0000
@@ -0,0 +1,733 @@
+/*** -*- linux-c -*- **********************************************************
+
+     Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+        Copyright 2000-2001 ATMEL Corporation.
+        Copyright 2003 Simon Kelley.
+
+    This code was developed from version 2.1.1 of the Atmel drivers, 
+    released by Atmel corp. under the GPL in December 2002. It also 
+    includes code from the Linux aironet drivers (C) Benjamin Reed, 
+    and the Linux PCMCIA package, (C) David Hinds. 
+
+    For all queries about this code, please contact the current author, 
+    Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This software is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Atmel wireless lan drivers; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+******************************************************************************/
+
+#include <linux/config.h>
+#ifdef __IN_PCMCIA_PACKAGE__
+#include <pcmcia/k_compat.h>
+#endif
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/ciscode.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/wireless.h>
+#include <linux/802_11.h>
+
+
+/*
+   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
+   you do not define PCMCIA_DEBUG at all, all the debug code will be
+   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
+   be present but disabled -- but it can then be enabled for specific
+   modules at load time with a 'pc_debug=#' option to insmod.
+*/
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+static char *version = "$Revision: 1.2 $";
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* The old way: bit map of interrupts to choose from */
+/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
+static u_int irq_mask = 0xdeb8;
+/* Newer, simpler way of listing specific interrupts */
+static int irq_list[4] = { -1 };
+
+MODULE_AUTHOR("Simon Kelley");
+MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+
+/*====================================================================*/
+
+/*
+   The event() function is this driver's Card Services event handler.
+   It will be called by Card Services when an appropriate card status
+   event is received.  The config() and release() entry points are
+   used to configure or release a socket, in response to card
+   insertion and ejection events.  They are invoked from the atmel_cs
+   event handler. 
+*/
+
+struct net_device *init_atmel_card(int, int, char *, int,
+				    int (*present_func)(void *), void * );
+void stop_atmel_card( struct net_device *, int );
+int reset_atmel_card( struct net_device * );
+
+static void atmel_config(dev_link_t *link);
+static void atmel_release(dev_link_t *link);
+static int atmel_event(event_t event, int priority,
+		       event_callback_args_t *args);
+
+/*
+   The attach() and detach() entry points are used to create and destroy
+   "instances" of the driver, where each instance represents everything
+   needed to manage one actual PCMCIA card.
+*/
+
+static dev_link_t *atmel_attach(void);
+static void atmel_detach(dev_link_t *);
+
+/*
+   You'll also need to prototype all the functions that will actually
+   be used to talk to your device.  See 'pcmem_cs' for a good example
+   of a fully self-sufficient driver; the other drivers rely more or
+   less on other parts of the kernel.
+*/
+
+/*
+   The dev_info variable is the "key" that is used to match up this
+   device driver with appropriate cards, through the card configuration
+   database.
+*/
+
+static dev_info_t dev_info = "atmel_cs";
+
+/*
+   A linked list of "instances" of the  atmelnet device.  Each actual
+   PCMCIA card corresponds to one device instance, and is described
+   by one dev_link_t structure (defined in ds.h).
+
+   You may not want to use a linked list for this -- for example, the
+   memory card driver uses an array of dev_link_t pointers, where minor
+   device numbers are used to derive the corresponding array index.
+*/
+
+static dev_link_t *dev_list = NULL;
+
+/*
+   A dev_link_t structure has fields for most things that are needed
+   to keep track of a socket, but there will usually be some device
+   specific information that also needs to be kept track of.  The
+   'priv' pointer in a dev_link_t structure can be used to point to
+   a device-specific private data structure, like this.
+
+   A driver needs to provide a dev_node_t structure for each device
+   on a card.  In some cases, there is only one device per card (for
+   example, ethernet cards, modems).  In other cases, there may be
+   many actual or logical devices (SCSI adapters, memory cards with
+   multiple partitions).  The dev_node_t structures need to be kept
+   in a linked list starting at the 'dev' field of a dev_link_t
+   structure.  We allocate them in the card's private data structure,
+   because they generally shouldn't be allocated dynamically.
+
+   In this case, we also provide a flag to indicate if a device is
+   "stopped" due to a power management event, or card ejection.  The
+   device IO routines can use a flag like this to throttle IO to a
+   card that is not ready to accept it.
+*/
+   
+typedef struct local_info_t {
+	dev_node_t	node;
+	struct net_device *eth_dev;
+} local_info_t;
+
+/*====================================================================*/
+
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+	error_info_t err = { func, ret };
+	CardServices(ReportError, handle, &err);
+}
+
+/*======================================================================
+  
+  atmel_attach() creates an "instance" of the driver, allocating
+  local data structures for one device.  The device is registered
+  with Card Services.
+  
+  The dev_link structure is initialized, but we don't actually
+  configure the card at this point -- we wait until we receive a
+  card insertion event.
+  
+  ======================================================================*/
+
+static dev_link_t *atmel_attach(void)
+{
+	client_reg_t client_reg;
+	dev_link_t *link;
+	local_info_t *local;
+	int ret, i;
+	
+	DEBUG(0, "atmel_attach()\n");
+
+	/* Initialize the dev_link_t structure */
+	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+	if (!link) {
+		printk(KERN_ERR "atmel_cs: no memory for new device\n");
+		return NULL;
+	}
+	memset(link, 0, sizeof(struct dev_link_t));
+	
+	/* Interrupt setup */
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+	link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
+	if (irq_list[0] == -1)
+		link->irq.IRQInfo2 = irq_mask;
+	else
+		for (i = 0; i < 4; i++)
+			link->irq.IRQInfo2 |= 1 << irq_list[i];
+	link->irq.Handler = NULL;
+	
+	/*
+	  General socket configuration defaults can go here.  In this
+	  client, we assume very little, and rely on the CIS for almost
+	  everything.  In most clients, many details (i.e., number, sizes,
+	  and attributes of IO windows) are fixed by the nature of the
+	  device, and can be hard-wired here.
+	*/
+	link->conf.Attributes = 0;
+	link->conf.Vcc = 50;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+	
+	/* Allocate space for private device-specific data */
+	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+	if (!local) {
+		printk(KERN_ERR "atmel_cs: no memory for new device\n");
+		kfree (link);
+		return NULL;
+	}
+	memset(local, 0, sizeof(local_info_t));
+	link->priv = local;
+	
+	/* Register with Card Services */
+	link->next = dev_list;
+	dev_list = link;
+	client_reg.dev_info = &dev_info;
+	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+	client_reg.EventMask =
+		CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+		CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+		CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+	client_reg.event_handler = &atmel_event;
+	client_reg.Version = 0x0210;
+	client_reg.event_callback_args.client_data = link;
+	ret = CardServices(RegisterClient, &link->handle, &client_reg);
+	if (ret != 0) {
+		cs_error(link->handle, RegisterClient, ret);
+		atmel_detach(link);
+		return NULL;
+	}
+	
+	return link;
+} /* atmel_attach */
+
+/*======================================================================
+  
+  This deletes a driver "instance".  The device is de-registered
+  with Card Services.  If it has been released, all local data
+  structures are freed.  Otherwise, the structures will be freed
+  when the device is released.
+  
+  ======================================================================*/
+
+static void atmel_detach(dev_link_t *link)
+{
+	dev_link_t **linkp;
+	
+	DEBUG(0, "atmel_detach(0x%p)\n", link);
+	
+	/* Locate device structure */
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link) break;
+	if (*linkp == NULL)
+		return;
+
+	if (link->state & DEV_CONFIG)
+		atmel_release(link);
+		
+	/* Break the link with Card Services */
+	if (link->handle)
+		CardServices(DeregisterClient, link->handle);
+
+	/* Unlink device structure, free pieces */
+	*linkp = link->next;
+	if (link->priv)
+		kfree(link->priv);
+	kfree(link);
+}
+
+/*======================================================================
+  
+  atmel_config() is scheduled to run after a CARD_INSERTION event
+  is received, to configure the PCMCIA socket, and to make the
+  device available to the system.
+  
+  ======================================================================*/
+
+#define CS_CHECK(fn, args...) \
+while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
+
+#define CFG_CHECK(fn, args...) \
+if (CardServices(fn, args) != 0) goto next_entry
+
+/* Call-back function to interrogate PCMCIA-specific information
+   about the current existance of the card */
+static int card_present(void *arg)
+{ 
+	dev_link_t *link = (dev_link_t *)arg;
+	if (link->state & DEV_SUSPEND)
+		return 0;
+	else if (link->state & DEV_PRESENT)
+		return 1;
+	
+	return 0;
+}
+
+/* list of cards we know about and their firmware requirements.
+   Go either by Manfid or version strings.
+   Cards not in this list will need a firmware parameter to the module
+   in all probability. Note that the SMC 2632 V2 and V3 have the same
+   manfids, so we ignore those and use the version1 strings. */
+
+static struct { 
+	int manf, card;
+	char *ver1;
+	char *firmware;
+	char *name;
+} card_table[] = {
+	{ 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d.bin", "Actiontec 802CAT1" },  
+	{ 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502.bin", "NoName-RFMD" }, 
+	{ 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d.bin", "NoName-revD" }, 
+	{ 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e.bin", "NoName-revE" },
+	{ 0, 0, "ATMEL/AT76C504", "atmel_at76c504.bin", "NoName-504" },
+	{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com.bin", "3com 3CRWE62092B" }, 
+	{ MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com.bin", "3com 3CRSHPW_96" }, 
+	{ 0, 0, "SMC/2632W-V2", "atmel_at76c502.bin", "SMC 2632W-V2" },
+        { 0, 0, "SMC/2632W", "atmel_at76c502d.bin", "SMC 2632W-V3" },
+	{ 0xd601, 0x0007, NULL, "atmel_at76c502.bin", "Sitecom WLAN-011"}, /* suspect - from a usenet posting. */
+	{ 0x01bf, 0x3302, NULL, "atmel_at76c502d.bin", "Belkin F5D6060u"},  /*    "        "  "    "      "     */
+	{ 0, 0, "BT/Voyager 1020 Laptop Adapter", "atmel_at76c502.bin", "BT Voyager 1020"},
+        { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", "atmel_at76c502.bin", "Siemens Gigaset PC Card II" },
+	{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", "atmel_at76c502e.bin", "CNet CNWLC-811ARL" }
+};
+
+static void atmel_config(dev_link_t *link)
+{
+	client_handle_t handle;
+	tuple_t tuple;
+	cisparse_t parse;
+	local_info_t *dev;
+	int last_fn, last_ret;
+	u_char buf[64];
+	int card_index = -1, done = 0;
+	
+	handle = link->handle;
+	dev = link->priv;
+
+	DEBUG(0, "atmel_config(0x%p)\n", link);
+	
+	tuple.Attributes = 0;
+	tuple.TupleData = buf;
+	tuple.TupleDataMax = sizeof(buf);
+	tuple.TupleOffset = 0;
+	
+	tuple.DesiredTuple = CISTPL_MANFID;
+	if (CardServices(GetFirstTuple, handle, &tuple) == 0) {
+		int i;
+		cistpl_manfid_t *manfid;
+		CS_CHECK(GetTupleData, handle, &tuple);
+		CS_CHECK(ParseTuple, handle, &tuple, &parse);
+		manfid = &(parse.manfid);
+		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
+			if (!card_table[i].ver1 &&
+			    manfid->manf == card_table[i].manf &&
+			    manfid->card == card_table[i].card) {
+				card_index = i;
+				done = 1;
+			}
+		}
+	}
+
+	tuple.DesiredTuple = CISTPL_VERS_1;
+	if (!done && (CardServices(GetFirstTuple, handle, &tuple) == 0)) {
+		int i, j, k;
+		cistpl_vers_1_t *ver1;
+		CS_CHECK(GetTupleData, handle, &tuple);
+		CS_CHECK(ParseTuple, handle, &tuple, &parse);
+		ver1 = &(parse.version_1);
+		
+		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
+			for (j = 0; j < ver1->ns; j++) {
+				char *p = card_table[i].ver1;
+				char *q = &ver1->str[ver1->ofs[j]];
+				if (!p)
+					goto mismatch;
+				for (k = 0; k < j; k++) {
+					while ((*p != '\0') && (*p != '/')) p++;
+					if (*p == '\0') {
+					  if (*q != '\0')
+						goto mismatch;
+					} else
+					  p++;
+				}
+				while((*q != '\0') && (*p != '\0') && 
+				      (*p != '/') && (*p == *q)) p++, q++;
+				if (((*p != '\0') && *p != '/') || *q != '\0')
+					goto mismatch;
+			}
+			card_index = i;
+			break;	/* done */
+			
+		mismatch:
+			j = 0; /* dummy stmt to shut up compiler */
+		}
+	}		
+
+	/*
+	  This reads the card's CONFIG tuple to find its configuration
+	  registers.
+	*/
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	CS_CHECK(GetTupleData, handle, &tuple);
+	CS_CHECK(ParseTuple, handle, &tuple, &parse);
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+	
+	/* Configure card */
+	link->state |= DEV_CONFIG;
+	
+	/*
+	  In this loop, we scan the CIS for configuration table entries,
+	  each of which describes a valid card configuration, including
+	  voltage, IO window, memory window, and interrupt settings.
+	  
+	  We make no assumptions about the card to be configured: we use
+	  just the information available in the CIS.  In an ideal world,
+	  this would work for any PCMCIA card, but it requires a complete
+	  and accurate CIS.  In practice, a driver usually "knows" most of
+	  these things without consulting the CIS, and most client drivers
+	  will only use the CIS to fill in implementation-defined details.
+	*/
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	while (1) {
+		cistpl_cftable_entry_t dflt = { 0 };
+		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+		CFG_CHECK(GetTupleData, handle, &tuple);
+		CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+		
+		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
+		if (cfg->index == 0) goto next_entry;
+		link->conf.ConfigIndex = cfg->index;
+		
+		/* Does this card need audio output? */
+		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+			link->conf.Attributes |= CONF_ENABLE_SPKR;
+			link->conf.Status = CCSR_AUDIO_ENA;
+		}
+		
+		/* Use power settings for Vcc and Vpp if present */
+		/*  Note that the CIS values need to be rescaled */
+		if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
+		else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
+		
+		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 =
+				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 =
+				dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
+		
+		/* Do we need to allocate an interrupt? */
+		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
+			link->conf.Attributes |= CONF_ENABLE_IRQ;
+		
+		/* IO window settings */
+		link->io.NumPorts1 = link->io.NumPorts2 = 0;
+		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+			if (!(io->flags & CISTPL_IO_8BIT))
+				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+			if (!(io->flags & CISTPL_IO_16BIT))
+				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+			link->io.BasePort1 = io->win[0].base;
+			link->io.NumPorts1 = io->win[0].len;
+			if (io->nwin > 1) {
+				link->io.Attributes2 = link->io.Attributes1;
+				link->io.BasePort2 = io->win[1].base;
+				link->io.NumPorts2 = io->win[1].len;
+			}
+		}
+		
+		/* This reserves IO space but doesn't actually enable it */
+		CFG_CHECK(RequestIO, link->handle, &link->io); 
+		/* If we got this far, we're cool! */
+		break;
+		
+	next_entry:
+		CS_CHECK(GetNextTuple, handle, &tuple);
+	}
+	
+	/*
+	  Allocate an interrupt line.  Note that this does not assign a
+	  handler to the interrupt, unless the 'Handler' member of the
+	  irq structure is initialized.
+	*/
+	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+		CS_CHECK(RequestIRQ, link->handle, &link->irq);
+	
+	/*
+	  This actually configures the PCMCIA socket -- setting up
+	  the I/O windows and the interrupt mapping, and putting the
+	  card and host interface into "Memory and IO" mode.
+	*/
+	CS_CHECK(RequestConfiguration, link->handle, &link->conf);
+	
+	if (link->irq.AssignedIRQ == 0) {
+		printk(KERN_ALERT 
+		       "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
+		goto cs_failed;
+	}
+	
+	((local_info_t*)link->priv)->eth_dev = 
+		init_atmel_card(link->irq.AssignedIRQ,
+				link->io.BasePort1,
+				card_index == -1 ? NULL :  card_table[card_index].firmware,
+				card_index == -1 ? 0 : (card_table[card_index].manf == MANFID_3COM),
+				card_present, 
+				link);
+	if (!((local_info_t*)link->priv)->eth_dev) 
+		goto cs_failed;
+	
+	/*
+	  At this point, the dev_node_t structure(s) need to be
+	  initialized and arranged in a linked list at link->dev.
+	*/
+	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
+	dev->node.major = dev->node.minor = 0;
+	link->dev = &dev->node;
+	
+	/* Finally, report what we've done */
+	printk(KERN_INFO "%s: %s%sindex 0x%02x: Vcc %d.%d",
+	       dev->node.dev_name,
+	       card_index == -1 ? "" :  card_table[card_index].name,
+	       card_index == -1 ? "" : " ",
+	       link->conf.ConfigIndex,
+	       link->conf.Vcc/10, link->conf.Vcc%10);
+	if (link->conf.Vpp1)
+		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+		printk(", irq %d", link->irq.AssignedIRQ);
+	if (link->io.NumPorts1)
+		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+		       link->io.BasePort1+link->io.NumPorts1-1);
+	if (link->io.NumPorts2)
+		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+		       link->io.BasePort2+link->io.NumPorts2-1);
+	printk("\n");
+	
+	link->state &= ~DEV_CONFIG_PENDING;
+	return;
+	
+ cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+	atmel_release(link);
+}
+
+/*======================================================================
+  
+  After a card is removed, atmel_release() will unregister the
+  device, and release the PCMCIA configuration.  If the device is
+  still open, this will be postponed until it is closed.
+  
+  ======================================================================*/
+
+static void atmel_release(dev_link_t *link)
+{
+	struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
+		
+	DEBUG(0, "atmel_release(0x%p)\n", link);
+	
+	/* Unlink the device chain */
+	link->dev = NULL;
+	
+	if (dev) 
+		stop_atmel_card(dev, 0);
+	((local_info_t*)link->priv)->eth_dev = 0; 
+	
+	/* Don't bother checking to see if these succeed or not */
+	CardServices(ReleaseConfiguration, link->handle);
+	if (link->io.NumPorts1)
+		CardServices(ReleaseIO, link->handle, &link->io);
+	if (link->irq.AssignedIRQ)
+		CardServices(ReleaseIRQ, link->handle, &link->irq);
+	link->state &= ~DEV_CONFIG;
+}
+
+/*======================================================================
+  
+  The card status event handler.  Mostly, this schedules other
+  stuff to run after an event is received.
+
+  When a CARD_REMOVAL event is received, we immediately set a
+  private flag to block future accesses to this device.  All the
+  functions that actually access the device should check this flag
+  to make sure the card is still present.
+  
+  ======================================================================*/
+
+static int atmel_event(event_t event, int priority,
+		      event_callback_args_t *args)
+{
+	dev_link_t *link = args->client_data;
+	local_info_t *local = link->priv;
+	
+	DEBUG(1, "atmel_event(0x%06x)\n", event);
+	
+	switch (event) {
+	case CS_EVENT_CARD_REMOVAL:
+		link->state &= ~DEV_PRESENT;
+		if (link->state & DEV_CONFIG) {
+			netif_device_detach(local->eth_dev);
+			atmel_release(link);
+		}
+		break;
+	case CS_EVENT_CARD_INSERTION:
+		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+		atmel_config(link);
+		break;
+	case CS_EVENT_PM_SUSPEND:
+		link->state |= DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+		if (link->state & DEV_CONFIG) {
+			netif_device_detach(local->eth_dev);
+			CardServices(ReleaseConfiguration, link->handle);
+		}
+		break;
+	case CS_EVENT_PM_RESUME:
+		link->state &= ~DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_CARD_RESET:
+		if (link->state & DEV_CONFIG) {
+			CardServices(RequestConfiguration, link->handle, &link->conf);
+			reset_atmel_card(local->eth_dev);
+			netif_device_attach(local->eth_dev);
+		}
+		break;
+	}
+	return 0;
+} /* atmel_event */
+
+static int atmel_cs_init(void)
+{
+	servinfo_t serv;
+	DEBUG(0, "%s\n", version);
+	CardServices(GetCardServicesInfo, &serv);
+	if (serv.Revision != CS_RELEASE_CODE) {
+		printk(KERN_NOTICE "atmel_cs: Card Services release "
+		       "does not match!\n");
+		return -1;
+	}
+	register_pcmcia_driver(&dev_info, &atmel_attach, &atmel_detach);
+        return 0;
+}
+
+static void atmel_cs_cleanup(void)
+{
+        unregister_pcmcia_driver(&dev_info);
+
+        /* XXX: this really needs to move into generic code.. */
+        while (dev_list != NULL) {
+                if (dev_list->state & DEV_CONFIG)
+                        atmel_release(dev_list);
+                atmel_detach(dev_list);
+        }
+}
+
+/*
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation; either version 2
+    of the License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    In addition:
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+    3. The name of the author may not be used to endorse or promote
+       products derived from this software without specific prior written
+       permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGE.    
+*/
+
+module_init(atmel_cs_init);
+module_exit(atmel_cs_cleanup);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/pcmcia/yenta.c linux-2.4.26-pre6/drivers/pcmcia/yenta.c
--- linux-2.4.25/drivers/pcmcia/yenta.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/pcmcia/yenta.c	2004-03-25 00:20:31.000000000 +0000
@@ -870,6 +870,13 @@ static struct cardbus_override_struct {
 	{ PD(TI,1420),	&ti_ops },
 	{ PD(TI,4410),	&ti_ops },
 	{ PD(TI,4451),	&ti_ops },
+	{ PD(TI,1510),  &ti_ops },
+	{ PD(TI,1520),  &ti_ops },
+
+	{ PD(ENE,1211),  &ti_ops },
+	{ PD(ENE,1225),  &ti_ops },
+	{ PD(ENE,1410),  &ti_ops },
+	{ PD(ENE,1420),  &ti_ops },
 
 	{ PD(RICOH,RL5C465), &ricoh_ops },
 	{ PD(RICOH,RL5C466), &ricoh_ops },
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/advansys.c linux-2.4.26-pre6/drivers/scsi/advansys.c
--- linux-2.4.25/drivers/scsi/advansys.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/advansys.c	2004-03-25 00:18:40.000000000 +0000
@@ -5551,7 +5551,7 @@ advansys_detect(Scsi_Host_Template *tpnt
                 }
             } else {
                 ADV_CARR_T      *carrp;
-                int             req_cnt;
+                int             req_cnt = 0;
                 adv_req_t       *reqp = NULL;
                 int             sg_cnt = 0;
 
@@ -9257,8 +9257,6 @@ DvcAdvWritePCIConfigByte(
         PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
             ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
         offset, byte_data);
-#else /* CONFIG_PCI */
-    return 0;
 #endif /* CONFIG_PCI */
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/eata_dma.c linux-2.4.26-pre6/drivers/scsi/eata_dma.c
--- linux-2.4.25/drivers/scsi/eata_dma.c	2001-09-30 19:26:07.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/eata_dma.c	2004-03-25 00:17:10.000000000 +0000
@@ -1067,7 +1067,7 @@ short register_HBA(u32 base, struct get_
     char *buff = 0;
     unchar bugs = 0;
     struct Scsi_Host *sh;
-    hostdata *hd;
+    hostdata *hd = NULL;
     int x;
     
     
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/qlogicfc.c linux-2.4.26-pre6/drivers/scsi/qlogicfc.c
--- linux-2.4.25/drivers/scsi/qlogicfc.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/qlogicfc.c	2004-03-25 00:21:03.000000000 +0000
@@ -411,7 +411,7 @@ static unsigned short risc_code_addr01 =
    if that mbox should be copied as input.  For example 0x2 would mean
    only copy mbox1. */
 
-const u_char mbox_param[] =
+static const u_char mbox_param[] =
 {
 	0x01,			/* MBOX_NO_OP */
 	0x1f,			/* MBOX_LOAD_RAM */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/qlogicpti.c linux-2.4.26-pre6/drivers/scsi/qlogicpti.c
--- linux-2.4.25/drivers/scsi/qlogicpti.c	2001-10-30 23:08:11.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/qlogicpti.c	2004-03-25 00:20:51.000000000 +0000
@@ -53,7 +53,7 @@ static int qptis_running = 0;
 
 #define PACKB(a, b)			(((a)<<4)|(b))
 
-const u_char mbox_param[] = {
+static const u_char mbox_param[] = {
 	PACKB(1, 1),	/* MBOX_NO_OP */
 	PACKB(5, 5),	/* MBOX_LOAD_RAM */
 	PACKB(2, 0),	/* MBOX_EXEC_FIRMWARE */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/scsi_error.c linux-2.4.26-pre6/drivers/scsi/scsi_error.c
--- linux-2.4.25/drivers/scsi/scsi_error.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/scsi_error.c	2004-03-25 00:16:55.000000000 +0000
@@ -110,25 +110,13 @@ void scsi_add_timer(Scsi_Cmnd * SCset,
 		    int timeout,
 		    void (*complete) (Scsi_Cmnd *))
 {
-
-	/*
-	 * If the clock was already running for this command, then
-	 * first delete the timer.  The timer handling code gets rather
-	 * confused if we don't do this.
-	 */
-	if (SCset->eh_timeout.function != NULL) {
-		del_timer(&SCset->eh_timeout);
-	}
 	SCset->eh_timeout.data = (unsigned long) SCset;
-	SCset->eh_timeout.expires = jiffies + timeout;
 	SCset->eh_timeout.function = (void (*)(unsigned long)) complete;
+	mod_timer(&SCset->eh_timeout, jiffies + timeout);
 
 	SCset->done_late = 0;
 
 	SCSI_LOG_ERROR_RECOVERY(5, printk("Adding timer for command %p at %d (%p)\n", SCset, timeout, complete));
-
-	add_timer(&SCset->eh_timeout);
-
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/scsi_lib.c linux-2.4.26-pre6/drivers/scsi/scsi_lib.c
--- linux-2.4.25/drivers/scsi/scsi_lib.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/scsi_lib.c	2004-03-25 00:19:56.000000000 +0000
@@ -405,6 +405,14 @@ static Scsi_Cmnd *__scsi_end_request(Scs
 	 */
 	if (req->bh) {
 		/*
+		 * Recount segments whether we are immediately going to
+		 * requeue the command or not, other code might requeue
+		 * it later and since we changed the segment count up above,
+		 * we need it updated.
+		 */
+		recount_segments(SCpnt);
+
+		/*
 		 * Bleah.  Leftovers again.  Stick the leftovers in
 		 * the front of the queue, and goose the queue again.
 		 */
@@ -966,15 +974,6 @@ void scsi_request_fn(request_queue_t * q
 			 */
 			if( req->special != NULL ) {
 				SCpnt = (Scsi_Cmnd *) req->special;
-				/*
-				 * We need to recount the number of
-				 * scatter-gather segments here - the
-				 * normal case code assumes this to be
-				 * correct, as it would be a performance
-				 * lose to always recount.  Handling
-				 * errors is always unusual, of course.
-				 */
-				recount_segments(SCpnt);
 			} else {
 				SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
 			}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/scsi_scan.c linux-2.4.26-pre6/drivers/scsi/scsi_scan.c
--- linux-2.4.25/drivers/scsi/scsi_scan.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/scsi_scan.c	2004-03-25 00:21:21.000000000 +0000
@@ -189,6 +189,7 @@ static struct dev_info device_list[] =
 	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
 	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"HITACHI", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI XP Arrays */
+	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI 9960 */
 	{"WINSYS","FLASHDISK G6", "*", BLIST_SPARSELUN},
 	{"DotHill","SANnet RAID X300", "*", BLIST_SPARSELUN},	
 	{"SUN", "T300", "*", BLIST_SPARSELUN},
@@ -221,10 +222,14 @@ static unsigned int max_scsi_luns = MAX_
 static unsigned int max_scsi_luns = 1;
 #endif
 
+static unsigned int scsi_allow_ghost_devices = 0;
+
 #ifdef MODULE
 
 MODULE_PARM(max_scsi_luns, "i");
 MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)");
+MODULE_PARM(scsi_allow_ghost_devices, "i");
+MODULE_PARM_DESC(scsi_allow_ghost_devices, "allow devices marked as being offline to be accessed anyway (0 = off, else allow ghosts on lun 0 through scsi_allow_ghost_devices - 1");
 
 #else
 
@@ -244,6 +249,21 @@ static int __init scsi_luns_setup(char *
 
 __setup("max_scsi_luns=", scsi_luns_setup);
 
+static int __init scsi_allow_ghost_devices_setup(char *str)
+{
+	unsigned int tmp;
+
+	if (get_option(&str, &tmp) == 1) {
+		scsi_allow_ghost_devices = tmp;
+		return 1;
+	} else {
+		printk("scsi_allow_ghost_devices_setup: usage scsi_allow_ghost_devices=n (0: off else\nallow ghost devices (ghost devices are devices that report themselves as\nbeing offline but which we allow access to anyway) on lun 0 through n - 1.\n");
+		return 0;
+	}
+}
+
+__setup("scsi_allow_ghost_devices=", scsi_allow_ghost_devices_setup);
+
 #endif
 
 static void print_inquiry(unsigned char *data)
@@ -620,6 +640,7 @@ static int scan_scsis_single(unsigned in
 		} else {
 			/* assume no peripheral if any other sort of error */
 			scsi_release_request(SRpnt);
+			scsi_release_commandblocks(SDpnt);
 			return 0;
 		}
 	}
@@ -630,6 +651,24 @@ static int scan_scsis_single(unsigned in
 	 */
 
 	/*
+	 * If we are offline and we are on a LUN != 0, then skip this entry.
+	 * If we are on a BLIST_FORCELUN device this will stop the scan at
+	 * the first offline LUN (typically the correct thing to do).  If
+	 * we are on a BLIST_SPARSELUN device then this won't stop the scan,
+	 * but it will keep us from having false entries in our device
+	 * array. DL
+	 *
+	 * NOTE: Need to test this to make sure it doesn't cause problems
+	 * with tape autoloaders, multidisc CD changers, and external
+	 * RAID chassis that might use sparse luns or multiluns... DL
+	 */
+	if (lun != 0 && (scsi_result[0] >> 5) == 1) {
+		scsi_release_request(SRpnt);
+		scsi_release_commandblocks(SDpnt);
+		return 0;
+	}
+
+	/*
 	 * Get any flags for this device.  
 	 */
 	bflags = get_device_flags (scsi_result);
@@ -667,8 +706,11 @@ static int scan_scsis_single(unsigned in
 
 	SDpnt->removable = (0x80 & scsi_result[1]) >> 7;
 	/* Use the peripheral qualifier field to determine online/offline */
-	if (((scsi_result[0] >> 5) & 7) == 1) 	SDpnt->online = FALSE;
-	else SDpnt->online = TRUE;
+	if ((((scsi_result[0] >> 5) & 7) == 1) &&
+	    (lun >= scsi_allow_ghost_devices))
+		SDpnt->online = FALSE;
+	else 
+		SDpnt->online = TRUE;
 	SDpnt->lockable = SDpnt->removable;
 	SDpnt->changed = 0;
 	SDpnt->access_count = 0;
@@ -876,11 +918,26 @@ static int scan_scsis_single(unsigned in
 		 * I think we need REPORT LUNS in future to avoid scanning
 		 * of unused LUNs. But, that is another item.
 		 */
+		/*
 		if (*max_dev_lun < shpnt->max_lun)
 			*max_dev_lun = shpnt->max_lun;
 		else 	if ((max_scsi_luns >> 1) >= *max_dev_lun)
 				*max_dev_lun += shpnt->max_lun;
 			else	*max_dev_lun = max_scsi_luns;
+		*/
+		/*
+		 * Blech...the above code is broken.  When you have a device
+		 * that is present, and it is a FORCELUN device, then we
+		 * need to scan *all* the luns on that device.  Besides,
+		 * skipping the scanning of LUNs is a false optimization.
+		 * Scanning for a LUN on a present device is a very fast
+		 * operation, it's scanning for devices that don't exist that
+		 * is expensive and slow (although if you are truly scanning
+		 * through MAX_SCSI_LUNS devices that would be bad, I hope
+		 * all of the controllers out there set a reasonable value
+		 * in shpnt->max_lun).  DL
+		 */
+		*max_dev_lun = shpnt->max_lun;
 		return 1;
 	}
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/scsi_syms.c linux-2.4.26-pre6/drivers/scsi/scsi_syms.c
--- linux-2.4.25/drivers/scsi/scsi_syms.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/scsi_syms.c	2004-03-25 00:19:56.000000000 +0000
@@ -43,6 +43,7 @@ EXPORT_SYMBOL(scsi_allocate_device);
 EXPORT_SYMBOL(scsi_do_cmd);
 EXPORT_SYMBOL(scsi_command_size);
 EXPORT_SYMBOL(scsi_ioctl);
+EXPORT_SYMBOL(scsi_finish_command);
 EXPORT_SYMBOL(print_command);
 EXPORT_SYMBOL(print_sense);
 EXPORT_SYMBOL(print_req_sense);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/sym53c8xx.c linux-2.4.26-pre6/drivers/scsi/sym53c8xx.c
--- linux-2.4.25/drivers/scsi/sym53c8xx.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/sym53c8xx.c	2004-03-25 00:20:50.000000000 +0000
@@ -6992,7 +6992,7 @@ static void ncr_chip_reset (ncb_p np)
 
 static void ncr_soft_reset(ncb_p np)
 {
-	u_char istat;
+	u_char istat = 0;
 	int i;
 
 	if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SRUN))
@@ -11981,6 +11981,19 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_
 		inq_byte7 |= INQ7_SYNC;
 
 	/*
+	**	Don't do PPR negotiations on SCSI-2 devices unless
+	**	they set the DT bit (0x04) in byte 57 of the INQUIRY
+	**	return data.
+	*/
+	if (((inq_data[2] & 0x07) < 3) && (inq_data[4] < 53 ||
+					   !(inq_data[56] & 0x04))) {
+		if (tp->minsync < 10)
+			tp->minsync = 10;
+		if (tp->usrsync < 10)
+			tp->usrsync = 10;
+	}
+
+	/*
 	**	Prepare negotiation if SIP capabilities have changed.
 	*/
 	tp->inq_done = 1;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/scsi/sym53c8xx_2/sym_hipd.c linux-2.4.26-pre6/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- linux-2.4.25/drivers/scsi/sym53c8xx_2/sym_hipd.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-03-25 00:16:53.000000000 +0000
@@ -221,7 +221,7 @@ static void sym_chip_reset (hcb_p np)
  */
 static void sym_soft_reset (hcb_p np)
 {
-	u_char istat;
+	u_char istat = 0;
 	int i;
 
 	if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/sound/i810_audio.c linux-2.4.26-pre6/drivers/sound/i810_audio.c
--- linux-2.4.25/drivers/sound/i810_audio.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/sound/i810_audio.c	2004-03-25 00:21:14.000000000 +0000
@@ -120,9 +120,15 @@
 #ifndef PCI_DEVICE_ID_INTEL_ICH5
 #define PCI_DEVICE_ID_INTEL_ICH5	0x24d5
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH6_3
+#define PCI_DEVICE_ID_INTEL_ICH6_3	0x266e
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_440MX
 #define PCI_DEVICE_ID_INTEL_440MX	0x7195
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ESB_5
+#define PCI_DEVICE_ID_INTEL_ESB_5	0x25a6
+#endif
 #ifndef PCI_DEVICE_ID_SI_7012
 #define PCI_DEVICE_ID_SI_7012		0x7012
 #endif
@@ -343,6 +349,11 @@ static struct pci_device_id i810_pci_tbl
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
 	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AC97,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_3,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
+
 	{0,}
 };
 
@@ -2785,7 +2796,8 @@ static int i810_ac97_power_up_bus(struct
 	 */	
 	/* see i810_ac97_init for the next 7 lines (jsaw) */
 	inw(card->ac97base);
-	if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5)
+	if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5 ||
+	     card->pci_id == PCI_DEVICE_ID_INTEL_ESB_5 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH6_3)
 	    && (card->use_mmio)) {
 		primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
@@ -2855,7 +2867,8 @@ static int __init i810_ac97_init(struct 
 		   possible IO channels. Bit 0:1 of SDM then holds the 
 		   last codec ID spoken to. 
 		*/
-		if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5)
+		if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5 ||
+		     card->pci_id == PCI_DEVICE_ID_INTEL_ESB_5 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH6_3)
 		    && (card->use_mmio)) {
 			ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 			printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/sound/sb_audio.c linux-2.4.26-pre6/drivers/sound/sb_audio.c
--- linux-2.4.25/drivers/sound/sb_audio.c	2002-02-25 19:38:06.000000000 +0000
+++ linux-2.4.26-pre6/drivers/sound/sb_audio.c	2004-03-25 00:21:29.000000000 +0000
@@ -879,7 +879,7 @@ sb16_copy_from_user(int dev,
 			c -= locallen; p += locallen;
 		}
 		/* used = ( samples * 16 bits size ) */
-		*used = len << 1;
+		*used =  max_in  > ( max_out << 1) ? (max_out << 1) : max_in;
 		/* returned = ( samples * 8 bits size ) */
 		*returned = len;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/audio.c linux-2.4.26-pre6/drivers/usb/audio.c
--- linux-2.4.25/drivers/usb/audio.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/audio.c	2004-03-25 00:22:19.000000000 +0000
@@ -1684,12 +1684,12 @@ static int set_format_in(struct usb_audi
 		    alts->endpoint[1].bmAttributes != 0x01 ||
 		    alts->endpoint[1].bSynchAddress != 0 ||
 		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress & 0x7f)) {
-			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
+			printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims adaptive in but has invalid synch pipe; treating as asynchronous in\n",
 			       dev->devnum, u->interface, fmt->altsetting);
-			return -1;
+		} else {
+			u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
+			u->syncinterval = alts->endpoint[1].bRefresh;
 		}
-		u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
-		u->syncinterval = alts->endpoint[1].bRefresh;
 	}
 	if (d->srate < fmt->sratelo)
 		d->srate = fmt->sratelo;
@@ -1779,12 +1779,12 @@ static int set_format_out(struct usb_aud
 		    alts->endpoint[1].bmAttributes != 0x01 ||
 		    alts->endpoint[1].bSynchAddress != 0 ||
 		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress | 0x80)) {
-			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
+			printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims asynch out but has invalid synch pipe; treating as adaptive out\n",
 			       dev->devnum, u->interface, fmt->altsetting);
-			return -1;
+		} else {
+			u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
+			u->syncinterval = alts->endpoint[1].bRefresh;
 		}
-		u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
-		u->syncinterval = alts->endpoint[1].bRefresh;
 	}
 	if (d->srate < fmt->sratelo)
 		d->srate = fmt->sratelo;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/Config.in linux-2.4.26-pre6/drivers/usb/gadget/Config.in
--- linux-2.4.25/drivers/usb/gadget/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/Config.in	2004-03-25 00:19:41.000000000 +0000
@@ -31,6 +31,9 @@ if [ "$CONFIG_USB_GADGET" = "y" -o "$CON
     define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_GOKU
   fi
 
+  # or any other controller that supports high speed transfers ...
+  define_bool CONFIG_USB_GADGET_DUALSPEED $CONFIG_USB_GADGET_NET2280
+
   if [ "$CONFIG_USB_GADGET_CONTROLLER" = "y" -o "$CONFIG_USB_GADGET_CONTROLLER" = "m" ] ; then
 
   #
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/Makefile linux-2.4.26-pre6/drivers/usb/gadget/Makefile
--- linux-2.4.25/drivers/usb/gadget/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/Makefile	2004-03-25 00:18:41.000000000 +0000
@@ -16,10 +16,10 @@ controller-$(CONFIG_USB_NET2280)	+= net2
 controller-$(CONFIG_USB_GOKU)		+= goku_udc.o
 
 # ... and only one of these, too; kbuild/kconfig don't help though.
-g_zero-objs			:= zero.o usbstring.o
+g_zero-objs			:= zero.o usbstring.o config.o
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 
-g_ether-objs			:= ether.o usbstring.o
+g_ether-objs			:= ether.o usbstring.o config.o
 obj-$(CONFIG_USB_ETH)		+= g_ether.o
 
 g_file_storage-objs		:= file_storage.o usbstring.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/config.c linux-2.4.26-pre6/drivers/usb/gadget/config.c
--- linux-2.4.25/drivers/usb/gadget/config.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/config.c	2004-03-25 00:18:23.000000000 +0000
@@ -0,0 +1,115 @@
+/*
+ * usb/gadget/config.c -- simplify building config descriptors
+ *
+ * Copyright (C) 2003 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+
+#include <linux/usb_ch9.h>
+
+
+/**
+ * usb_descriptor_fillbuf - fill buffer with descriptors
+ * @buf: Buffer to be filled
+ * @buflen: Size of buf
+ * @src: Array of descriptor pointers, terminated by null pointer.
+ *
+ * Copies descriptors into the buffer, returning the length or a
+ * negative error code if they can't all be copied.  Useful when
+ * assembling descriptors for an associated set of interfaces used
+ * as part of configuring a composite device; or in other cases where
+ * sets of descriptors need to be marshaled.
+ */
+int
+usb_descriptor_fillbuf(void *buf, unsigned buflen,
+		const struct usb_descriptor_header **src)
+{
+	u8	*dest = buf;
+
+	if (!src)
+		return -EINVAL;
+
+	/* fill buffer from src[] until null descriptor ptr */
+	for (; 0 != *src; src++) {
+		unsigned		len = (*src)->bLength;
+
+		if (len > buflen);
+			return -EINVAL;
+		memcpy(dest, *src, len);
+		buflen -= len;
+		dest += len;
+	}
+	return dest - (u8 *)buf;
+}
+
+
+/**
+ * usb_gadget_config_buf - builts a complete configuration descriptor
+ * @config: Header for the descriptor, including characteristics such
+ *	as power requirements and number of interfaces.
+ * @desc: Null-terminated vector of pointers to the descriptors (interface,
+ *	endpoint, etc) defining all functions in this device configuration.
+ * @buf: Buffer for the resulting configuration descriptor.
+ * @length: Length of buffer.  If this is not big enough to hold the
+ *	entire configuration descriptor, an error code will be returned.
+ *
+ * This copies descriptors into the response buffer, building a descriptor
+ * for that configuration.  It returns the buffer length or a negative
+ * status code.  The config.wTotalLength field is set to match the length
+ * of the result, but other descriptor fields (including power usage and
+ * interface count) must be set by the caller.
+ *
+ * Gadget drivers could use this when constructing a config descriptor
+ * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
+ * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
+ */
+int usb_gadget_config_buf(
+	const struct usb_config_descriptor	*config,
+	void					*buf,
+	unsigned				length,
+	const struct usb_descriptor_header	**desc
+)
+{
+	struct usb_config_descriptor		*cp = buf;
+	int					len;
+
+	/* config descriptor first */
+	if (length < USB_DT_CONFIG_SIZE || !desc)
+		return -EINVAL;
+	*cp = *config; 
+
+	/* then interface/endpoint/class/vendor/... */
+	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
+			length - USB_DT_CONFIG_SIZE, desc);
+	if (len < 0)
+		return len;
+	len += USB_DT_CONFIG_SIZE;
+	if (len > 0xffff)
+		return -EINVAL;
+
+	/* patch up the config descriptor */
+	cp->bLength = USB_DT_CONFIG_SIZE;
+	cp->bDescriptorType = USB_DT_CONFIG;
+	cp->wTotalLength = cpu_to_le16(len);
+	cp->bmAttributes |= USB_CONFIG_ATT_ONE;
+	return len;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/ether.c linux-2.4.26-pre6/drivers/usb/gadget/ether.c
--- linux-2.4.25/drivers/usb/gadget/ether.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/ether.c	2004-03-25 00:17:11.000000000 +0000
@@ -19,7 +19,7 @@
  */
 
 
-#define DEBUG 1
+// #define DEBUG 1
 // #define VERBOSE
 
 #include <linux/config.h>
@@ -136,7 +136,6 @@ struct eth_dev {
  * DRIVER_VERSION_NUM ... alerts the host side driver to differences
  * EP_*_NAME ... which endpoints do we use for which purpose?
  * EP_*_NUM ... numbers for them (often limited by hardware)
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
  * WAKEUP ... if hardware supports remote wakeup AND we will issue the
  * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
  *
@@ -174,7 +173,6 @@ static const char EP_IN_NAME [] = "ep-b"
 #define EP_IN_NUM	2
 static const char EP_STATUS_NAME [] = "ep-f";
 #define EP_STATUS_NUM	3
-#define HIGHSPEED
 /* supports remote wakeup, but this driver doesn't */
 
 extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
@@ -323,7 +321,7 @@ static const char EP_IN_NAME[] = "ep2in-
 #define DEFAULT_QLEN	2	/* double buffering by default */
 #endif
 
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 
 static unsigned qmult = 5;
 MODULE_PARM (qmult, "i");
@@ -336,7 +334,7 @@ MODULE_PARM (qmult, "i");
 /* also defer IRQs on highspeed TX */
 #define TX_DELAY	DEFAULT_QLEN
 
-#else	/* !HIGHSPEED ... full speed: */
+#else	/* full speed (low speed doesn't do bulk) */
 #define qlen(gadget) DEFAULT_QLEN
 #endif
 
@@ -619,7 +617,26 @@ fs_sink_desc = {
 	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-#ifdef	HIGHSPEED
+static const struct usb_descriptor_header *fs_function [] = {
+#ifdef DEV_CONFIG_CDC
+	/* "cdc" mode descriptors */
+	(struct usb_descriptor_header *) &control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+#ifdef	EP_STATUS_NUM
+	(struct usb_descriptor_header *) &fs_status_desc,
+#endif
+	(struct usb_descriptor_header *) &data_nop_intf,
+#endif /* DEV_CONFIG_CDC */
+	/* minimalist core */
+	(struct usb_descriptor_header *) &data_intf,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	0,
+};
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 
 /*
  * usb 2.0 devices need to expose both high speed and full speed
@@ -672,6 +689,25 @@ dev_qualifier = {
 	.bNumConfigurations =	1,
 };
 
+static const struct usb_descriptor_header *hs_function [] = {
+#ifdef DEV_CONFIG_CDC
+	/* "cdc" mode descriptors */
+	(struct usb_descriptor_header *) &control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+#ifdef	EP_STATUS_NUM
+	(struct usb_descriptor_header *) &hs_status_desc,
+#endif
+	(struct usb_descriptor_header *) &data_nop_intf,
+#endif /* DEV_CONFIG_CDC */
+	/* minimalist core */
+	(struct usb_descriptor_header *) &data_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
+};
+
 
 /* maxpacket and other transfer characteristics vary by speed. */
 #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
@@ -681,7 +717,7 @@ dev_qualifier = {
 /* if there's no high speed support, maxpacket doesn't change. */
 #define ep_desc(g,hs,fs) fs
 
-#endif	/* !HIGHSPEED */
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
 /*-------------------------------------------------------------------------*/
 
@@ -716,86 +752,25 @@ static struct usb_gadget_strings	stringt
 static int
 config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
 {
-	const unsigned	config_len = USB_DT_CONFIG_SIZE
-#ifdef DEV_CONFIG_CDC
-				+ 2 * USB_DT_INTERFACE_SIZE
-				+ sizeof header_desc
-				+ sizeof union_desc
-				+ sizeof ether_desc
-#ifdef	EP_STATUS_NUM
-				+ USB_DT_ENDPOINT_SIZE
-#endif
-#endif /* DEV_CONFIG_CDC */
-				+ USB_DT_INTERFACE_SIZE
-				+ 2 * USB_DT_ENDPOINT_SIZE;
+	int				len;
+	const struct usb_descriptor_header **function = fs_function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int				hs = (speed == USB_SPEED_HIGH);
 
-#ifdef HIGHSPEED
-	int		hs;
-#endif
-	/* a single configuration must always be index 0 */
-	if (index > 0)
-		return -EINVAL;
-	if (config_len > USB_BUFSIZ)
-		return -EDOM;
-
-	/* config (or other speed config) */
-	memcpy (buf, &eth_config, USB_DT_CONFIG_SIZE);
-	buf [1] = type;
-	((struct usb_config_descriptor *) buf)->wTotalLength
-		= __constant_cpu_to_le16 (config_len);
-	buf += USB_DT_CONFIG_SIZE;
-#ifdef	HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-#endif
-
-#ifdef DEV_CONFIG_CDC
-	/* control interface, class descriptors, optional status endpoint */
-	memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	memcpy (buf, &header_desc, sizeof header_desc);
-	buf += sizeof header_desc;
-	memcpy (buf, &union_desc, sizeof union_desc);
-	buf += sizeof union_desc;
-	memcpy (buf, &ether_desc, sizeof ether_desc);
-	buf += sizeof ether_desc;
-
-#ifdef	EP_STATUS_NUM
-#ifdef	HIGHSPEED
 	if (hs)
-		memcpy (buf, &hs_status_desc, USB_DT_ENDPOINT_SIZE);
-	else
-#endif	/* HIGHSPEED */
-		memcpy (buf, &fs_status_desc, USB_DT_ENDPOINT_SIZE);
-	buf += USB_DT_ENDPOINT_SIZE;
-#endif	/* EP_STATUS_NUM */
-
-	/* default data altsetting has no endpoints */
-	memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-#endif /* DEV_CONFIG_CDC */
-
-	/* the "real" data interface has two endpoints */
-	memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-#ifdef HIGHSPEED
-	if (hs) {
-		memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	} else
+		function = hs_function;
 #endif
-	{
-		memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	}
 
-	return config_len;
+	/* a single configuration must always be index 0 */
+	if (index > 0)
+		return -EINVAL;
+	len = usb_gadget_config_buf (&eth_config, buf, USB_BUFSIZ, function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -897,8 +872,11 @@ set_ether_config (struct eth_dev *dev, i
 #ifndef	DEV_CONFIG_CDC
 	if (result == 0) {
 		netif_carrier_on (dev->net);
-		if (netif_running (dev->net))
+		if (netif_running (dev->net)) {
+			spin_unlock (&dev->lock);
 			eth_start (dev, GFP_ATOMIC);
+			spin_lock (&dev->lock);
+		}
 	} else {
 		(void) usb_ep_disable (dev->in_ep);
 		dev->in_ep = 0;
@@ -1001,7 +979,7 @@ eth_set_config (struct eth_dev *dev, uns
 
 		switch (gadget->speed) {
 		case USB_SPEED_FULL:	speed = "full"; break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_SPEED_HIGH:	speed = "high"; break;
 #endif
 		default: 		speed = "?"; break;
@@ -1172,15 +1150,19 @@ eth_setup (struct usb_gadget *gadget, co
 			value = min (ctrl->wLength, (u16) sizeof device_desc);
 			memcpy (req->buf, &device_desc, value);
 			break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget->is_dualspeed)
+				break;
 			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
+			if (!gadget->is_dualspeed)
+				break;
 			// FALLTHROUGH
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			value = config_buf (gadget->speed, req->buf,
 					ctrl->wValue >> 8,
@@ -1258,8 +1240,11 @@ eth_setup (struct usb_gadget *gadget, co
 #ifdef	EP_STATUS_NUM
 				issue_start_status (dev);
 #endif
-				if (netif_running (dev->net))
+				if (netif_running (dev->net)) {
+					spin_unlock (&dev->lock);
 					eth_start (dev, GFP_ATOMIC);
+					spin_lock (&dev->lock);
+				}
 			} else {
 				netif_stop_queue (dev->net);
 				netif_carrier_off (dev->net);
@@ -1426,16 +1411,14 @@ static int
 rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
 {
 	struct sk_buff		*skb;
-	int			retval = 0;
+	int			retval = -ENOMEM;
 	size_t			size;
 
 	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
 
 	if ((skb = alloc_skb (size, gfp_flags)) == 0) {
 		DEBUG (dev, "no rx skb\n");
-		defer_kevent (dev, WORK_RX_MEMORY);
-		list_add (&req->list, &dev->rx_reqs);
-		return -ENOMEM;
+		goto enomem;
 	}
 
 	req->buf = skb->data;
@@ -1445,11 +1428,14 @@ rx_submit (struct eth_dev *dev, struct u
 
 	retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
 	if (retval == -ENOMEM)
+enomem:
 		defer_kevent (dev, WORK_RX_MEMORY);
 	if (retval) {
 		DEBUG (dev, "rx submit --> %d\n", retval);
 		dev_kfree_skb_any (skb);
+		spin_lock (&dev->lock);
 		list_add (&req->list, &dev->rx_reqs);
+		spin_unlock (&dev->lock);
 	}
 	return retval;
 }
@@ -1514,6 +1500,7 @@ quiesce:
 		dev_kfree_skb_any (skb);
 	if (!netif_running (dev->net)) {
 clean:
+		/* nobody reading rx_reqs, so no dev->lock */
 		list_add (&req->list, &dev->rx_reqs);
 		req = 0;
 	}
@@ -1580,19 +1567,26 @@ fail:
 static void rx_fill (struct eth_dev *dev, int gfp_flags)
 {
 	struct usb_request	*req;
+	unsigned long		flags;
 
 	clear_bit (WORK_RX_MEMORY, &dev->todo);
 
 	/* fill unused rxq slots with some skb */
+	spin_lock_irqsave (&dev->lock, flags);
 	while (!list_empty (&dev->rx_reqs)) {
 		req = container_of (dev->rx_reqs.next,
 				struct usb_request, list);
 		list_del_init (&req->list);
+		spin_unlock_irqrestore (&dev->lock, flags);
+
 		if (rx_submit (dev, req, gfp_flags) < 0) {
 			defer_kevent (dev, WORK_RX_MEMORY);
 			return;
 		}
+
+		spin_lock_irqsave (&dev->lock, flags);
 	}
+	spin_unlock_irqrestore (&dev->lock, flags);
 }
 
 static void eth_work (void *_dev)
@@ -1628,7 +1622,9 @@ static void tx_complete (struct usb_ep *
 	}
 	dev->stats.tx_packets++;
 
+	spin_lock (&dev->lock);
 	list_add (&req->list, &dev->tx_reqs);
+	spin_unlock (&dev->lock);
 	dev_kfree_skb_any (skb);
 
 	atomic_dec (&dev->tx_qlen);
@@ -1642,11 +1638,14 @@ static int eth_start_xmit (struct sk_buf
 	int			length = skb->len;
 	int			retval;
 	struct usb_request	*req = 0;
+	unsigned long		flags;
 
+	spin_lock_irqsave (&dev->lock, flags);
 	req = container_of (dev->tx_reqs.next, struct usb_request, list);
 	list_del (&req->list);
 	if (list_empty (&dev->tx_reqs))
 		netif_stop_queue (net);
+	spin_unlock_irqrestore (&dev->lock, flags);
 
 	/* no buffer copies needed, unless the network stack did it
 	 * or the hardware can't use skb buffers.
@@ -1667,7 +1666,7 @@ static int eth_start_xmit (struct sk_buf
 #endif
 	req->length = length;
 
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	/* throttle highspeed IRQ rate back slightly */
 	req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
 		? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0)
@@ -1687,9 +1686,11 @@ static int eth_start_xmit (struct sk_buf
 	if (retval) {
 		dev->stats.tx_dropped++;
 		dev_kfree_skb_any (skb);
+		spin_lock_irqsave (&dev->lock, flags);
 		if (list_empty (&dev->tx_reqs))
 			netif_start_queue (net);
 		list_add (&req->list, &dev->tx_reqs);
+		spin_unlock_irqrestore (&dev->lock, flags);
 	}
 	return 0;
 }
@@ -1788,7 +1789,7 @@ eth_bind (struct usb_gadget *gadget)
 #endif
 
 	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	/* assumes ep0 uses the same value for both speeds ... */
 	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
 #endif
@@ -1810,9 +1811,7 @@ eth_bind (struct usb_gadget *gadget)
 	/* network device setup */
 	dev->net = net;
 	SET_MODULE_OWNER (net);
-	net->priv = dev;
 	strcpy (net->name, "usb%d");
-	ether_setup (net);
 
 	/* one random address for the gadget device ... both of these could
 	 * reasonably come from an id prom or a module parameter.
@@ -1886,7 +1885,7 @@ fail:
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver eth_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
 #else
 	.speed		= USB_SPEED_FULL,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/gadget_chips.h linux-2.4.26-pre6/drivers/usb/gadget/gadget_chips.h
--- linux-2.4.25/drivers/usb/gadget/gadget_chips.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/gadget_chips.h	2004-03-25 00:17:59.000000000 +0000
@@ -0,0 +1,57 @@
+/*
+ * USB device controllers have lots of quirks.  Use these macros in
+ * gadget drivers or other code that needs to deal with them, and which
+ * autoconfigures instead of using early binding to the hardware.
+ *
+ * This could eventually work like the ARM mach_is_*() stuff, driven by
+ * some config file that gets updated as new hardware is supported.
+ *
+ * NOTE:  some of these controller drivers may not be available yet.
+ */
+#ifdef CONFIG_USB_GADGET_NET2280
+#define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
+#else
+#define	gadget_is_net2280(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_PXA
+#define	gadget_is_pxa(g)	!strcmp("pxa2xx_udc", (g)->name)
+#else
+#define	gadget_is_pxa(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_GOKU
+#define	gadget_is_goku(g)	!strcmp("goku_udc", (g)->name)
+#else
+#define	gadget_is_goku(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_SUPERH
+#define	gadget_is_sh(g)		!strcmp("sh_udc", (g)->name)
+#else
+#define	gadget_is_sh(g)		0
+#endif
+
+#ifdef CONFIG_USB_GADGET_SA1100
+#define	gadget_is_sa1100(g)	!strcmp("sa1100_udc", (g)->name)
+#else
+#define	gadget_is_sa1100(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_MQ11XX
+#define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
+#else
+#define	gadget_is_mq11xx(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_OMAP
+#define	gadget_is_omap(g)	!strcmp("omap_udc", (g)->name)
+#else
+#define	gadget_is_omap(g)	0
+#endif
+
+// CONFIG_USB_GADGET_AT91RM9200
+// CONFIG_USB_GADGET_SX2
+// CONFIG_USB_GADGET_AU1X00
+// ...
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/net2280.c linux-2.4.26-pre6/drivers/usb/gadget/net2280.c
--- linux-2.4.25/drivers/usb/gadget/net2280.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/net2280.c	2004-03-25 00:18:36.000000000 +0000
@@ -2718,6 +2718,7 @@ static int net2280_probe (struct pci_dev
 	spin_lock_init (&dev->lock);
 	dev->pdev = pdev;
 	dev->gadget.ops = &net2280_ops;
+	dev->gadget.is_dualspeed = 1;
 
 	dev->gadget.dev.bus_id = pdev->slot_name;
 	dev->gadget.name = driver_name;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/usbstring.c linux-2.4.26-pre6/drivers/usb/gadget/usbstring.c
--- linux-2.4.25/drivers/usb/gadget/usbstring.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/usbstring.c	2004-03-25 00:18:03.000000000 +0000
@@ -16,24 +16,89 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include <asm/unaligned.h>
+
+
+static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
+{
+	int	count = 0;
+	u8	c;
+	u16	uchar;
+
+	/* this insists on correct encodings, though not minimal ones.
+	 * BUT it currently rejects legit 4-byte UTF-8 code points,
+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)
+	 */
+	while (len != 0 && (c = (u8) *s++) != 0) {
+		if (unlikely(c & 0x80)) {
+			// 2-byte sequence:
+			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
+			if ((c & 0xe0) == 0xc0) {
+				uchar = (c & 0x1f) << 6;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0xc0)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c;
+
+			// 3-byte sequence (most CJKV characters):
+			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
+			} else if ((c & 0xf0) == 0xe0) {
+				uchar = (c & 0x0f) << 12;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0xc0)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c << 6;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0xc0)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c;
+
+				/* no bogus surrogates */
+				if (0xd800 <= uchar && uchar <= 0xdfff)
+					goto fail;
+
+			// 4-byte sequence (surrogate pairs, currently rare):
+			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx
+			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
+			// (uuuuu = wwww + 1)
+			// FIXME accept the surrogate code points (only)
+
+			} else
+				goto fail;
+		} else
+			uchar = c;
+		put_unaligned (cpu_to_le16 (uchar), cp++);
+		count++;
+		len--;
+	}
+	return count;
+fail:
+	return -1;
+}
+
 
 /**
  * usb_gadget_get_string - fill out a string descriptor 
- * @table: of c strings using iso latin/1 characters
+ * @table: of c strings encoded using UTF-8
  * @id: string id, from low byte of wValue in get string descriptor
  * @buf: at least 256 bytes
  *
- * Finds the iso latin/1 string matching the ID, and converts it into a
+ * Finds the UTF-8 string matching the ID, and converts it into a
  * string descriptor in utf16-le.
  * Returns length of descriptor (always even) or negative errno
  *
- * If your driver needs stings in multiple languages, you'll need to
- * to use some alternate solution for languages where the ISO 8859/1
- * (latin/1) character set can't be used.  For example, they can't be
- * used with Chinese (Big5, GB2312, etc), Japanese, Korean, or many other
- * languages.  You'd likely "switch (wIndex) { ... }"  in your ep0
- * string descriptor logic, using this routine in cases where "western
- * european" characters suffice for the strings being returned.
+ * If your driver needs stings in multiple languages, you'll probably
+ * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
+ * using this routine after choosing which set of UTF-8 strings to use.
+ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
+ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
+ * characters (which are also widely used in C strings).
  */
 int
 usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
@@ -59,13 +124,12 @@ usb_gadget_get_string (struct usb_gadget
 
 	/* string descriptors have length, tag, then UTF16-LE text */
 	len = min ((size_t) 126, strlen (s->s));
+	memset (buf + 2, 0, 2 * len);	/* zero all the bytes */
+	len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
+	if (len < 0)
+		return -EINVAL;
 	buf [0] = (len + 1) * 2;
 	buf [1] = USB_DT_STRING;
-	memset (buf + 2, 0, 2 * len);	/* zero all the high bytes */
-	while (len) {
-		buf [2 * len] = s->s [len - 1];
-		len--;
-	}
 	return buf [0];
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/gadget/zero.c linux-2.4.26-pre6/drivers/usb/gadget/zero.c
--- linux-2.4.25/drivers/usb/gadget/zero.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/gadget/zero.c	2004-03-25 00:17:36.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * zero.c -- Gadget Zero, for USB development
  *
- * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -101,6 +101,11 @@ static const char loopback [] = "loop in
 /*-------------------------------------------------------------------------*/
 
 /*
+ * driver assumes self-powered hardware, and
+ * has no way for users to trigger remote wakeup.
+ */
+
+/*
  * hardware-specific configuration, controlled by which device
  * controller driver was configured.
  *
@@ -108,11 +113,6 @@ static const char loopback [] = "loop in
  * DRIVER_VERSION_NUM ... alerts the host side driver to differences
  * EP_*_NAME ... which endpoints do we use for which purpose?
  * EP_*_NUM ... numbers for them (often limited by hardware)
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
- * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... if we can run on bus power, zero
- * WAKEUP ... if hardware supports remote wakeup AND we will issue the
- * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
  *
  * add other defines for other portability issues, like hardware that
  * for some reason doesn't handle full speed bulk maxpacket of 64.
@@ -136,9 +136,6 @@ static const char EP_OUT_NAME [] = "ep-a
 #define EP_OUT_NUM	2
 static const char EP_IN_NAME [] = "ep-b";
 #define EP_IN_NUM	2
-#define HIGHSPEED
-/* specific hardware configs could be bus-powered */
-/* supports remote wakeup, but this driver doesn't */
 #endif
 
 /*
@@ -159,8 +156,6 @@ static const char EP_OUT_NAME [] = "ep12
 #define EP_OUT_NUM	12
 static const char EP_IN_NAME [] = "ep11in-bulk";
 #define EP_IN_NUM	11
-/* doesn't support bus-powered operation */
-/* supports remote wakeup, but this driver doesn't */
 #endif
 
 /*
@@ -181,8 +176,6 @@ static const char EP_OUT_NAME [] = "ep1o
 #define EP_OUT_NUM	1
 static const char EP_IN_NAME [] = "ep2in-bulk";
 #define EP_IN_NUM	2
-/* doesn't support bus-powered operation */
-/* doesn't support remote wakeup? */
 #endif
 
 /*
@@ -197,7 +190,6 @@ static const char EP_OUT_NAME [] = "ep1-
 #define EP_OUT_NUM	1
 static const char EP_IN_NAME [] = "ep2-bulk";
 #define EP_IN_NUM	2
-/* doesn't support remote wakeup */
 #endif
 
 /*-------------------------------------------------------------------------*/
@@ -206,30 +198,6 @@ static const char EP_IN_NAME [] = "ep2-b
 #	error Configure some USB peripheral controller driver!
 #endif
 
-/* power usage is config specific.
- * hardware that supports remote wakeup defaults to disabling it.
- */
-
-#ifndef	SELFPOWER
-/* default: say we're self-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* else:
- * - SELFPOWER value must be zero
- * - MAX_USB_POWER may be nonzero.
- */
-#endif
-
-#ifndef	MAX_USB_POWER
-/* any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER	100	/* mA */
-#endif
-
-#ifndef	WAKEUP
-/* default: this driver won't do remote wakeup */
-#define WAKEUP		0
-/* else value must be USB_CONFIG_ATT_WAKEUP */
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 /* big enough to hold our biggest descriptor */
@@ -284,8 +252,8 @@ static unsigned pattern = 0;
 /*
  * Normally the "loopback" configuration is second (index 1) so
  * it's not the default.  Here's where to change that order, to
- * work better with hosts (like Linux ... for now!) where config
- * changes are problematic.
+ * work better with hosts where config changes are problematic.
+ * Or controllers (like superh) that only support one config.
  */
 static int loopdefault = 0;
 
@@ -306,7 +274,7 @@ MODULE_PARM_DESC (loopdefault, "true to 
 
 /* Thanks to NetChip Technologies for donating this product ID.
  *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
 #define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
@@ -358,8 +326,8 @@ source_sink_config = {
 	.bNumInterfaces =	1,
 	.bConfigurationValue =	CONFIG_SOURCE_SINK,
 	.iConfiguration =	STRING_SOURCE_SINK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,	/* self-powered */
 };
 
 static const struct usb_config_descriptor
@@ -371,8 +339,8 @@ loopback_config = {
 	.bNumInterfaces =	1,
 	.bConfigurationValue =	CONFIG_LOOPBACK,
 	.iConfiguration =	STRING_LOOPBACK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,	/* self-powered */
 };
 
 /* one interface in each configuration */
@@ -419,7 +387,21 @@ fs_sink_desc = {
 	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-#ifdef	HIGHSPEED
+static const struct usb_descriptor_header *fs_source_sink_function [] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	0,
+};
+
+static const struct usb_descriptor_header *fs_loopback_function [] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	0,
+};
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 
 /*
  * usb 2.0 devices need to expose both high speed and full speed
@@ -430,22 +412,20 @@ fs_sink_desc = {
  * for the config descriptor.
  */
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 };
@@ -461,6 +441,20 @@ dev_qualifier = {
 	.bNumConfigurations =	2,
 };
 
+static const struct usb_descriptor_header *hs_source_sink_function [] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
+};
+
+static const struct usb_descriptor_header *hs_loopback_function [] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
+};
+
 /* maxpacket and other transfer characteristics vary by speed. */
 #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
 
@@ -469,13 +463,14 @@ dev_qualifier = {
 /* if there's no high speed support, maxpacket doesn't change. */
 #define ep_desc(g,hs,fs) fs
 
-#endif	/* !HIGHSPEED */
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
+static char				manufacturer [40];
 static char				serial [40];
 
 /* static strings, in iso 8859/1 */
 static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, },
+	{ STRING_MANUFACTURER, manufacturer, },
 	{ STRING_PRODUCT, longname, },
 	{ STRING_SERIAL, serial, },
 	{ STRING_LOOPBACK, loopback, },
@@ -507,60 +502,42 @@ static struct usb_gadget_strings	stringt
  * device?)
  */
 static int
-config_buf (enum usb_device_speed speed,
+config_buf (struct usb_gadget *gadget,
 		u8 *buf, u8 type, unsigned index)
 {
-	int		is_source_sink;
-	const unsigned	config_len = USB_DT_CONFIG_SIZE
-				+ USB_DT_INTERFACE_SIZE
-				+ 2 * USB_DT_ENDPOINT_SIZE;
-#ifdef HIGHSPEED
-	int		hs;
+	int				is_source_sink;
+	int				len;
+	const struct usb_descriptor_header **function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int				hs = (gadget->speed == USB_SPEED_HIGH);
 #endif
+
 	/* two configurations will always be index 0 and index 1 */
 	if (index > 1)
 		return -EINVAL;
-	if (config_len > USB_BUFSIZ)
-		return -EDOM;
 	is_source_sink = loopdefault ? (index == 1) : (index == 0);
 
-	/* config (or other speed config) */
-	if (is_source_sink)
-		memcpy (buf, &source_sink_config, USB_DT_CONFIG_SIZE);
-	else
-		memcpy (buf, &loopback_config, USB_DT_CONFIG_SIZE);
-	buf [1] = type;
-	((struct usb_config_descriptor *) buf)->wTotalLength
-		= __constant_cpu_to_le16 (config_len);
-	buf += USB_DT_CONFIG_SIZE;
-
-	/* one interface */
-	if (is_source_sink)
-		memcpy (buf, &source_sink_intf, USB_DT_INTERFACE_SIZE);
-	else
-		memcpy (buf, &loopback_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	/* the endpoints in that interface (at that speed) */
-#ifdef HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-	if (hs) {
-		memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	} else
+	if (hs)
+		function = is_source_sink
+			? hs_source_sink_function
+			: hs_loopback_function;
+	else
 #endif
-	{
-		memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	}
-
-	return config_len;
+		function = is_source_sink
+			? fs_source_sink_function
+			: fs_loopback_function;
+
+	len = usb_gadget_config_buf (is_source_sink
+					? &source_sink_config
+					: &loopback_config,
+			buf, USB_BUFSIZ, function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1024,17 +1001,21 @@ zero_setup (struct usb_gadget *gadget, c
 			value = min (ctrl->wLength, (u16) sizeof device_desc);
 			memcpy (req->buf, &device_desc, value);
 			break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget->is_dualspeed)
+				break;
 			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
+			if (!gadget->is_dualspeed)
+				break;
 			// FALLTHROUGH
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
-			value = config_buf (gadget->speed, req->buf,
+			value = config_buf (gadget, req->buf,
 					ctrl->wValue >> 8,
 					ctrl->wValue & 0xff);
 			if (value >= 0)
@@ -1217,14 +1198,26 @@ zero_bind (struct usb_gadget *gadget)
 	dev->req->complete = zero_setup_complete;
 
 	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef HIGHSPEED
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	/* assume ep0 uses the same value for both speeds ... */
 	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 #endif
 
 	gadget->ep0->driver_data = dev;
 
 	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
+	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
+		EP_OUT_NAME, EP_IN_NAME);
+
+	snprintf (manufacturer, sizeof manufacturer,
+		UTS_SYSNAME " " UTS_RELEASE " with %s",
+		gadget->name);
+
 	return 0;
 
 enomem:
@@ -1235,7 +1228,7 @@ enomem:
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver zero_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
 #else
 	.speed		= USB_SPEED_FULL,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/hcd.c linux-2.4.26-pre6/drivers/usb/hcd.c
--- linux-2.4.25/drivers/usb/hcd.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/hcd.c	2004-03-25 00:19:41.000000000 +0000
@@ -1201,25 +1201,27 @@ static int hcd_submit_urb (struct urb *u
 		return status;
 
 	// NOTE:  2.5 does this if !URB_NO_DMA_MAP transfer flag
-	if (usb_pipecontrol (urb->pipe))
-		urb->setup_dma = pci_map_single (
-				hcd->pdev,
-				urb->setup_packet,
-				sizeof (struct usb_ctrlrequest),
-				PCI_DMA_TODEVICE);
-	if (urb->transfer_buffer_length != 0)
-		urb->transfer_dma = pci_map_single (
-				hcd->pdev,
-				urb->transfer_buffer,
-				urb->transfer_buffer_length,
-				usb_pipein (urb->pipe)
-				    ? PCI_DMA_FROMDEVICE
-				    : PCI_DMA_TODEVICE);
-
-	if (urb->dev == hcd->bus->root_hub)
+	
+	/* For 2.4, don't map bounce buffer if it's a root hub operation. */
+	if (urb->dev == hcd->bus->root_hub) {
 		status = rh_urb_enqueue (hcd, urb);
-	else
+	} else {
+		if (usb_pipecontrol (urb->pipe))
+			urb->setup_dma = pci_map_single (
+					hcd->pdev,
+					urb->setup_packet,
+					sizeof (struct usb_ctrlrequest),
+					PCI_DMA_TODEVICE);
+		if (urb->transfer_buffer_length != 0)
+			urb->transfer_dma = pci_map_single (
+					hcd->pdev,
+					urb->transfer_buffer,
+					urb->transfer_buffer_length,
+					usb_pipein (urb->pipe)
+					    ? PCI_DMA_FROMDEVICE
+					    : PCI_DMA_TODEVICE);
 		status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+	}
 	return status;
 }
 
@@ -1471,6 +1473,11 @@ static void hcd_irq (int irq, void *__hc
  */
 void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
 {
+	int is_root_hub_operation;
+
+	/* Work this out here as urb_unlink clears urb->dev */
+	is_root_hub_operation = (urb->dev == hcd->bus->root_hub);
+
 	urb_unlink (urb);
 
 	// NOTE:  a generic device/urb monitoring hook would go here.
@@ -1480,11 +1487,14 @@ void usb_hcd_giveback_urb (struct usb_hc
 	// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
 
 	// NOTE:  2.5 does this if !URB_NO_DMA_MAP transfer flag
-	if (usb_pipecontrol (urb->pipe))
+	
+	/* For 2.4, don't unmap bounce buffer if it's a root hub operation. */
+	if (usb_pipecontrol (urb->pipe) && !is_root_hub_operation)
 		pci_unmap_single (hcd->pdev, urb->setup_dma,
 				sizeof (struct usb_ctrlrequest),
 				PCI_DMA_TODEVICE);
-	if (urb->transfer_buffer_length != 0)
+
+	if ((urb->transfer_buffer_length != 0) && !is_root_hub_operation)
 		pci_unmap_single (hcd->pdev, urb->transfer_dma,
 				urb->transfer_buffer_length,
 				usb_pipein (urb->pipe)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/hid-core.c linux-2.4.26-pre6/drivers/usb/hid-core.c
--- linux-2.4.25/drivers/usb/hid-core.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/hid-core.c	2004-03-25 00:20:21.000000000 +0000
@@ -243,6 +243,9 @@ static int hid_add_field(struct hid_pars
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
+	if (usages < parser->global.report_count)
+		usages = parser->global.report_count;
+
 	if (usages == 0)
 		return 0; /* ignore padding fields */
 
@@ -254,9 +257,13 @@ static int hid_add_field(struct hid_pars
 	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
 	for (i = 0; i < usages; i++) {
-		field->usage[i].hid = parser->local.usage[i];
+		int j = i;
+		/* Duplicate the last usage we parsed if we have excess values */
+		if (i >= parser->local.usage_index)
+			j = parser->local.usage_index - 1;
+		field->usage[i].hid = parser->local.usage[j];
 		field->usage[i].collection_index =
-			parser->local.collection_index[i];
+			parser->local.collection_index[j];
 	}
 
 	field->maxusage = usages;
@@ -1182,7 +1189,10 @@ void hid_init_reports(struct hid_device 
 #define USB_VENDOR_ID_MGE		0x0463
 #define USB_DEVICE_ID_MGE_UPS		0xffff
 #define USB_DEVICE_ID_MGE_UPS1		0x0001
- 
+
+#define USB_VENDOR_ID_NEC		0x073e
+#define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
+
 struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
@@ -1237,6 +1247,7 @@ struct hid_blacklist {
 	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
 	{ 0, 0 }
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/hid-input.c linux-2.4.26-pre6/drivers/usb/hid-input.c
--- linux-2.4.25/drivers/usb/hid-input.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/hid-input.c	2004-03-25 00:19:23.000000000 +0000
@@ -444,8 +444,10 @@ int hidinput_connect(struct hid_device *
 		while (list != &report_enum->report_list) {
 			report = (struct hid_report *) list;
 
-			if (!report->maxfield)
+			if (!report->maxfield) {
+				list = list->next;
 				continue;
+			}
 
 			if (!hidinput) {
 				hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/hiddev.c linux-2.4.26-pre6/drivers/usb/hiddev.c
--- linux-2.4.25/drivers/usb/hiddev.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/hiddev.c	2004-03-25 00:19:26.000000000 +0000
@@ -396,7 +396,8 @@ static int hiddev_ioctl(struct inode *in
 	struct hiddev_collection_info cinfo;
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
-	struct hiddev_usage_ref uref;
+	struct hiddev_usage_ref_multi uref_multi;
+	struct hiddev_usage_ref *uref = &uref_multi.uref;
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
 	struct hid_field *field;
@@ -554,64 +555,93 @@ static int hiddev_ioctl(struct inode *in
 		return copy_to_user((void *) arg, &finfo, sizeof(finfo));
 
 	case HIDIOCGUCODE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+		if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
 			return -EFAULT;
 
-		rinfo.report_type = uref.report_type;
-		rinfo.report_id = uref.report_id;
+		rinfo.report_type = uref->report_type;
+		rinfo.report_id = uref->report_id;
 		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 			return -EINVAL;
 
-		if (uref.field_index >= report->maxfield)
+		if (uref->field_index >= report->maxfield)
 			return -EINVAL;
 
-		field = report->field[uref.field_index];
-		if (uref.usage_index >= field->maxusage)
+		field = report->field[uref->field_index];
+		if (uref->usage_index >= field->maxusage)
 			return -EINVAL;
 
-		uref.usage_code = field->usage[uref.usage_index].hid;
+		uref->usage_code = field->usage[uref->usage_index].hid;
 
-		return copy_to_user((void *) arg, &uref, sizeof(uref));
+		return copy_to_user((void *) arg, uref, sizeof(*uref));
 
 	case HIDIOCGUSAGE:
 	case HIDIOCSUSAGE:
+	case HIDIOCGUSAGES:
+	case HIDIOCSUSAGES:
 	case HIDIOCGCOLLECTIONINDEX:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
+		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+			if (copy_from_user(&uref_multi, (void *) arg, 
+					   sizeof(uref_multi)))
+				return -EFAULT;
+		} else {
+			if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
+				return -EFAULT;
+		}
 
-		if (cmd == HIDIOCSUSAGE &&
-		    uref.report_type == HID_REPORT_TYPE_INPUT)
+		if (cmd != HIDIOCGUSAGE && 
+		    cmd != HIDIOCGUSAGES &&
+		    uref->report_type == HID_REPORT_TYPE_INPUT)
 			return -EINVAL;
 
-		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, &uref);
+		if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
+			field = hiddev_lookup_usage(hid, uref);
 			if (field == NULL)
 				return -EINVAL;
 		} else {
-			rinfo.report_type = uref.report_type;
-			rinfo.report_id = uref.report_id;
+			rinfo.report_type = uref->report_type;
+			rinfo.report_id = uref->report_id;
 			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 				return -EINVAL;
 
-			if (uref.field_index >= report->maxfield)
+			if (uref->field_index >= report->maxfield)
 				return -EINVAL;
 
-			field = report->field[uref.field_index];
-			if (uref.usage_index >= field->maxusage)
+			field = report->field[uref->field_index];
+			if (uref->usage_index >= field->maxusage)
 				return -EINVAL;
+
+			if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+				if (uref_multi.num_values >= HID_MAX_USAGES || 
+				    uref->usage_index >= field->maxusage || 
+				   (uref->usage_index + uref_multi.num_values) >= field->maxusage)
+					return -EINVAL;
+			}
 		}
 
 		switch (cmd) {
 		case HIDIOCGUSAGE:
-			uref.value = field->value[uref.usage_index];
-			return copy_to_user((void *) arg, &uref, sizeof(uref));
+			uref->value = field->value[uref->usage_index];
+			return copy_to_user((void *) arg, uref, sizeof(*uref));
 
 		case HIDIOCSUSAGE:
-			field->value[uref.usage_index] = uref.value;
+			field->value[uref->usage_index] = uref->value;
 			return 0;
 
 		case HIDIOCGCOLLECTIONINDEX:
-			return field->usage[uref.usage_index].collection_index;
+			return field->usage[uref->usage_index].collection_index;
+		case HIDIOCGUSAGES:
+			for (i = 0; i < uref_multi.num_values; i++)
+				uref_multi.values[i] = 
+				    field->value[uref->usage_index + i];
+			if (copy_to_user((void *) arg, &uref_multi, 
+					 sizeof(uref_multi)))
+				return -EFAULT;
+			return 0;
+		case HIDIOCSUSAGES:
+			for (i = 0; i < uref_multi.num_values; i++)
+				field->value[uref->usage_index + i] = 
+				    uref_multi.values[i];
+			return 0;
 		}
 		break;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/host/ehci-dbg.c linux-2.4.26-pre6/drivers/usb/host/ehci-dbg.c
--- linux-2.4.25/drivers/usb/host/ehci-dbg.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/host/ehci-dbg.c	2004-03-25 00:20:04.000000000 +0000
@@ -377,7 +377,7 @@ static void qh_lines (
 			scratch, cpu_to_le32p (&qh->hw_info2),
 			cpu_to_le32p (&qh->hw_token), mark,
 			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
-				? "data0" : "data1",
+				? "data1" : "data0",
 			(cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f);
 	size -= temp;
 	next += temp;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/host/ehci-hub.c linux-2.4.26-pre6/drivers/usb/host/ehci-hub.c
--- linux-2.4.25/drivers/usb/host/ehci-hub.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/host/ehci-hub.c	2004-03-25 00:20:34.000000000 +0000
@@ -113,7 +113,7 @@ ehci_hub_descriptor (
 	u16		temp;
 
 	desc->bDescriptorType = 0x29;
-	desc->bPwrOn2PwrGood = 0;	/* FIXME: f(system power) */
+	desc->bPwrOn2PwrGood = 10;	/* ehci 1.0, 2.3.9 says 20ms max */
 	desc->bHubContrCurrent = 0;
 
 	desc->bNbrPorts = ports;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/host/ehci-sched.c linux-2.4.26-pre6/drivers/usb/host/ehci-sched.c
--- linux-2.4.25/drivers/usb/host/ehci-sched.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/host/ehci-sched.c	2004-03-25 00:18:53.000000000 +0000
@@ -490,33 +490,6 @@ done:
 	return status;
 }
 
-static unsigned
-intr_complete (
-	struct ehci_hcd	*ehci,
-	unsigned	frame,
-	struct ehci_qh	*qh,
-	struct pt_regs	*regs
-) {
-	unsigned	count;
-
-	/* nothing to report? */
-	if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
-			!= 0))
-		return 0;
-	if (unlikely (list_empty (&qh->qtd_list))) {
-		dbg ("intr qh %p no TDs?", qh);
-		return 0;
-	}
-	
-	/* handle any completions */
-	count = qh_completions (ehci, qh, regs);
-
-	if (unlikely (list_empty (&qh->qtd_list)))
-		intr_deschedule (ehci, qh, 0);
-
-	return count;
-}
-
 /*-------------------------------------------------------------------------*/
 
 static inline struct ehci_iso_stream *
@@ -718,7 +691,8 @@ itd_sched_init (
 
 		trans = EHCI_ISOC_ACTIVE;
 		trans |= buf & 0x0fff;
-		if (unlikely ((i + 1) == urb->number_of_packets))
+		if (unlikely (((i + 1) == urb->number_of_packets))
+				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
 			trans |= EHCI_ITD_IOC;
 		trans |= length << 16;
 		uframe->transaction = cpu_to_le32 (trans);
@@ -809,7 +783,10 @@ itd_urb_transaction (
  * periodic schedule slots.  (Affected by TUNE_FLS, which defaults to
  * "as small as possible" to be cache-friendlier.)  That limits the size
  * transfers you can stream reliably; avoid more than 64 msec per urb.
- * Also avoid queue depths of less than the system's worst irq latency.
+ * Also avoid queue depths of less than ehci's worst irq latency (affected
+ * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter,
+ * and other factors); or more than about 230 msec total (for portability,
+ * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
 #define SCHEDULE_SLOP	10	/* frames */
@@ -1236,7 +1213,7 @@ static void
 scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
 	unsigned	frame, clock, now_uframe, mod;
-	unsigned	count = 0;
+	unsigned	modified;
 
 	mod = ehci->periodic_size << 3;
 
@@ -1247,47 +1224,50 @@ scan_periodic (struct ehci_hcd *ehci, st
 	 */
 	now_uframe = ehci->next_uframe;
 	if (HCD_IS_RUNNING (ehci->hcd.state))
-		clock = readl (&ehci->regs->frame_index) % mod;
+		clock = readl (&ehci->regs->frame_index);
 	else
 		clock = now_uframe + mod - 1;
+	clock %= mod;
 
 	for (;;) {
 		union ehci_shadow	q, *q_p;
 		u32			type, *hw_p;
 		unsigned		uframes;
 
+		/* don't scan past the live uframe */
 		frame = now_uframe >> 3;
-restart:
-		/* scan schedule to _before_ current frame index */
-		if ((frame == (clock >> 3))
-				&& HCD_IS_RUNNING (ehci->hcd.state))
+		if (frame == (clock >> 3))
 			uframes = now_uframe & 0x07;
-		else
+		else {
+			/* safe to scan the whole frame at once */
+			now_uframe |= 0x07;
 			uframes = 8;
+		}
 
+restart:
+		/* scan each element in frame's queue for completions */
 		q_p = &ehci->pshadow [frame];
 		hw_p = &ehci->periodic [frame];
 		q.ptr = q_p->ptr;
 		type = Q_NEXT_TYPE (*hw_p);
+		modified = 0;
 
-		/* scan each element in frame's queue for completions */
 		while (q.ptr != 0) {
-			int			last;
 			unsigned		uf;
 			union ehci_shadow	temp;
 
 			switch (type) {
 			case Q_TYPE_QH:
-				last = (q.qh->hw_next == EHCI_LIST_END);
-				temp = q.qh->qh_next;
+				/* handle any completions */
+				temp.qh = qh_get (q.qh);
 				type = Q_NEXT_TYPE (q.qh->hw_next);
-				count += intr_complete (ehci, frame,
-						qh_get (q.qh), regs);
-				qh_put (ehci, q.qh);
-				q = temp;
+				q = q.qh->qh_next;
+				modified = qh_completions (ehci, temp.qh, regs);
+				if (unlikely (list_empty (&temp.qh->qtd_list)))
+					intr_deschedule (ehci, temp.qh, 0);
+				qh_put (ehci, temp.qh);
 				break;
 			case Q_TYPE_FSTN:
-				last = (q.fstn->hw_next == EHCI_LIST_END);
 				/* for "save place" FSTNs, look at QH entries
 				 * in the previous frame for completions.
 				 */
@@ -1298,8 +1278,6 @@ restart:
 				q = q.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
-				last = (q.itd->hw_next == EHCI_LIST_END);
-
 				/* skip itds for later in the frame */
 				rmb ();
 				for (uf = uframes; uf < 8; uf++) {
@@ -1320,31 +1298,24 @@ restart:
 				 */
 				*q_p = q.itd->itd_next;
 				*hw_p = q.itd->hw_next;
+				type = Q_NEXT_TYPE (q.itd->hw_next);
 				wmb();
-
-				/* always rescan here; simpler */
-				count += itd_complete (ehci, q.itd, regs);
-				goto restart;
+				modified = itd_complete (ehci, q.itd, regs);
+				q = *q_p;
+				break;
 #ifdef have_split_iso
 			case Q_TYPE_SITD:
-				last = (q.sitd->hw_next == EHCI_LIST_END);
-				sitd_complete (ehci, q.sitd);
-				type = Q_NEXT_TYPE (q.sitd->hw_next);
-
-				// FIXME unlink SITD after split completes
-				q = q.sitd->sitd_next;
-				break;
+				// nyet!
 #endif /* have_split_iso */
 			default:
 				dbg ("corrupt type %d frame %d shadow %p",
 					type, frame, q.ptr);
 				// BUG ();
-				last = 1;
 				q.ptr = 0;
 			}
 
-			/* did completion remove an interior q entry? */
-			if (unlikely (q.ptr == 0 && !last))
+			/* assume completion callbacks modify the queue */
+			if (unlikely (modified))
 				goto restart;
 		}
 
@@ -1371,9 +1342,6 @@ restart:
 			/* rescan the rest of this frame, then ... */
 			clock = now;
 		} else {
-			/* FIXME sometimes we can scan the next frame
-			 * right away, not always inching up on it ...
-			 */
 			now_uframe++;
 			now_uframe %= mod;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/pegasus.h linux-2.4.26-pre6/drivers/usb/pegasus.h
--- linux-2.4.25/drivers/usb/pegasus.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/pegasus.h	2004-03-25 00:22:19.000000000 +0000
@@ -126,6 +126,7 @@ struct usb_eth_dev {
 #define	VENDOR_DLINK		0x2001
 #define VENDOR_ELCON		0x0db7
 #define	VENDOR_ELSA		0x05cc
+#define	VENDOR_GIGABYTE		0x1044
 #define	VENDOR_HAWKING		0x0e66
 #define	VENDOR_HP		0x03f0
 #define	VENDOR_IODATA		0x04bb
@@ -221,6 +222,8 @@ PEGASUS_DEV( "EasiDock Ethernet", VENDOR
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
 		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002,
+		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c,
@@ -263,6 +266,8 @@ PEGASUS_DEV( "NETGEAR FA101", VENDOR_NET
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "OCT USB TO Ethernet", VENDOR_OCT, 0x0901,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/printer.c linux-2.4.26-pre6/drivers/usb/printer.c
--- linux-2.4.25/drivers/usb/printer.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/printer.c	2004-03-25 00:18:01.000000000 +0000
@@ -604,14 +604,16 @@ static ssize_t usblp_write(struct file *
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct usblp *usblp = file->private_data;
-	int timeout, err = 0;
+	int timeout, err = 0, transfer_length = 0;
 	size_t writecount = 0;
 
 	while (writecount < count) {
 		if (!usblp->wcomplete) {
 			barrier();
-			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
+			if (file->f_flags & O_NONBLOCK) {
+				writecount += transfer_length;
+				return writecount ? writecount : -EAGAIN;
+			}
 
 			timeout = USBLP_WRITE_TIMEOUT;
 			add_wait_queue(&usblp->wait, &wait);
@@ -655,27 +657,36 @@ static ssize_t usblp_write(struct file *
 			continue;
 		}
 
-		writecount += usblp->writeurb->transfer_buffer_length;
-		usblp->writeurb->transfer_buffer_length = 0;
-
+		/* We must increment writecount here, and not at the
+		 * end of the loop. Otherwise, the final loop iteration may
+		 * be skipped, leading to incomplete printer output.
+		 */
+		writecount += transfer_length;
 		if (writecount == count) {
 			up (&usblp->sem);
 			break;
 		}
 
-		usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
-							  (count - writecount) : USBLP_BUF_SIZE;
+		transfer_length = count - writecount;
+		if(transfer_length > USBLP_BUF_SIZE) 
+			transfer_length = USBLP_BUF_SIZE;
+		
+		usblp->writeurb->transfer_buffer_length = transfer_length;
 
-		if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount,
-				usblp->writeurb->transfer_buffer_length)) {
+		if (copy_from_user(usblp->writeurb->transfer_buffer, 
+				   buffer + writecount, transfer_length)) {
 			up(&usblp->sem);
 			return writecount ? writecount : -EFAULT;
 		}
 
 		usblp->writeurb->dev = usblp->dev;
 		usblp->wcomplete = 0;
-		if (usb_submit_urb(usblp->writeurb)) {
-			count = -EIO;
+		err = usb_submit_urb(usblp->writeurb);
+		if (err) {
+			if (err != -ENOMEM)
+				count = -EIO;
+			else
+				count = writecount ? writecount : -ENOMEM;
 			up (&usblp->sem);
 			break;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/ftdi_sio.c linux-2.4.26-pre6/drivers/usb/serial/ftdi_sio.c
--- linux-2.4.25/drivers/usb/serial/ftdi_sio.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/serial/ftdi_sio.c	2004-03-25 00:21:20.000000000 +0000
@@ -17,6 +17,11 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (09/Feb/2004) Ian Abbott
+ *      Changed full name of USB-UIRT device to avoid "/" character.
+ *      Added FTDI's alternate PID (0x6006) for FT232/245 devices.
+ *      Added PID for "ELV USB Module UO100" from Stefan Frings.
+ * 
  * (21/Oct/2003) Ian Abbott
  *      Renamed some VID/PID macros for Matrix Orbital and Perle Systems
  *      devices.  Removed Matrix Orbital and Perle Systems devices from the
@@ -272,8 +277,12 @@ static struct usb_device_id id_table_sio
 
 
 static struct usb_device_id id_table_8U232AM [] = {
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
+	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
+	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
@@ -337,12 +346,15 @@ static struct usb_device_id id_table_8U2
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
 	{ }						/* Terminating entry */
 };
 
 
 static struct usb_device_id id_table_FT232BM [] = {
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
@@ -415,6 +427,7 @@ static struct usb_device_id id_table_FT2
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
@@ -432,9 +445,13 @@ static struct usb_device_id id_table_HE_
 
 
 static __devinitdata struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
+	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
+	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
@@ -508,6 +525,7 @@ static __devinitdata struct usb_device_i
 	{ USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
 	{ }						/* Terminating entry */
 };
 
@@ -652,7 +670,7 @@ static struct usb_serial_device_type ftd
 
 static struct usb_serial_device_type ftdi_USB_UIRT_device = {
 	.owner =		THIS_MODULE,
-	.name =			"USB-UIRT Infrared Receiver/Transmitter",
+	.name =			"USB-UIRT Infrared Tranceiver",
 	.id_table =		id_table_USB_UIRT,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/ftdi_sio.h linux-2.4.26-pre6/drivers/usb/serial/ftdi_sio.h
--- linux-2.4.25/drivers/usb/serial/ftdi_sio.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/serial/ftdi_sio.h	2004-03-25 00:21:44.000000000 +0000
@@ -25,10 +25,13 @@
 #define FTDI_VID	0x0403	/* Vendor Id */
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
+#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
 
+/* www.irtrans.de device */
+#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
 
 /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
 /* they use the ftdi chipset for the USB interface and the vendor id is the same */
@@ -58,6 +61,12 @@
 #define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
 #define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
 
+/* Interbiometrics USB I/O Board */
+/* Developed for Interbiometrics by Rudolf Gugler */
+#define INTERBIOMETRICS_VID              0x1209
+#define INTERBIOMETRICS_IOBOARD_PID      0x1002
+#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006
+
 /*
  * The following are the values for the Perle Systems
  * UltraPort USB serial converters
@@ -132,6 +141,9 @@
 /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
 #define FTDI_USB_UIRT_PID	0xF850	/* Product Id */
 
+/* ELV USB Module UO100 (PID sent by Stefan Frings) */
+#define FTDI_ELV_UO100_PID	0xFB58	/* Product Id */
+
 /*
  * Definitions for ID TECH (www.idt-net.com) devices
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/io_edgeport.c linux-2.4.26-pre6/drivers/usb/serial/io_edgeport.c
--- linux-2.4.25/drivers/usb/serial/io_edgeport.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/serial/io_edgeport.c	2004-03-25 00:17:22.000000000 +0000
@@ -1760,7 +1760,7 @@ static int set_modem_info(struct edgepor
 			if (arg & TIOCM_RTS)
 				mcr |= MCR_RTS;
 			if (arg & TIOCM_DTR)
-				mcr |= MCR_RTS;
+				mcr |= MCR_DTR;
 			if (arg & TIOCM_LOOP)
 				mcr |= MCR_LOOPBACK;
 			break;
@@ -1769,7 +1769,7 @@ static int set_modem_info(struct edgepor
 			if (arg & TIOCM_RTS)
 				mcr &= ~MCR_RTS;
 			if (arg & TIOCM_DTR)
-				mcr &= ~MCR_RTS;
+				mcr &= ~MCR_DTR;
 			if (arg & TIOCM_LOOP)
 				mcr &= ~MCR_LOOPBACK;
 			break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/pl2303.c linux-2.4.26-pre6/drivers/usb/serial/pl2303.c
--- linux-2.4.25/drivers/usb/serial/pl2303.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/serial/pl2303.c	2004-03-25 00:19:39.000000000 +0000
@@ -390,7 +390,7 @@ static int pl2303_open (struct usb_seria
 {
 	struct termios tmp_termios;
 	struct usb_serial *serial = port->serial;
-	unsigned char buf[10];
+	unsigned char *buf;
 	int result;
 
 	if (port_paranoia_check (port, __FUNCTION__))
@@ -401,6 +401,10 @@ static int pl2303_open (struct usb_seria
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
 
+	buf = kmalloc(10, GFP_KERNEL);
+	if (buf==NULL)
+		return -ENOMEM;
+
 #define FISH(a,b,c,d)								\
 	result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
 			       b, a, c, d, buf, 1, 100);			\
@@ -420,6 +424,8 @@ static int pl2303_open (struct usb_seria
 	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
 	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
 
+	kfree(buf);
+
 	/* Setup termios */
 	if (port->tty) {
 		pl2303_set_termios (port, &tmp_termios);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/visor.c linux-2.4.26-pre6/drivers/usb/serial/visor.c
--- linux-2.4.25/drivers/usb/serial/visor.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/serial/visor.c	2004-03-25 00:18:43.000000000 +0000
@@ -215,6 +215,7 @@ static struct usb_device_id id_table [] 
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
+	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -247,6 +248,7 @@ static __devinitdata struct usb_device_i
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
+	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
 	{ }					/* Terminating entry */
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/visor.h linux-2.4.26-pre6/drivers/usb/serial/visor.h
--- linux-2.4.25/drivers/usb/serial/visor.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/serial/visor.h	2004-03-25 00:21:34.000000000 +0000
@@ -50,6 +50,9 @@
 #define GARMIN_VENDOR_ID		0x091E
 #define GARMIN_IQUE_3600_ID		0x0004
 
+#define ACEECA_VENDOR_ID		0x4766
+#define ACEECA_MEZ1000_ID		0x0001
+
 /****************************************************************************
  * Handspring Visor Vendor specific request codes (bRequest values)
  * A big thank you to Handspring for providing the following information.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/storage/scsiglue.c linux-2.4.26-pre6/drivers/usb/storage/scsiglue.c
--- linux-2.4.25/drivers/usb/storage/scsiglue.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/storage/scsiglue.c	2004-03-25 00:19:56.000000000 +0000
@@ -213,9 +213,14 @@ static int command_abort( Scsi_Cmnd *srb
 static int device_reset( Scsi_Cmnd *srb )
 {
 	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+	int rc;
 
 	US_DEBUGP("device_reset() called\n" );
-	return us->transport_reset(us);
+
+	spin_unlock_irq(&io_request_lock);
+	rc = us->transport_reset(us);
+	spin_lock_irq(&io_request_lock);
+	return rc;
 }
 
 /* This resets the device port, and simulates the device
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/storage/unusual_devs.h linux-2.4.26-pre6/drivers/usb/storage/unusual_devs.h
--- linux-2.4.25/drivers/usb/storage/unusual_devs.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/usb/storage/unusual_devs.h	2004-03-25 00:21:17.000000000 +0000
@@ -278,6 +278,13 @@ UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x
 		"Memorystick MSC-U01N",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
+
+/* Submitted by Michal Mlotek <mlotek@foobar.pl> */
+UNUSUAL_DEV(  0x054c, 0x0058, 0x0000, 0x9999,
+		"Sony",
+		"PEG N760c Memorystick",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
 		
 UNUSUAL_DEV(  0x054c, 0x0069, 0x0000, 0x9999,
 		"Sony",
@@ -370,7 +377,7 @@ UNUSUAL_DEV(  0x05e3, 0x0700, 0x0000, 0x
 UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff, 
 		"", 
 		"USB TO IDE",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MODE_XLATE ), 
 
 /* Reported by Peter Marks <peter.marks@turner.com>
@@ -628,6 +635,17 @@ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0001, 0x0
 		US_SC_DEVICE, US_PR_BULK, NULL,
 		US_FL_MODE_XLATE ),
 
+/* Entry needed for flags. Moreover, all devices with this ID use
+ * bulk-only transport, but _some_ falsely report Control/Bulk instead.
+ * One example is "Trumpion Digital Research MYMP3".
+ * Submitted by Bjoern Brill <brill(at)fs.math.uni-frankfurt.de>
+ */
+UNUSUAL_DEV(  0x090a, 0x1001, 0x0100, 0x0100,
+		"Trumpion",
+		"t33520 USB Flash Card Controller",
+		US_SC_DEVICE, US_PR_BULK, NULL,
+		US_FL_MODE_XLATE),
+
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
 		"Trumpion",
@@ -667,15 +685,9 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_FIX_INQUIRY ),
 
-/* This entry from <matthias@ma-c.de> in the Debian mailing list */
-UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
-		"Pentax",
-		"Optio 330GS",
-		US_SC_8070, US_PR_CB, NULL,
-		US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ),
 
 /* Submitted by Per Winkvist <per.winkvist@uk.com> */
-UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
+UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
                 "Pentax",
                 "Optio S/S4",
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/amifb.c linux-2.4.26-pre6/drivers/video/amifb.c
--- linux-2.4.25/drivers/video/amifb.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/amifb.c	2004-03-25 00:21:45.000000000 +0000
@@ -807,7 +807,7 @@ static struct fb_videomode ami_modedb[] 
 	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
 	/* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
-	"ntsc-lace", 60, 640, TAG_HIRES, 106, 86, 88, 33, 76, 4,
+	"ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
 	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
 	/* 640x256, 15 kHz, 50 Hz (PAL) */
@@ -902,7 +902,7 @@ static struct fb_videomode ami_modedb[] 
 	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
 	/* 1024x800, 15 Hz */
-	"a2024-15", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+	"a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
 	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/pm3fb.c linux-2.4.26-pre6/drivers/video/pm3fb.c
--- linux-2.4.25/drivers/video/pm3fb.c	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/pm3fb.c	2004-03-25 00:20:09.000000000 +0000
@@ -19,6 +19,7 @@
  *  $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
  *
  *  CHANGELOG:
+ *  Wed Nov 13 11:19:34 MET 2002, v 1.4.11C: option flatpanel: wasn't available in module, fixed.
  *  Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
  *  Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
  *  Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
@@ -3756,6 +3757,8 @@ MODULE_PARM(printtimings, "h");
 MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
 MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
 MODULE_PARM_DESC(forcesize, "force specified memory size");
+MODULE_PARM(flatpanel, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+MODULE_PARM_DESC(flatpanel, "flatpanel (LCD) support (preliminary)");
 /*
 MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
 MODULE_GENERIC_TABLE(gtype,name)
@@ -3800,6 +3803,11 @@ void pm3fb_build_options(void)
 			sprintf(ts, ",depth:%d:%d", i, depth[i]);
 			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
 		}
+                if (flatpanel[i])
+		{
+			sprintf(ts, ",flatpanel:%d:", i);
+			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
+		}
 	}
 	g_options[PM3_OPTIONS_SIZE - 1] = '\0';
 	DPRINTK(1, "pm3fb use options: %s\n", g_options);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/radeonfb.c linux-2.4.26-pre6/drivers/video/radeonfb.c
--- linux-2.4.25/drivers/video/radeonfb.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/radeonfb.c	2004-03-25 00:22:17.000000000 +0000
@@ -202,6 +202,8 @@ enum radeon_chips {
 	RADEON_If,
 	RADEON_Ig,
 	RADEON_Y_,
+	RADEON_Ya,
+	RADEON_Yd,
 	RADEON_Ld,
 	RADEON_Le,
 	RADEON_Lf,
@@ -261,6 +263,8 @@ static struct radeon_chip_info {
 	{ "9000 If", RADEON_RV250 },
 	{ "9000 Ig", RADEON_RV250 },
 	{ "9200 Y", RADEON_RV280 },
+	{ "9200 Ya", RADEON_RV280 },
+	{ "9200 Yd", RADEON_RV280 },
 	{ "M9 Ld", RADEON_M9 },
 	{ "M9 Le", RADEON_M9 },
 	{ "M9 Lf", RADEON_M9 },
@@ -326,6 +330,8 @@ static struct pci_device_id radeonfb_pci
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NH, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NH},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NI},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Y_, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Y_},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ya, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ya},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Yd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Yd},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AD},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AP},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AR},
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/300vtbl.h linux-2.4.26-pre6/drivers/video/sis/300vtbl.h
--- linux-2.4.25/drivers/video/sis/300vtbl.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/300vtbl.h	2004-03-25 00:17:57.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -52,20 +49,7 @@
  *
  */
 
-typedef struct _SiS300_StStruct
-{
-	UCHAR St_ModeID;
-	USHORT St_ModeFlag;
-	UCHAR St_StTableIndex;
-	UCHAR St_CRT2CRTC;
-	UCHAR St_ResInfo;
-	UCHAR VB_StTVFlickerIndex;
-	UCHAR VB_StTVEdgeIndex;
-	UCHAR VB_StTVYFilterIndex;
-	UCHAR St_PDC;
-} SiS300_StStruct;
-
-static const SiS300_StStruct  SiS300_SModeIDTable[] =
+static const SiS_StStruct  SiS300_SModeIDTable[] =
 {
 	{0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0},
 	{0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0},
@@ -89,206 +73,168 @@ static const SiS300_StStruct  SiS300_SMo
 	{0xff,     0,   0,   0,   0,   0,   0,   0, 0}
 };
 
-typedef struct _SiS300_ExtStruct
+static const SiS_ExtStruct  SiS300_EModeIDTable[] =
 {
-	UCHAR  Ext_ModeID;
-	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
-	USHORT Ext_VESAID;
-	UCHAR  Ext_RESINFO;
-	UCHAR  VB_ExtTVFlickerIndex;
-	UCHAR  VB_ExtTVEdgeIndex;
-	UCHAR  VB_ExtTVYFilterIndex;
-	UCHAR  VB_ExtTVYFilterIndexROM661;
-	UCHAR  REFindex;
-} SiS300_ExtStruct;
-
-static const SiS300_ExtStruct  SiS300_EModeIDTable[] =
-{
-	{0x6a,0x2212,0x04,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x? */
-	{0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x2f,0x021b,0x03,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x8 */
-	{0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},
-	{0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x8 */
-	{0x32,0x2a1b,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x8 */
-	{0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x16 */
-	{0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x16 */
-	{0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x32 */
-	{0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x32 */
-	{0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x? */
-	{0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x8 */
-	{0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},  /* 1280x1024x8 */
-	{0x3c,0x063b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x3d,0x067d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x40,0x921c,0x00,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x15 */
-	{0x41,0x921d,0x00,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x16 */
-	{0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x15 */
-	{0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x16 */
-	{0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x50,0x921b,0x00,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x8  */
-	{0x51,0xb21b,0x01,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x8  */
-	{0x52,0x921b,0x02,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x8  */
-	{0x56,0x921d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x16 */
-	{0x57,0xb21d,0x01,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x16 */
-	{0x58,0x921d,0x02,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x16 */
-	{0x59,0x921b,0x00,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x8  */
-	{0x5c,0x921f,0x02,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x32 */
-	{0x5d,0x021d,0x03,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x16 */
- 	{0x5e,0x021f,0x03,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x32 */
-	{0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x32 */
-	{0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x66,0x06ff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6b,0x07ff,0x08,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x8 - not in BIOS! */
-	{0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x16 - not in BIOS! */
-	{0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x8 */
-	{0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x8 */
-	{0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x16 */
-	{0x75,0x0e3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x16 */
-	{0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x32 */
-	{0x77,0x0a3f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x32 */
-	{0x78,0x0eff,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x32 */
-	{0x79,0x0e3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x8 */
-	{0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x16 */
-	{0x7c,0x0a3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x8 */
-	{0x7d,0x0a7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x16 */
-	{0x7e,0x0aff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x32 */
-	{0x20,0x0a1b,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},  /* 1024x600 */
-	{0x21,0x0a3d,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x22,0x0a7f,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x23,0x0a1b,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},  /* 1152x768 */
-	{0x24,0x0a3d,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x25,0x0a7f,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x29,0x0e1b,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},  /* 1152x864 */
-	{0x2a,0x0e3d,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x2b,0x0e7f,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x39,0x2a1b,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},  /* 848x480 */
-	{0x3b,0x2a3d,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3e,0x2a7f,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3f,0x2a1b,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},  /* 856x480 */
-	{0x42,0x2a3d,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x45,0x2a7f,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x48,0x223b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},  /* 1360x768 */
-	{0x4b,0x227d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4e,0x22ff,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4f,0x921f,0x00,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x32 */
-	{0x53,0x921f,0x00,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x32 */
-	{0x54,0xb21f,0x01,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x32 */
-	{0x55,0x2e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},  /* 1280x768   */
-	{0x5a,0x2e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5b,0x2eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x8 */
-	{0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x16 */
-	{0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x32 */
-	{0x67,0x2e3b,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x8 (BARCO) */
-	{0x6f,0x2e7d,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x16 (BARCO) */
-	{0x72,0x2eff,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x32 (BARCO) */
-	{0xff,0x0000,0x00,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-typedef struct _SiS300_Ext2Struct
-{
-	USHORT Ext_InfoFlag;
-	UCHAR  Ext_CRT1CRTC;  /* Index in SiS300_CRT1Table */
-	UCHAR  Ext_CRTVCLK;   /* Index in VCLK array */
-	UCHAR  Ext_CRT2CRTC;  /* Index in LCD Paneltype arrays (&3f) */
-	UCHAR  ModeID;
-	USHORT XRes;
-	USHORT YRes;
-	UCHAR  Ext_PDC;
-} SiS300_Ext2Struct;
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
+	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},
+	{0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x8 */
+	{0x32,0x2a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x8 */
+	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x16 */
+	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x16 */
+	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x32 */
+	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},  /* 1280x1024x8 */
+	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
+	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
+	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x15 */
+	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x15 */
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
+	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x8  */
+	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x8  */
+	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x8  */
+	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x16 */
+	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x16 */
+	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x16 */
+	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x8  */
+	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x32 */
+	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x16 */
+ 	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
+	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
+	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x8 - not in BIOS! */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x16 - not in BIOS! */
+	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x8 */
+	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x8 */
+	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x16 */
+	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x16 */
+	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x32 */
+	{0x77,0x0a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x32 */
+	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x32 */
+	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x8 */
+	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x16 */
+	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x8 */
+	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x16 */
+	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x32 */
+	{0x20,0x0a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},  /* 1024x600 */
+	{0x21,0x0a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
+	{0x22,0x0a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
+	{0x23,0x0a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},  /* 1152x768 */
+	{0x24,0x0a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
+	{0x25,0x0a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
+	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},  /* 1152x864 */
+	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
+	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
+	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},  /* 848x480 */
+	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
+	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
+	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},  /* 856x480 */
+	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
+	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
+	{0x48,0x223b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},  /* 1360x768 */
+	{0x4b,0x227d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
+	{0x4e,0x22ff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
+	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x32 */
+	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x32 */
+	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x32 */
+	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},  /* 1280x768   */
+	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
+	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
+	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x8 */
+	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x16 */
+	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x32 */
+	{0x67,0x2e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x8 (BARCO) */
+	{0x6f,0x2e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x16 (BARCO) */
+	{0x72,0x2eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x32 (BARCO) */
+	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
+};
 
-static const SiS300_Ext2Struct  SiS300_RefIndex[] =
+static const SiS_Ext2Struct  SiS300_RefIndex[] =
 { 
-	{0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0}, /* 00 */
-	{0x0467,0x0e,0x44,0x05,0x6a, 800, 600, 0}, /* 01 */
-	{0x0067,0x0f,0x07,0x48,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
-	{0x0067,0x10,0x06,0x8b,0x6a, 800, 600, 0}, /* 03 */
-	{0x0147,0x11,0x08,0x00,0x6a, 800, 600, 0}, /* 04 */
-	{0x0147,0x12,0x0c,0x00,0x6a, 800, 600, 0}, /* 05 */
-	{0x0047,0x11,0x4e,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
-	{0x0047,0x11,0x13,0x00,0x6a, 800, 600, 0}, /* 07 */
-	{0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 08 */
-	{0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0}, /* 09 */
-	{0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0}, /* 0a */
-	{0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0}, /* 0b */
-	{0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0}, /* 0c */
-	{0xc047,0x0a,0x08,0x00,0x2e, 640, 480, 0}, /* 0d */
-	{0xc047,0x0b,0x0a,0x00,0x2e, 640, 480, 0}, /* 0e */
-	{0xc047,0x0c,0x10,0x00,0x2e, 640, 480, 0}, /* 0f */
-	{0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
-	{0xc04f,0x31,0x01,0x06,0x31, 720, 480, 0}, /* 11 */
-	{0x004f,0x32,0x03,0x06,0x32, 720, 576, 0}, /* 12 */
-	{0x0187,0x15,0x05,0x00,0x37,1024, 768, 0}, /* 13 */
-        {0xc877,0x16,0x09,0x06,0x37,1024, 768, 0}, /* 14 */
-	{0xc067,0x17,0x0b,0x49,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
-	{0x0267,0x18,0x0d,0x00,0x37,1024, 768, 0}, /* 16 */
-	{0x0047,0x19,0x11,0x8c,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
-	{0x0047,0x1a,0x52,0x00,0x37,1024, 768, 0}, /* 18 */
-	{0x0007,0x1b,0x16,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
-	{0x0387,0x1c,0x4d,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
-	{0x0077,0x1d,0x14,0x07,0x3a,1280,1024, 0}, /* 1b */
-	{0x0047,0x1e,0x17,0x00,0x3a,1280,1024, 0}, /* 1c */
-	{0x0007,0x1f,0x98,0x00,0x3a,1280,1024, 0}, /* 1d */
-	{0x0007,0x20,0x59,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
-	{0x0007,0x21,0x5a,0x00,0x3c,1600,1200, 0}, /* 1f */
-	{0x0007,0x22,0x1b,0x00,0x3c,1600,1200, 0}, /* 20 */
-	{0x0007,0x23,0x1d,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
-	{0x0007,0x24,0x1e,0x00,0x3c,1600,1200, 0}, /* 22 */
-	{0x407f,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
-	{0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0}, /* 24 */
-	{0x0077,0x02,0x04,0x05,0x51, 400, 300, 0}, /* 25 */
-	{0xc877,0x03,0x09,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
-	{0x8207,0x25,0x1f,0x00,0x68,1920,1440, 0}, /* 27 */
-	{0x0007,0x26,0x20,0x00,0x6c,2048,1536, 0}, /* 28 */
-	{0x0067,0x27,0x14,0x08,0x6e,1280, 960, 0}, /* 29 - TW: 1280x960-60 */
-	{0x0027,0x45,0x3c,0x08,0x6e,1280, 960, 0}, /* 2a - TW: 1280x960-85 */
-	{0xc077,0x33,0x09,0x06,0x20,1024, 600, 0}, /* 2b */
-	{0xc077,0x34,0x0b,0x06,0x23,1152, 768, 0}, /* 2c */	/* VCLK 0x09 */
-	{0x0057,0x35,0x27,0x08,0x70, 800, 480, 0}, /* 2d */
-	{0x0047,0x36,0x37,0x08,0x70, 800, 480, 0}, /* 2e */
-	{0x0047,0x37,0x08,0x08,0x70, 800, 480, 0}, /* 2f */
-	{0x0057,0x38,0x09,0x09,0x71,1024, 576, 0}, /* 30 */
-	{0x0047,0x39,0x38,0x09,0x71,1024, 576, 0}, /* 31 */
-	{0x0047,0x3a,0x11,0x09,0x71,1024, 576, 0}, /* 32 */
-	{0x0057,0x3b,0x39,0x0a,0x75,1280, 720, 0}, /* 33 */
-	{0x0047,0x3c,0x3a,0x0a,0x75,1280, 720, 0}, /* 34 */
-	{0x0007,0x3d,0x3b,0x0a,0x75,1280, 720, 0}, /* 35 */
-	{0x0047,0x3e,0x34,0x06,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */
-	{0x0047,0x44,0x3a,0x06,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */
-	{0x00c7,0x3f,0x28,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */
-	{0xc067,0x40,0x3d,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz  */
-	{0x00c7,0x41,0x28,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */
-	{0xc047,0x42,0x28,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz  */
-	{0x0067,0x43,0x3e,0x0c,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */
-	{0x0077,0x46,0x3f,0x08,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */
-	{0x004f,0x47,0x03,0x06,0x5f, 768, 576, 0}, /* 3e 768x576 */
-	{0x0027,0x48,0x13,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
-	{0xffff,   0,   0,   0,   0,   0,   0, 0}
-};
-
-typedef struct _SiS_VBModeIDTableStruct
-{
-	UCHAR  ModeID;
-	UCHAR  VB_TVDelayIndex;
-	UCHAR  VB_TVFlickerIndex;
-	UCHAR  VB_TVPhaseIndex;
-	UCHAR  VB_TVYFilterIndex;
-	UCHAR  VB_LCDDelayIndex;
-	UCHAR  _VB_LCDHIndex;
-	UCHAR  _VB_LCDVIndex;
-}SiS_VBModeIDTableStruct;
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */
+	{0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */
+	{0x0067,0x0f,0x07,0x48,0x00,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
+	{0x0067,0x10,0x06,0x8b,0x00,0x6a, 800, 600, 0}, /* 03 */
+	{0x0147,0x11,0x08,0x00,0x00,0x6a, 800, 600, 0}, /* 04 */
+	{0x0147,0x12,0x0c,0x00,0x00,0x6a, 800, 600, 0}, /* 05 */
+	{0x0047,0x11,0x4e,0x00,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
+	{0x0047,0x11,0x13,0x00,0x00,0x6a, 800, 600, 0}, /* 07 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */
+	{0xc047,0x09,0x05,0x00,0x00,0x2e, 640, 480, 0}, /* 0c */
+	{0xc047,0x0a,0x08,0x00,0x00,0x2e, 640, 480, 0}, /* 0d */
+	{0xc047,0x0b,0x0a,0x00,0x00,0x2e, 640, 480, 0}, /* 0e */
+	{0xc047,0x0c,0x10,0x00,0x00,0x2e, 640, 480, 0}, /* 0f */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
+	{0xc04f,0x31,0x01,0x06,0x00,0x31, 720, 480, 0}, /* 11 */
+	{0x004f,0x32,0x03,0x06,0x00,0x32, 720, 576, 0}, /* 12 */
+	{0x0187,0x15,0x05,0x00,0x00,0x37,1024, 768, 0}, /* 13 */
+        {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */
+	{0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
+	{0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */
+	{0x0047,0x19,0x11,0x8c,0x00,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
+	{0x0047,0x1a,0x52,0x00,0x00,0x37,1024, 768, 0}, /* 18 */
+	{0x0007,0x1b,0x16,0x00,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
+	{0x0387,0x1c,0x4d,0x00,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
+	{0x0077,0x1d,0x14,0x07,0x00,0x3a,1280,1024, 0}, /* 1b */
+	{0x0047,0x1e,0x17,0x00,0x00,0x3a,1280,1024, 0}, /* 1c */
+	{0x0007,0x1f,0x98,0x00,0x00,0x3a,1280,1024, 0}, /* 1d */
+	{0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
+	{0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */
+	{0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */
+	{0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
+	{0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */
+	{0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */
+	{0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
+	{0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */
+	{0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */
+	{0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */
+	{0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */
+	{0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */
+	{0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */	/* VCLK 0x09 */
+	{0x0057,0x35,0x27,0x08,0x00,0x70, 800, 480, 0}, /* 2d */
+	{0x0047,0x36,0x37,0x08,0x00,0x70, 800, 480, 0}, /* 2e */
+	{0x0047,0x37,0x08,0x08,0x00,0x70, 800, 480, 0}, /* 2f */
+	{0x0057,0x38,0x09,0x09,0x00,0x71,1024, 576, 0}, /* 30 */
+	{0x0047,0x39,0x38,0x09,0x00,0x71,1024, 576, 0}, /* 31 */
+	{0x0047,0x3a,0x11,0x09,0x00,0x71,1024, 576, 0}, /* 32 */
+	{0x0057,0x3b,0x39,0x0a,0x00,0x75,1280, 720, 0}, /* 33 */
+	{0x0047,0x3c,0x3a,0x0a,0x00,0x75,1280, 720, 0}, /* 34 */
+	{0x0007,0x3d,0x3b,0x0a,0x00,0x75,1280, 720, 0}, /* 35 */
+	{0x0047,0x3e,0x34,0x06,0x00,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */
+	{0x0047,0x44,0x3a,0x06,0x00,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */
+	{0x00c7,0x3f,0x28,0x00,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */
+	{0xc067,0x40,0x3d,0x0b,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz  */
+	{0x00c7,0x41,0x28,0x00,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */
+	{0xc047,0x42,0x28,0x00,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz  */
+	{0x0067,0x43,0x3e,0x0c,0x0b,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */
+	{0x0077,0x46,0x3f,0x08,0x00,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */
+	{0x004f,0x47,0x03,0x06,0x00,0x5f, 768, 576, 0}, /* 3e 768x576 */
+	{0x0027,0x48,0x13,0x08,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
+	{0xffff,   0,   0,   0,   0,   0,   0,   0, 0}
+};
 
-static const SiS_VBModeIDTableStruct  SiS300_VBModeIDTable[] =
+static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
 {
 	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
 	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
@@ -355,12 +301,7 @@ static const SiS_VBModeIDTableStruct  Si
 	{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
 };
 
-typedef struct _SiS300_CRT1TableStruct
-{
-	UCHAR CR[17];
-} SiS300_CRT1TableStruct;
-
-static const SiS300_CRT1TableStruct  SiS300_CRT1Table[] =
+static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
 {
 #if 1
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,    /* 0x00 - 320x200 */
@@ -625,13 +566,7 @@ static const SiS300_CRT1TableStruct  SiS
    0x00}}   /* 0x48 */
 };
 
-typedef struct _SiS300_MCLKDataStruct
-{
-	UCHAR SR28,SR29,SR2A;
-	USHORT CLOCK;
-} SiS300_MCLKDataStruct;
-
-static const SiS300_MCLKDataStruct  SiS300_MCLKData_630[] =
+static const SiS_MCLKDataStruct  SiS300_MCLKData_630[] =
 {
 	{ 0x5a,0x64,0x80, 66},
 	{ 0xb3,0x45,0x80, 83},
@@ -643,7 +578,7 @@ static const SiS300_MCLKDataStruct  SiS3
 	{ 0x37,0x61,0x80,100}
 };
 
-static const SiS300_MCLKDataStruct  SiS300_MCLKData_300[] =
+static const SiS_MCLKDataStruct  SiS300_MCLKData_300[] =
 {
 	{ 0x68,0x43,0x80,125},
 	{ 0x68,0x43,0x80,125},
@@ -655,13 +590,7 @@ static const SiS300_MCLKDataStruct  SiS3
 	{ 0x37,0x61,0x80,100}
 };
 
-typedef struct _SiS300_VCLKDataStruct
-{
-	UCHAR SR2B,SR2C;
-	USHORT CLOCK;
-} SiS300_VCLKDataStruct;
-
-static const SiS300_VCLKDataStruct  SiS300_VCLKData[] =
+static SiS_VCLKDataStruct SiS300_VCLKData[] =
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -736,14 +665,7 @@ static const SiS300_VCLKDataStruct  SiS3
 	{ 0x37,0x61,100}, /* 0x43 */  /* 1280x960 LCD */
 	{ 0xe3,0x9a,106}, /* 0x44 */  /* 1360x1024 - special for Barco iQ R300 */
 	{ 0xe2,0x46,135}, /* 0x45 */  /* 1280x1024-75, better clock for VGA2 */
-	{ 0xff,0x00,  0}
-};
-
-static const UCHAR  SiS300_ScreenOffset[] =
-{
-	0x14,0x19,0x20,0x28,0x32,0x40,0x50,
-        0x64,0x78,0x80,0x2d,0x35,0x48,0x35,
-	0x55,0x30,0xff
+	{    0,   0,  0}  /* 0x46 custom (will be filled out) */
 };
 
 #ifndef LINUX_XF86
@@ -789,12 +711,7 @@ static const DRAM4Type SiS300_CR40[5];
 static UCHAR SiS300_CR49[2];
 #endif
 
-typedef struct _SiS300_PanelDelayTblStruct
-{
-	UCHAR timer[2];
-} SiS300_PanelDelayTblStruct;
-
-static const SiS300_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
+static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
 {
 	{{0x05,0xaa}},
 	{{0x05,0x14}},
@@ -815,7 +732,7 @@ static const SiS300_PanelDelayTblStruct 
 };
 
 #if 0
-static const SiS300_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
+static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
 {
 	{{0x05,0xaa}},
 	{{0x05,0x14}},
@@ -840,28 +757,18 @@ static const SiS300_PanelDelayTblStruct 
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS300_LCDDataStruct
+static const SiS_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
 {
-	USHORT RVBHCMAX;
-	USHORT RVBHCFACT;
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS300_LCDDataStruct;
-
-static const SiS300_LCDDataStruct  SiS300_StLCD1024x768Data[] =
-{
-	{   66,  31, 992, 510,1320, 816},
-	{   66,  31, 992, 510,1320, 816},
-	{  176,  75, 900, 510,1320, 816},
-	{  176,  75, 900, 510,1320, 816},
-	{   66,  31, 992, 510,1320, 816},
-	{   27,  16,1024, 650,1350, 832},
+	{   62,  25, 800, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{  104,  45, 945, 496,1344, 806},
+	{   62,  25, 800, 546,1344, 806},
+	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS300_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
+static const SiS_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
 {
 	{   12,   5, 896, 512,1344, 806},
 	{   12,   5, 896, 510,1344, 806},
@@ -878,30 +785,19 @@ static const SiS300_LCDDataStruct  SiS30
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS300_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
+static const SiS_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
 {
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const SiS300_LCDDataStruct  SiS300_StLCD1280x1024Data[] =
-{
-	{    4,   1, 880, 510,1650,1088},
-	{    4,   1, 880, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
 	{  176,  45, 900, 510,1650,1088},
 	{  176,  45, 900, 510,1650,1088},
-	{    4,   1, 880, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
 	{   13,   5,1024, 675,1560,1152},
 	{   16,   9,1266, 804,1688,1072},
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS300_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
 {
 	{  211,  60,1024, 501,1688,1066},
 	{  211,  60,1024, 508,1688,1066},
@@ -913,74 +809,18 @@ static const SiS300_LCDDataStruct  SiS30
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS300_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const SiS300_LCDDataStruct  SiS300_NoScaleData1024x768[] =
-{
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 800, 525, 800, 525},
-	{    1,   1,1056, 628,1056, 628},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const SiS300_LCDDataStruct  SiS300_NoScaleData1280x1024[] =  /* TW: Fake */
-{
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 800, 525, 800, 525},
-	{    1,   1,1056, 628,1056, 628},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-typedef struct _SiS300_Part2PortTblStruct
-{
- 	UCHAR CR[12];
-} SiS300_Part2PortTblStruct;
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
 { /* VESA Timing */
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
 {  /* Non-VESA */
  {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
  {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
@@ -991,38 +831,23 @@ static const SiS300_Part2PortTblStruct S
  {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
-{
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
+{	
  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
 {
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_2[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
-{	/* TW: Temporary data, invalid */
   {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_3[] =
-{	/* TW: Temporary data, invalid */
-  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
+{
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_3[] =
-{	/* TW: Temporary data, invalid */
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
+{
   {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
@@ -1030,15 +855,7 @@ static const SiS300_Part2PortTblStruct S
 /* LVDS/Chrontel -------------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS300_LVDSDataStruct
-{
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS300_LVDSDataStruct;
-
-static const SiS300_LVDSDataStruct  SiS300_CHTVUPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVUPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1048,7 +865,7 @@ static const SiS300_LVDSDataStruct  SiS3
 	{ 936, 836, 936, 836}
 };
 
-static const SiS300_LVDSDataStruct  SiS300_CHTVOPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVOPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1058,7 +875,7 @@ static const SiS300_LVDSDataStruct  SiS3
 	{ 960, 750, 960, 750}
 };
 
-static const SiS300_LVDSDataStruct  SiS300_CHTVSOPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVSOPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1068,13 +885,8 @@ static const SiS300_LVDSDataStruct  SiS3
 	{ 944, 625, 944, 625}
 };
 
-typedef struct _SiS300_LVDSDesStruct
-{
-	USHORT LCDHDES;
-	USHORT LCDVDES;
-} SiS300_LVDSDesStruct;
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType00_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType00_1[] =
 {
 	{ 1059, 626 },   /* 2.08 */
 	{ 1059, 624 },
@@ -1098,7 +910,7 @@ static const SiS300_LVDSDesStruct  SiS30
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType01_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType01_1[] =
 {
 	{   0,   0 },  /* 2.08 */
 	{   0,   0 },
@@ -1122,7 +934,7 @@ static const SiS300_LVDSDesStruct  SiS30
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType02_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType02_1[] =
 {
 	{ 1059, 626 },  /* 2.08 */
 	{ 1059, 624 },
@@ -1146,7 +958,7 @@ static const SiS300_LVDSDesStruct  SiS30
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType03_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType03_1[] =
 {
 	{   8, 436},
 	{   8, 440},
@@ -1159,7 +971,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{1343, 794}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1[] =	/* 1280x1024 */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1[] =	/* 1280x1024 */
 {
 	{1343, 798},
 	{1343, 794},
@@ -1172,7 +984,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType05_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType05_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1185,7 +997,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType06_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType06_1[] =	/* Clevo Trumpion 1024x768 */
 {
 	{1343, 798},
 	{1343, 794},
@@ -1198,7 +1010,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType07_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType07_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1211,7 +1023,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType08_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType08_1[] =
 {
 	{1059, 626},
 	{1059, 624},
@@ -1224,7 +1036,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType09_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType09_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1237,7 +1049,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0a_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0a_1[] =
 {
 	{1059, 626},
 	{1059, 624},
@@ -1250,7 +1062,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0b_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0b_1[] =
 {
 	{1343,   0},
 	{1343,   0},
@@ -1263,7 +1075,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0c_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0c_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1276,7 +1088,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0d_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0d_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1289,7 +1101,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0e_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0e_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1302,7 +1114,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}     /* 1280x960 - not applicable */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0f_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0f_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1315,7 +1127,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType00_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType00_2[] =
 {
 	{976, 527},
 	{976, 502},
@@ -1328,7 +1140,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType01_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType01_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1341,7 +1153,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType02_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType02_2[] =
 {
 	{976, 527},
 	{976, 502},
@@ -1354,7 +1166,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType03_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType03_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1367,7 +1179,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{1152, 597}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1380,7 +1192,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType05_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType05_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1393,7 +1205,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType06_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType06_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1406,7 +1218,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType07_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType07_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1419,7 +1231,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType08_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType08_2[] =
 {
  	{976, 527},
  	{976, 502},
@@ -1432,7 +1244,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType09_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType09_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1445,7 +1257,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0a_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0a_2[] =
 {
  	{976, 527},
  	{976, 502},
@@ -1458,7 +1270,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0b_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0b_2[] =
 {
  	{ 1152, 700},
  	{ 1152, 675},
@@ -1471,7 +1283,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{    0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0c_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0c_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1484,7 +1296,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0d_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0d_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1497,7 +1309,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0e_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0e_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1510,7 +1322,7 @@ static const SiS300_LVDSDesStruct  SiS30
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0f_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0f_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1523,8 +1335,36 @@ static const SiS300_LVDSDesStruct  SiS30
  	{   0,   0}
 };
 
+static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_1[]=
+{
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0, 805},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0}
+};
+
+static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_2[] =
+{
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0}
+};
+
 /* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
 {
 	{1330, 798},  /* 320x200 */
 	{1330, 794},
@@ -1537,7 +1377,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0,   0}   /* 1360x1024          */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2a[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2a[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1551,7 +1391,7 @@ static const SiS300_LVDSDesStruct  SiS30
 };
 
 /* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1b[] =	/* 1024x768 */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1b[] =	/* 1024x768 */
 {
 	{1330, 798},  /* 320x200 */
 	{1330, 794},
@@ -1562,7 +1402,7 @@ static const SiS300_LVDSDesStruct  SiS30
 	{   0, 805}   /* 1024x768 / 512x384 */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2b[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2b[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1575,12 +1415,7 @@ static const SiS300_LVDSDesStruct  SiS30
 
 /* CRT1 CRTC for slave modes */
 
-typedef struct _SiS300_LVDSCRT1DataStruct
-{
-UCHAR CR[15];
-} SiS300_LVDSCRT1DataStruct;
-
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
 {
 	{{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
 	  0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1602,7 +1437,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
 {
 	{{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
 	  0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
@@ -1624,7 +1459,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
 { 
 	{{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
@@ -1649,7 +1484,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01}}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
 {
 	{{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
@@ -1698,7 +1533,7 @@ static const SiS300_LVDSCRT1DataStruct  
 #endif
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
 {
 	{{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
@@ -1723,7 +1558,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
 {
 	{{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
@@ -1748,7 +1583,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
 {
 	{{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
 	  0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
@@ -1770,7 +1605,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
 {
 	{{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
 	  0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
@@ -1792,7 +1627,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
 {
 	{{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
@@ -1817,7 +1652,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
 {
 	{{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
@@ -1842,7 +1677,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
 {
 	{{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
@@ -1867,7 +1702,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
 {
 	{{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
@@ -1892,7 +1727,64 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01}}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+   0x01}}
+};
+
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1_H[] =
+{
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},
+ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+   0x01}},
+ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+   0x01}}
+};
+
+
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
 {
 	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
 	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -1914,7 +1806,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
 {
 	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
 	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -1936,7 +1828,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1958,7 +1850,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1980,7 +1872,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -2002,12 +1894,7 @@ static const SiS300_LVDSCRT1DataStruct  
 	  0x01 }}
 };
 
-typedef struct _SiS300_CHTVRegDataStruct
-{
-	UCHAR Reg[16];
-} SiS300_CHTVRegDataStruct;
-
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
 {
 	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2017,7 +1904,7 @@ static const SiS300_CHTVRegDataStruct Si
 	{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 24: 800x600 NTSC 7/10 */
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
 {
 	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2027,7 +1914,7 @@ static const SiS300_CHTVRegDataStruct Si
 	{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 23: 800x600 NTSC 3/4 */
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2038,7 +1925,7 @@ static const SiS300_CHTVRegDataStruct Si
 
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2049,7 +1936,7 @@ static const SiS300_CHTVRegDataStruct Si
 
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/310vtbl.h linux-2.4.26-pre6/drivers/video/sis/310vtbl.h
--- linux-2.4.25/drivers/video/sis/310vtbl.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/310vtbl.h	2004-03-25 00:20:30.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -52,20 +49,7 @@
  *
  */
 
-typedef struct _SiS310_StStruct
-{
-	UCHAR St_ModeID;
-	USHORT St_ModeFlag;
-	UCHAR St_StTableIndex;
-	UCHAR St_CRT2CRTC;
-	UCHAR St_ResInfo;
-	UCHAR VB_StTVFlickerIndex;
-	UCHAR VB_StTVEdgeIndex;
-	UCHAR VB_StTVYFilterIndex;
-	UCHAR St_PDC;
-} SiS310_StStruct;
-
-static const SiS310_StStruct SiS310_SModeIDTable[]=
+static const SiS_StStruct SiS310_SModeIDTable[]=
 {
 	{0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40},
 	{0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40},
@@ -89,207 +73,184 @@ static const SiS310_StStruct SiS310_SMod
 	{0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40}
 };
 
-typedef struct _SiS310_ExtStruct
+static const SiS_ExtStruct  SiS310_EModeIDTable[]=
 {
-	UCHAR  Ext_ModeID;
-	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
-	USHORT Ext_VESAID;
-	UCHAR  Ext_RESINFO;
-	UCHAR  VB_ExtTVFlickerIndex;
-	UCHAR  VB_ExtTVEdgeIndex;
-	UCHAR  VB_ExtTVYFilterIndex;
-	UCHAR  VB_ExtTVYFilterIndexROM661;
-	UCHAR  REFindex;
-} SiS310_ExtStruct;
-
-static const SiS310_ExtStruct  SiS310_EModeIDTable[]=
-{
-	{0x6a,0x2212,0x04,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */
-	{0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */
-        {0x2f,0x0a1b,0x03,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */
-	{0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */
-        {0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */
-	{0x32,0x0a1b,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */
-	{0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */
-	{0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */
-	{0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */
-	{0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */
-	{0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */
-	{0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */
-	{0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
-	{0x3c,0x0e3b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
-	{0x3d,0x0e7d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
-	{0x40,0x9a1c,0x00,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */
-	{0x41,0x9a1d,0x00,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */
-	{0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08},
-	{0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */
-	{0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00},
-	{0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */
-	{0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13},
-	{0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */
-	{0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
-	{0x50,0x9a1b,0x00,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x8  */
-	{0x51,0xba1b,0x01,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x8  */
-  	{0x52,0xba1b,0x02,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x8  */
-	{0x56,0x9a1d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */
-	{0x57,0xba1d,0x01,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */
- 	{0x58,0xba1d,0x02,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */
-	{0x59,0x9a1b,0x00,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x8  */
-	{0x5a,0x021b,0x00,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8  fstn */
-	{0x5b,0x0a1d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */
-	{0x5c,0xba1f,0x02,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */
-	{0x5d,0x0a1d,0x03,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10},
-	{0x5e,0x0a1f,0x03,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */
-	{0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */
-	{0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */
-	{0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */
-	{0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
-	{0x66,0x0eff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
-	{0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
-	{0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
-	{0x6b,0x07ff,0x08,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
-	{0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
-	{0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
-	{0x6e,0x07ff,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
-	{0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */
-	{0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
-	{0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
-	{0x75,0x0a3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
-	{0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */
-	{0x77,0x0a1f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
-	{0x78,0x0a3f,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
-	{0x79,0x0a3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
-	{0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */
-	{0x7c,0x0e3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
-	{0x7d,0x0e7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
-	{0x7e,0x0eff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
-	{0x23,0x0e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
-	{0x24,0x0e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
-	{0x25,0x0eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
-	{0x26,0x0e3b,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
-	{0x27,0x0e7d,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
-	{0x28,0x0eff,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
-	{0x29,0x0e1b,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */
-	{0x2a,0x0e3d,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x2b,0x0e7f,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x39,0x2a1b,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45}, /* 848x480 */
-	{0x3b,0x2a3d,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3e,0x2a7f,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3f,0x2a1b,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47}, /* 856x480 */
-	{0x42,0x2a3d,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x45,0x2a7f,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x48,0x2a1b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */
-	{0x4b,0x2a3d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4e,0x2a7f,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4f,0x9a1f,0x00,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */
-	{0x53,0x9a1f,0x00,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */
-	{0x54,0xba1f,0x01,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */
-	{0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x8 */
-	{0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x16 */
-	{0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x32 */
-	{0xff,0x0000,0x00,0x0000,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-typedef struct _SiS310_Ext2Struct
-{
-	USHORT Ext_InfoFlag;
-	UCHAR  Ext_CRT1CRTC;
-	UCHAR  Ext_CRTVCLK;
-	UCHAR  Ext_CRT2CRTC;
-	UCHAR  ModeID;
-	USHORT XRes;
-	USHORT YRes;
-	UCHAR  Ext_PDC;
-} SiS310_Ext2Struct;
-
-static const SiS310_Ext2Struct SiS310_RefIndex[]=
-{
-	{0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
-	{0x0067,0x0e,0x04,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
-	{0x0067,0x0f,0x08,0x48,0x6a, 800, 600, 0x40}, /* 0x2 */
-	{0x0067,0x10,0x07,0x8b,0x6a, 800, 600, 0x40}, /* 0x3 */
-	{0x0047,0x11,0x0a,0x00,0x6a, 800, 600, 0x40}, /* 0x4 */
-	{0x0047,0x12,0x0d,0x00,0x6a, 800, 600, 0x40}, /* 0x5 */
-	{0x0047,0x13,0x13,0x00,0x6a, 800, 600, 0x20}, /* 0x6 */
-	{0x0107,0x14,0x1c,0x00,0x6a, 800, 600, 0x20}, /* 0x7 */
-	{0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
-	{0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
-	{0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0x40}, /* 0xa */
-	{0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0x40}, /* 0xb */
-	{0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0x40}, /* 0xc */
-	{0xc047,0x0a,0x09,0x00,0x2e, 640, 480, 0x40}, /* 0xd */
-	{0xc047,0x0b,0x0e,0x00,0x2e, 640, 480, 0x40}, /* 0xe */
-	{0xc047,0x0c,0x15,0x00,0x2e, 640, 480, 0x40}, /* 0xf */
-	{0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
-	{0xc04f,0x3c,0x01,0x06,0x31, 720, 480, 0x30}, /* 0x11 */
-	{0x004f,0x3d,0x03,0x06,0x32, 720, 576, 0x30}, /* 0x12 */
-	{0x0087,0x15,0x06,0x00,0x37,1024, 768, 0x30}, /* 0x13 */
-	{0xc877,0x16,0x0b,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
-	{0xc067,0x17,0x0f,0x49,0x37,1024, 768, 0x20}, /* 0x15 */
-	{0x0067,0x18,0x11,0x00,0x37,1024, 768, 0x20}, /* 0x16 */
-	{0x0047,0x19,0x16,0x8c,0x37,1024, 768, 0x20}, /* 0x17 */
-	{0x0107,0x1a,0x1b,0x00,0x37,1024, 768, 0x10}, /* 0x18 */
-	{0x0107,0x1b,0x1f,0x00,0x37,1024, 768, 0x10}, /* 0x19 */
-	{0x0087,0x1c,0x11,0x00,0x3a,1280,1024, 0x30}, /* 0x1a */
-	{0x0137,0x1d,0x19,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
-	{0x0107,0x1e,0x1e,0x00,0x3a,1280,1024, 0x00}, /* 0x1c */
-	{0x0207,0x1f,0x20,0x00,0x3a,1280,1024, 0x00}, /* 0x1d */
-	{0x0227,0x20,0x21,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
-	{0x0407,0x21,0x22,0x00,0x3c,1600,1200, 0x00}, /* 0x1f */
-	{0x0407,0x22,0x23,0x00,0x3c,1600,1200, 0x00}, /* 0x20 */
-	{0x0407,0x23,0x25,0x00,0x3c,1600,1200, 0x00}, /* 0x21 */
-	{0x0007,0x24,0x26,0x00,0x3c,1600,1200, 0x00}, /* 0x22 */
-	{0x0007,0x25,0x2c,0x00,0x3c,1600,1200, 0x00}, /* 0x23 */
-	{0x0007,0x26,0x34,0x00,0x3c,1600,1200, 0x00}, /* 0x24 */
-	{0x407f,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
-	{0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
-	{0x007f,0x02,0x04,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
-	{0xc077,0x03,0x0b,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
-	{0x8007,0x27,0x27,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
-	{0x4007,0x28,0x29,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
-	{0x4007,0x29,0x2e,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
-	{0x4007,0x2a,0x30,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
-	{0x4007,0x2b,0x35,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
-	{0x4005,0x2c,0x39,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
-	{0x4007,0x2d,0x2b,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
-	{0x4007,0x2e,0x31,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
-	{0x4007,0x2f,0x33,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
-	{0x4007,0x30,0x37,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
-	{0x4005,0x31,0x38,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
-	{0x0057,0x32,0x40,0x08,0x70, 800, 480, 0x30}, /* 0x34 */
-	{0x0047,0x33,0x07,0x08,0x70, 800, 480, 0x30}, /* 0x35 */
-	{0x0047,0x34,0x0a,0x08,0x70, 800, 480, 0x30}, /* 0x36 */
-	{0x0057,0x35,0x0b,0x09,0x71,1024, 576, 0x30}, /* 0x37 */
-	{0x0047,0x36,0x11,0x09,0x71,1024, 576, 0x30}, /* 0x38 */
-	{0x0047,0x37,0x16,0x09,0x71,1024, 576, 0x30}, /* 0x39 */
-	{0x0117,0x38,0x19,0x0a,0x75,1280, 720, 0x30}, /* 0x3a */
-	{0x0107,0x39,0x1e,0x0a,0x75,1280, 720, 0x30}, /* 0x3b */
-	{0x0207,0x3a,0x20,0x0a,0x75,1280, 720, 0x30}, /* 0x3c */
-	{0x0127,0x3b,0x19,0x08,0x7c,1280, 960, 0x30}, /* 0x3d */
-	{0x0227,0x4c,0x59,0x08,0x7c,1280, 960, 0x20}, /* 0x3e */
-	{0xc07f,0x4e,0x00,0x06,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
-        {0x0077,0x42,0x5b,0x08,0x23,1280, 768, 0x30}, /* 0x40 */    /* TW: 0x5b was 0x12 */
-	{0x0127,0x43,0x4d,0x08,0x26,1400,1050, 0x30}, /* 0x41 */
-	{0x0207,0x4b,0x5a,0x08,0x26,1400,1050, 0x30}, /* 0x42 Non-BIOS, new */
-	{0x0107,0x44,0x19,0x00,0x29,1152, 864, 0x30}, /* 0x43 Non-BIOS, new */
-	{0x0107,0x4a,0x1e,0x00,0x29,1152, 864, 0x30}, /* 0x44 Non-BIOS, new */
-	{0x0087,0x45,0x57,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi - Non-BIOS, new */
-	{0xc067,0x46,0x55,0x0b,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz  - Non-BIOS, new */
-	{0x0087,0x47,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi - Non-BIOS, new */
-	{0xc047,0x48,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz  - Non-BIOS, new */
-	{0x0067,0x49,0x58,0x0c,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz - Non-BIOS, new */
-	{0x004f,0x4d,0x03,0x06,0x5f, 768, 576, 0x30}, /* 0x4a 768x576 */
-	{0xffff,0x00,0x00,0x00,0x00,   0,   0, 0}
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */
+        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */
+        {0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */
+	{0x32,0x0a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */
+	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */
+	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */
+	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */
+	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
+	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
+	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
+	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */
+	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00},
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
+	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x8  */
+	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x8  */
+  	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x8  */
+	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */
+	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */
+ 	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */
+	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x8  */
+	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8  fstn */
+	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */
+	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */
+	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10},
+	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
+	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
+	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
+	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
+	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */
+	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
+	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
+	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
+	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */
+	{0x77,0x0a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
+	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
+	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
+	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */
+	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
+	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
+	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
+	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
+	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
+	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
+	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
+	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
+	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
+	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */
+	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
+	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
+	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45}, /* 848x480 */
+	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
+	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
+	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47}, /* 856x480 */
+	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
+	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
+	{0x48,0x2a1b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */
+	{0x4b,0x2a3d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
+	{0x4e,0x2a7f,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
+	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */
+	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */
+	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */
+	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576 */
+	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a},
+	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a},
+	{0x14,0x0e1b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b}, /* 1280x800 */
+	{0x15,0x0e3d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b},
+	{0x16,0x0e7f,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b},
+	{0x17,0x0e1b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c}, /* 1680x1050 */
+	{0x18,0x0e3d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c},
+	{0x19,0x0e7f,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c},
+	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00}
+};
+
+static const SiS_Ext2Struct SiS310_RefIndex[]=
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
+	{0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
+	{0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */
+	{0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */
+	{0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */
+	{0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */
+	{0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */
+	{0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */
+	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */
+	{0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */
+	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
+	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
+	{0xc04f,0x3c,0x01,0x06,0x00,0x31, 720, 480, 0x30}, /* 0x11 */
+	{0x004f,0x3d,0x03,0x06,0x00,0x32, 720, 576, 0x30}, /* 0x12 */
+	{0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
+	{0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
+	{0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
+	{0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */
+	{0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */
+	{0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */
+	{0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */
+	{0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */
+	{0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
+	{0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */
+	{0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */
+	{0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
+	{0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */
+	{0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */
+	{0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */
+	{0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */
+	{0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */
+	{0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
+	{0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
+	{0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
+	{0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
+	{0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
+	{0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
+	{0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
+	{0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
+	{0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
+	{0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
+	{0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
+	{0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
+	{0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
+	{0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
+	{0x0057,0x32,0x40,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x34 */
+	{0x0047,0x33,0x07,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x35 */
+	{0x0047,0x34,0x0a,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x36 */
+	{0x0057,0x35,0x0b,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x37 */
+	{0x0047,0x36,0x11,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x38 */
+	{0x0047,0x37,0x16,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x39 */
+	{0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
+	{0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
+	{0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
+	{0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */
+	{0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */
+	{0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
+        {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */    /* 0x5b was 0x12 */
+	{0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
+	{0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
+	{0x0107,0x44,0x19,0x00,0x00,0x29,1152, 864, 0x30}, /* 0x43 1152x864-75Hz  */
+	{0x0107,0x4a,0x1e,0x00,0x00,0x29,1152, 864, 0x30}, /* 0x44 1152x864-85Hz  */
+	{0x0087,0x45,0x57,0x00,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi  */
+	{0xc067,0x46,0x55,0x0b,0x00,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz   */
+	{0x0087,0x47,0x57,0x00,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi  */
+	{0xc047,0x48,0x57,0x00,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz   */
+	{0x0067,0x49,0x58,0x0c,0x00,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz  */
+	{0x004f,0x4d,0x03,0x06,0x00,0x5f, 768, 576, 0x30}, /* 0x4a 768x576-56Hz   */
+	{0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4b 1280x800-60Hz  */
+	{0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4c 1680x1050-60Hz */
+	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0}
 };
 
-typedef struct _SiS310_CRT1TableStruct
-{
- 	UCHAR CR[17];
-} SiS310_CRT1TableStruct;
-
-static const SiS310_CRT1TableStruct SiS310_CRT1Table[]=
+static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
 {
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
    0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
@@ -310,7 +271,7 @@ static const SiS310_CRT1TableStruct SiS3
  {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
    0x00}}, /* 0x5 */
-#endif   
+#endif
  {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
    0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
    0x00}},
@@ -329,16 +290,16 @@ static const SiS310_CRT1TableStruct SiS3
    0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
    0x00}}, /* 0x8 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
-   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* TW: Corrected VBE */
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* Corrected VBE */
    0x61}}, /* 0x9 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
    0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
    0x61}}, /* 0xa */
  {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
-   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* TW: Corrected VBE */
+   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* Corrected VBE */
    0x61}}, /* 0xb */
  {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
-   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* TW: Corrected VDE, VBE */
+   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* Corrected VDE, VBE */
    0x00}}, /* 0xc */
  {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
    0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
@@ -466,7 +427,7 @@ static const SiS310_CRT1TableStruct SiS3
  {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
    0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
    0x01}}, /* 0x36 */
- {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* TW: 95 was 15 - illegal HBE! */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* 95 was 15 - illegal HBE! */
    0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
    0x01}}, /* 0x37 */
  {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
@@ -498,7 +459,7 @@ static const SiS310_CRT1TableStruct SiS3
  {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
    0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
    0x00}}, /* 0x3f */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,   /* TW: The following from 650/LVDS BIOS */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
    0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
    0x01}},  /* 0x40 */
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
@@ -510,31 +471,31 @@ static const SiS310_CRT1TableStruct SiS3
  {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
    0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
    0x00}},  /* 0x43 */
- {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* New, 1152x864-75, not in BIOS */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */
    0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
    0x01}},  /* 0x44 */
- {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* New, 848x480-38i, not in BIOS */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */
    0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
    0x00}},  /* 0x45 */
- {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* New, 848x480-60, not in BIOS */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */
    0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
    0x00}},  /* 0x46 */
- {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* New, 856x480-38i, not in BIOS */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */
    0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
    0x00}},  /* 0x47 */
- {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* New, 856x480-60, not in BIOS */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */
    0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
    0x00}},  /* 0x48 */
- {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* New, 1360x768-60, not in BIOS */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */
    0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
    0x01}},  /* 0x49 */
- {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* New, 1152x864-84, not in any BIOS   */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84  */
    0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
    0x01}},  /* 0x4a */
- {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* New, 1400x1050-75, not in any BIOS  */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* 1400x1050-75  */
    0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
    0x00}},  /* 0x4b */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* New, 1280x960-85, not in any BIOS */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
    0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
    0x01}},  /* 0x4c */
  {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
@@ -542,16 +503,16 @@ static const SiS310_CRT1TableStruct SiS3
    0x01}},  /* 0x4d */
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}   /* 0x4e */
+   0x00}},  /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
+   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+   0x21}},  /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, /* 1680x1050-60 */
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+   0x20}}   /* 0x50 */
 };
 
-typedef struct _SiS310_MCLKDataStruct
-{
-	UCHAR SR28,SR29,SR2A;
-	USHORT CLOCK;
-} SiS310_MCLKDataStruct;
-
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_315[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
 {
 	{ 0x3b,0x22,0x01,143},
 	{ 0x5c,0x23,0x01,166},
@@ -563,7 +524,7 @@ static const SiS310_MCLKDataStruct SiS31
 	{ 0x5c,0x23,0x01,166}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
 {
 	{ 0x5a,0x64,0x82, 66},
 	{ 0xb3,0x45,0x82, 83},
@@ -575,7 +536,7 @@ static const SiS310_MCLKDataStruct SiS31
 	{ 0x37,0x22,0x82,133}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
 {
 	{ 0x5c,0x23,0x01,166},
 	{ 0x5c,0x23,0x01,166},
@@ -587,7 +548,7 @@ static const SiS310_MCLKDataStruct SiS31
 	{ 0x79,0x06,0x01,250}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_660[] =  /* TODO */
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
 {
 	{ 0x5c,0x23,0x82,166},
 	{ 0x5c,0x23,0x82,166},
@@ -599,7 +560,19 @@ static const SiS310_MCLKDataStruct SiS31
 	{ 0x37,0x21,0x82,200}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
+{
+	{ 0x37,0x22,0x82,133},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x7c,0x08,0x82,200},
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200}
+};
+
+static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
 {
         { 0x29,0x21,0x82,150},
 	{ 0x5c,0x23,0x82,166},
@@ -611,13 +584,7 @@ static const SiS310_MCLKDataStruct SiS31
 	{ 0x37,0x22,0x82,133}
 };
 
-typedef struct _SiS310_VCLKDataStruct
-{
-	UCHAR SR2B,SR2C;
-	USHORT CLOCK;
-} SiS310_VCLKDataStruct;
-
-static const SiS310_VCLKDataStruct SiS310_VCLKData[]=
+static SiS_VCLKDataStruct SiS310_VCLKData[]=
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -630,7 +597,7 @@ static const SiS310_VCLKDataStruct SiS31
 	{ 0x53,0xe2, 50}, /* 0x08 */
 	{ 0x74,0x67, 52}, /* 0x09 */
 	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x5a,0x64, 65}, /* 0x0b */  /* TW: was 6c c3 - WRONG */
+	{ 0x5a,0x64, 65}, /* 0x0b */  /* was 6c c3 - WRONG */
 	{ 0x46,0x44, 67}, /* 0x0c */
 	{ 0xb1,0x46, 68}, /* 0x0d */
 	{ 0xd3,0x4a, 72}, /* 0x0e */
@@ -644,7 +611,7 @@ static const SiS310_VCLKDataStruct SiS31
 	{ 0x62,0x44, 94}, /* 0x16 */
 	{ 0x2b,0x41,104}, /* 0x17 */
 	{ 0x3a,0x23,105}, /* 0x18 */
-	{ 0x70,0x44,108}, /* 0x19 */ 
+	{ 0x70,0x44,108}, /* 0x19 */
 	{ 0x3c,0x23,109}, /* 0x1a */
 	{ 0x5e,0x43,113}, /* 0x1b */
 	{ 0xbc,0x44,116}, /* 0x1c */
@@ -677,49 +644,51 @@ static const SiS310_VCLKDataStruct SiS31
 	{ 0xea,0x08,340}, /* 0x37 */
 	{ 0xe8,0x07,376}, /* 0x38 */
 	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f */  /* 301 TV */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
 	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x60,0x36, 30}, /* 0x41 */  /* Chrontel */
-	{ 0x40,0x4a, 28}, /* 0x42 */  /* Chrontel */
-	{ 0x9f,0x46, 44}, /* 0x43 */  /* Chrontel */
+	{ 0x60,0x36, 30}, /* 0x41 Chrontel */
+	{ 0x40,0x4a, 28}, /* 0x42 Chrontel */
+	{ 0x9f,0x46, 44}, /* 0x43 Chrontel */
 	{ 0x97,0x2c, 26}, /* 0x44 */
-	{ 0x44,0xe4, 25}, /* 0x45 */  /* Chrontel */
-	{ 0x7e,0x32, 47}, /* 0x46 */  /* Chrontel */
-	{ 0x8a,0x24, 31}, /* 0x47 */  /* Chrontel */
-	{ 0x97,0x2c, 26}, /* 0x48 */  /* Chrontel */
+	{ 0x44,0xe4, 25}, /* 0x45 Chrontel */
+	{ 0x7e,0x32, 47}, /* 0x46 Chrontel */
+	{ 0x8a,0x24, 31}, /* 0x47 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x48 Chrontel */
 	{ 0xce,0x3c, 39}, /* 0x49 */
-	{ 0x52,0x4a, 36}, /* 0x4a */  /* Chrontel */
+	{ 0x52,0x4a, 36}, /* 0x4a Chrontel */
 	{ 0x34,0x61, 95}, /* 0x4b */
 	{ 0x78,0x27,108}, /* 0x4c - was 102 */
-	{ 0x66,0x43,123}, /* 0x4d */  /* Modes 0x26-0x28 (1400x1050) */
+	{ 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
 	{ 0x41,0x4e, 21}, /* 0x4e */
-	{ 0xa1,0x4a, 29}, /* 0x4f */  /* Chrontel */
+	{ 0xa1,0x4a, 29}, /* 0x4f Chrontel */
 	{ 0x19,0x42, 42}, /* 0x50 */
-	{ 0x54,0x46, 58}, /* 0x51 */  /* Chrontel */
+	{ 0x54,0x46, 58}, /* 0x51 Chrontel */
 	{ 0x25,0x42, 61}, /* 0x52 */
-	{ 0x44,0x44, 66}, /* 0x53 */  /* Chrontel */
-	{ 0x3a,0x62, 70}, /* 0x54 */  /* Chrontel */
-	{ 0x62,0xc6, 34}, /* 0x55 - added for 848x480-60 (not in any BIOS) */
-	{ 0x6a,0xc6, 37}, /* 0x56 - added for 848x480-75 (not in any BIOS)    - TEMP */
-	{ 0xbf,0xc8, 35}, /* 0x57 - added for 856x480-38i,60 (not in any BIOS) */
-	{ 0x30,0x23, 88}, /* 0x58 - added for 1360x768-62 (is 60Hz!) (not in any BIOS) */
-	{ 0x52,0x07,149}, /* 0x59 - added for 1280x960-85 (Not in any BIOS) */
-	{ 0x56,0x07,156}, /* 0x5a - added for 1400x1050-75 */
-   	{ 0x70,0x29, 81}  /* 0x5b - added for 1280x768 LCD */
-};
-
-typedef struct _SiS310_VBVCLKDataStruct
-{
-	UCHAR Part4_A,Part4_B;
-	USHORT CLOCK;
-} SiS310_VBVCLKDataStruct;
+	{ 0x44,0x44, 66}, /* 0x53 Chrontel */
+	{ 0x3a,0x62, 70}, /* 0x54 Chrontel */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+   	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800  */
+	{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
+	{ 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x5a,0x64, 65}  /* 0x63 1280x720 (LCD LVDS) */
+};
 
-static const SiS310_VBVCLKDataStruct SiS310_VBVCLKData[]=
+static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -732,7 +701,7 @@ static const SiS310_VBVCLKDataStruct SiS
 	{ 0x53,0x47, 50}, /* 0x08 */
 	{ 0x74,0x67, 52}, /* 0x09 */
 	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62  */
+	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301: 35,62  */
 	{ 0x46,0x44, 67}, /* 0x0c */
 	{ 0xb1,0x46, 68}, /* 0x0d */
 	{ 0xd3,0x4a, 72}, /* 0x0e */
@@ -785,47 +754,48 @@ static const SiS310_VBVCLKDataStruct SiS
 	{ 0xea,0x08,340}, /* 0x37 */
 	{ 0xe8,0x07,376}, /* 0x38 */
 	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f */  /* 301 TV */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV - start */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
 	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x2e,0x48, 25}, /* 0x41 */  /* Replacement for LCD on 315 for index 0 */
-	{ 0x24,0x46, 25}, /* 0x42 */  /* Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
-	{ 0x26,0x64, 28}, /* 0x43 */  /* Replacement for LCD on 315 for index 1 */
-	{ 0x37,0x64, 40}, /* 0x44 */  /* Replacement for LCD on 315 for index 4 */
-	{ 0xa1,0x42,108}, /* 0x45 */  /* 1280x960 LCD */
-	{ 0x37,0x61,100}, /* 0x46 */  /* 1280x960 LCD */
+	{ 0x2e,0x48, 25}, /* 0x41 Replacement for LCD on 315 for index 0 */
+	{ 0x24,0x46, 25}, /* 0x42 Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
+	{ 0x26,0x64, 28}, /* 0x43 Replacement for LCD on 315 for index 1 */
+	{ 0x37,0x64, 40}, /* 0x44 Replacement for LCD on 315 for index 4 */
+	{ 0xa1,0x42,108}, /* 0x45 1280x960 LCD */
+	{ 0x37,0x61,100}, /* 0x46 1280x960 LCD */
 	{ 0x78,0x27,108}, /* 0x47 */
-	{ 0x97,0x2c, 26}, /* 0x48 */  /* UNUSED - Entries from here new, not in any BIOS */
-	{ 0xce,0x3c, 39}, /* 0x49 */  /* UNUSED */
-	{ 0x52,0x4a, 36}, /* 0x4a */  /* UNUSED */
-	{ 0x34,0x61, 95}, /* 0x4b */  /* UNUSED */
-	{ 0x78,0x27,108}, /* 0x4c */  /* UNUSED */
-	{ 0x66,0x43,123}, /* 0x4d */  /* 1400x1050-60 */
-	{ 0x41,0x4e, 21}, /* 0x4e */  /* UNUSED */
-	{ 0xa1,0x4a, 29}, /* 0x4f */  /* UNUSED */
-	{ 0x19,0x42, 42}, /* 0x50 */  /* UNUSED */
-	{ 0x54,0x46, 58}, /* 0x51 */  /* UNUSED */
-	{ 0x25,0x42, 61}, /* 0x52 */  /* UNUSED */
-	{ 0x44,0x44, 66}, /* 0x53 */  /* UNUSED */
-	{ 0x3a,0x62, 70}, /* 0x54 */  /* UNUSED */
-	{ 0x62,0xc6, 34}, /* 0x55 */  /* 848x480-60 */
-	{ 0x6a,0xc6, 37}, /* 0x56 */  /* 848x480-75 - TEMP, UNUSED */
-	{ 0xbf,0xc8, 35}, /* 0x57 */  /* 856x480-38i,60  */
-	{ 0x30,0x23, 88}, /* 0x58 */  /* 1360x768-62 (is 60Hz!) TEMP, UNUSED */
-	{ 0x52,0x07,149}, /* 0x59 */  /* 1280x960-85  */
-	{ 0x56,0x07,156}, /* 0x5a */  /* 1400x1050-75 */
-   	{ 0x70,0x29, 81}  /* 0x5b */  /* 1280x768 LCD */
-};
-
-static const UCHAR SiS310_ScreenOffset[] =
-{
-        0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,
-	0x78,0x80,0x2d,0x35,0x57,0x48,0x55,0x30,
-	0xff
+	{ 0x97,0x2c, 26}, /* 0x48 UNUSED */
+	{ 0xce,0x3c, 39}, /* 0x49 UNUSED */
+	{ 0x52,0x4a, 36}, /* 0x4a UNUSED */
+	{ 0x34,0x61, 95}, /* 0x4b UNUSED */
+	{ 0x78,0x27,108}, /* 0x4c UNUSED */
+	{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
+	{ 0x41,0x4e, 21}, /* 0x4e UNUSED */
+	{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
+	{ 0x19,0x42, 42}, /* 0x50 UNUSED */
+	{ 0x54,0x46, 58}, /* 0x51 UNUSED */
+	{ 0x25,0x42, 61}, /* 0x52 UNUSED */
+	{ 0x44,0x44, 66}, /* 0x53 UNUSED */
+	{ 0x3a,0x62, 70}, /* 0x54 UNUSED */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP, UNUSED */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60  */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85  */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+   	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x9c,0x62, 69}, /* 0x5c 1280x800 LCD - wrong? */
+	{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
+	{ 0x52,0x27, 75}, /* 0x5f 1280x720 LCD TMDS + HDTV (correct) */
+	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x5a,0x64, 65}  /* 0x63 1280x720 (LCD LVDS) */
 };
 
 static const DRAM4Type SiS310_SR15[8] = {
@@ -873,12 +843,7 @@ static const USHORT SiS310_VideoSenseDat
 static const USHORT SiS310_YCSenseData2    = 0x016b;
 #endif
 
-typedef struct _SiS310_PanelDelayTblStruct
-{
- 	UCHAR timer[2];
-} SiS310_PanelDelayTblStruct;
-
-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
 {
         {{0x10,0x40}},
 	{{0x10,0x40}},
@@ -898,7 +863,7 @@ static const SiS310_PanelDelayTblStruct 
 	{{0x10,0x40}}
 };
 
-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
 {
 	{{0x28,0xc8}},
 	{{0x28,0xc8}},
@@ -922,28 +887,18 @@ static const SiS310_PanelDelayTblStruct 
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS310_LCDDataStruct
-{
-	USHORT RVBHCMAX;
-	USHORT RVBHCFACT;
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS310_LCDDataStruct;
-
-static const SiS310_LCDDataStruct  SiS310_StLCD1024x768Data[]=
+static const SiS_LCDDataStruct  SiS310_St2LCD1024x768Data[] =
 {
 	{   62,  25, 800, 546,1344, 806},
 	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
+        {   62,  25, 800, 546,1344, 806},
 	{  104,  45, 945, 496,1344, 806},
 	{   62,  25, 800, 546,1344, 806},
 	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS310_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =   
+static const SiS_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =
 {
 	{   42,  25,1536, 419,1344, 806},
 	{   48,  25,1536, 369,1344, 806},
@@ -951,28 +906,10 @@ static const SiS310_LCDDataStruct  SiS31
 	{   48,  25,1536, 369,1344, 806},
 	{   12,   5, 896, 500,1344, 806},
 	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-	 
-};
-
-static const SiS310_LCDDataStruct  SiS310_St2LCD1024x768Data[] =  
-{
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-        {   62,  25, 800, 546,1344, 806},    
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS310_LCDDataStruct  SiS310_StLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
 {
 	{   22,   5, 800, 510,1650,1088},
 	{   22,   5, 800, 510,1650,1088},
@@ -984,7 +921,7 @@ static const SiS310_LCDDataStruct  SiS31
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS310_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
 {
 	{  211,  60,1024, 501,1688,1066},
 	{  211,  60,1024, 508,1688,1066},
@@ -993,53 +930,10 @@ static const SiS310_LCDDataStruct  SiS31
 	{  211,  60,1024, 500,1688,1066},
 	{  211,  75,1024, 625,1688,1066},
 	{  211, 120,1280, 798,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1800,1000,1688,1066}  /* 1280x960 - does not work, use panel scaler instead */
-};
-
-static const SiS310_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS310_LCDDataStruct  SiS310_NoScaleData1024x768[] =  
-{
-        {    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},  /* 640x400 - does not work */
-	{    1,   1,1344, 806,1344, 806},  /* 640x480 - does not work */
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const SiS310_LCDDataStruct  SiS310_NoScaleData1280x1024[] =
-{
-        {    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-typedef struct _SiS310_Part2PortTblStruct
-{
- 	UCHAR CR[12];
-} SiS310_Part2PortTblStruct;
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
+static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
 {
  {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
  {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
@@ -1047,646 +941,37 @@ static const SiS310_Part2PortTblStruct S
  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
  {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
  {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] =
-{
- {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x2c,0x12,0x38,0x55,0x2f,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}},
- {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},  /* others  */
-/* 0x36,0x13,0x02,0x25,0xff,0x03,0x45,0x09,0x07,0xf9,0x00,0x24        my      */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
+/* *** LCDA *** */
 
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] =
-{
-#if 1   /* Data from 650/301LVx 1.10.6s and others */
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x13,0xc9,0x24,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}}
+#if 0
+static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
+{ /* Clevo, 651+301C */
+	{1200, 450, 2048,1250},
+	{1200, 400, 2048,1250},
+	{1280, 450, 2048,1250},
+	{1280, 400, 2048,1250},
+	{1200, 530, 2048,1250},
+	{1360, 650, 2048,1250},
+	{1584, 818, 2048,1250},
+	{1688,1066, 2048,1250},
+	{1688,1066, 2048,1250},
+#if 0
+	{2048,1250, 2048,1250}   /* this should be correct */
 #endif
-#if 0    /* Data from my 301LV */
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},   /* TEST */
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}
+#if 1
+	{2160,1250, 2048,1250}   /* ? */
 #endif
 };
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] =
-{ /* Acer; BIOS data invalid, last row taken from _3 */
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x02,0x25,0xFF,0x03,0x45,0x09,0x07,0xF9,0x00,0x24}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_2[] =
-{ /* Acer */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-/*   1     2    4    5    6   1c   1d   1f   20   21   23   25   */
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] =
-{ /* Acer */
- {{0x31,0x1B,0xC4,0xDA,0xB0,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x34,0x1B,0x9F,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3E,0x1B,0xCF,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] =
-{
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_2[] =
-{
- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}},
- {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}},
- {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] =
-{
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] =
-{
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] =
-{
- {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x3A,0x1B,0x54,0x7A,0x48,0x80,0x24,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x36,0x1B,0x90,0xB6,0x84,0xA8,0x24,0x7A,0x30,0xCB,0x62,0x02}},
- {{0x3A,0x1C,0xE4,0x0A,0xD8,0xE0,0x24,0xB2,0x30,0x03,0x9A,0x02}},
- {{0x4A,0x24,0x64,0x8A,0x58,0x20,0x34,0xF2,0x30,0x43,0xDA,0x52}},
- {{0x47,0x24,0x71,0x97,0x65,0x3E,0x34,0x10,0x40,0x61,0xF8,0x02}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] =
-{
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-/* CRT1 CRTC for LCDA */
-
-typedef struct _SiS310_LCDACRT1DataStruct
-{
- 	UCHAR CR[17];
-}SiS310_LCDACRT1DataStruct;
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_1[]=
-{
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x04,0x3e,
-   0xE2,0x89,0xdf,0xdf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x63,0x8B,0x6D,0x18,0x7c,0xf0,
-   0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x06,
-   0x01}},
- {{0xA3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_1_H[]=
-{
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x55,0x31,0x31,0x99,0x3b,0x06,0x7c,0xf0,
-   0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x01,
-   0x01}},
- {{0x63,0x3F,0x3F,0x87,0x49,0x94,0x24,0xF5,
-   0x02,0x89,0xFF,0xFF,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_2[]=
-{
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xb3,
-   0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x06,
-   0x01}},
- {{0xa3,0x63,0x63,0x98,0x78,0x19,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_2_H[]=
-{
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xb3,
-   0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x01,
-   0x01 }},
- {{0x71,0x31,0x31,0x98,0x46,0x17,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02,
-   0x01 }},
- {{0x63,0x3f,0x3f,0x87,0x4c,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_1[]=
-{ /* Acer */
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x63,0x96,0x6c,0x18,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x7f,0x92,0x88,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_1_H[]=
-{  /* Acer */
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x31,0x84,0x3a,0x86,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x3f,0x92,0x48,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_2[]=
-{  /* Illegal data in BIOS (Acer, Compaq) */
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_2_H[]=
-{  /* Illegal data in BIOS (Acer, Compaq) */
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x31,0x31,0x93,0x3e,0x86,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01,
-   0x01 }},
- {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_1[]=
-{
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0xee,0x1f,
-   0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05,
-   0x00}},
- {{0x83,0x63,0x63,0x87,0x68,0x16,0x66,0xf0,
-   0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x06,
-   0x01}},
- {{0x9f,0x7f,0x7f,0x83,0x84,0x92,0x0e,0xf5,
-   0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x02,
-   0x01}},
- {{0xbf,0x9f,0x9f,0x83,0xa4,0x12,0x0e,0x5a,
-   0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0xae,0xae,0x92,0xb3,0x01,0x28,0x10,
-   0x1a,0x80,0x19,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_1_H[]=
-{
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
-    0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-    0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
-    0x92,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-    0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
-    0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05,
-    0x00}},
-  {{0x51,0x31,0x31,0x95,0x36,0x04,0x66,0xf0,
-    0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x01,
-    0x01}},
-  {{0x5f,0x3f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
-    0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x01,
-    0x01}},
-  {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-    0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x05,
-    0x01}},
-  {{0x76,0x56,0x56,0x9a,0x5b,0x89,0x28,0x10,
-    0x1c,0x80,0x19,0x19,0x29,0x0b,0x00,0x05,
-    0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_2[]=
-{
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03,
-   0x01}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9e,
-   0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x63,0x63,0x92,0x96,0x04,0x28,0xd4,
-   0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x07,
-   0x01}},
- {{0xce,0x7f,0x7f,0x92,0xa4,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xb4,0x02,0x28,0x5a,
-   0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x03,
-   0x01}},
- {{0xce,0xae,0xae,0x92,0xbc,0x0a,0x28,0x10,
-   0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_2_H[]=
-{
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9e,
-   0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0x9c,0x31,0x31,0x80,0x64,0x92,0x28,0xd4,
-   0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x06,
-   0x01}},
- {{0x8e,0x3f,0x3f,0x92,0x64,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x06,
-   0x01}},
- {{0x7e,0x4f,0x4f,0x82,0x64,0x12,0x28,0x5a,
-   0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x06,
-   0x01}},
- {{0x76,0x56,0x56,0x9a,0x64,0x92,0x28,0x10,
-   0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x05,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_1[]=
-{
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x10,0x3E,
-   0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x63,0x9B,0x65,0x1D,0x88,0xF0,
-   0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x06,
-   0x01}},
- {{0xB3,0x7F,0x7F,0x97,0x81,0x99,0x30,0xF5,
-   0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x02,
-   0x01}},
- {{0xD3,0x9F,0x9F,0x97,0xA1,0x19,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x07,
-   0x01}},
- {{0xE2,0xAE,0xAE,0x86,0xB0,0x88,0x4A,0x10,
-   0x1A,0x8E,0x19,0x19,0x4B,0x2F,0x00,0x03,
-   0x00}},
- {{0xFB,0xC7,0xC7,0x9F,0xC9,0x81,0xE0,0x10,
-   0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x07,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_1_H[]=
-{
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x10,0x3E,
-   0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x01,
-   0x00}},
- {{0x73,0x31,0x31,0x97,0x3A,0x92,0x88,0xF0,
-   0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x01,
-   0x01}},
- {{0x81,0x3F,0x3F,0x85,0x48,0x00,0x30,0xF5,
-   0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x06,
-   0x01}},
- {{0x91,0x4F,0x4F,0x95,0x58,0x10,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x06,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0xA5,0x63,0x63,0x89,0x6C,0x84,0xE0,0x10,
-   0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x02,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_2[]=
-{
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x63,0x63,0x8D,0xAD,0x05,0xE0,0xD4,
-   0x9B,0x8F,0x57,0x57,0xE1,0x21,0x01,0x00,
-   0x01}},
- {{0x09,0x7F,0x7F,0x8D,0xBB,0x13,0xE0,0xD4,
-   0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x01,0x00,
-   0x01}},
- {{0x09,0x9F,0x9F,0x8D,0xCB,0x03,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x01,0x04,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0x09,0xC7,0xC7,0x8D,0xDF,0x17,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x01,0x04,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_2_H[]=
-{
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xD7,0x31,0x31,0x9B,0x7B,0x13,0xE0,0xD4,
-   0x9B,0x8F,0x57,0x57,0xE1,0x21,0x00,0x03,
-   0x01}},
- {{0xC9,0x3F,0x3F,0x8D,0x7B,0x13,0xE0,0xD4,
-   0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x00,0x03,
-   0x01}},
- {{0xB9,0x4F,0x4F,0x9D,0x7B,0x93,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x00,0x02,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0xA5,0x63,0x63,0x89,0x7B,0x93,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x00,0x02,
-   0x00}}
-};
-
+#endif
 
 /**************************************************************/
 /* LVDS, CHRONTEL ------------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS310_LVDSDataStruct
-{
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS310_LVDSDataStruct;
-
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1697,7 +982,7 @@ static const SiS310_LVDSDataStruct  SiS3
 	{1400,1000,1400,1000}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALData[]= 
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1708,7 +993,7 @@ static const SiS310_LVDSDataStruct  SiS3
         {1400, 875,1400, 875}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALMData[]=  
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALMData[]=
 {
 	{ 840, 600, 840, 600},
 	{ 840, 600, 840, 600},
@@ -1719,7 +1004,7 @@ static const SiS310_LVDSDataStruct  SiS3
         {1160, 945,1160, 945}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALMData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALMData[]=
 {
 	{ 840, 525, 840, 525},
 	{ 840, 525, 840, 525},
@@ -1730,7 +1015,7 @@ static const SiS310_LVDSDataStruct  SiS3
         {1160, 840,1160, 840}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALNData[]=  
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALNData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1741,7 +1026,7 @@ static const SiS310_LVDSDataStruct  SiS3
 	{1400,1000,1400,1000}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALNData[]= 
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALNData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1752,7 +1037,7 @@ static const SiS310_LVDSDataStruct  SiS3
         {1400, 875,1400, 875}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* TW: (super overscan - no effect on 7019) */
+static const SiS_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* (super overscan - no effect on 7019) */
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1763,13 +1048,8 @@ static const SiS310_LVDSDataStruct  SiS3
         {1400, 875,1400, 875}       	
 };
 
-typedef struct _SiS310_LVDSDesStruct
-{
-	USHORT LCDHDES;
-	USHORT LCDVDES;
-} SiS310_LVDSDesStruct;
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
+static const SiS_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1782,7 +1062,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1795,7 +1075,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
+static const SiS_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1810,7 +1090,7 @@ static const SiS310_LVDSDesStruct  SiS31
 };
 
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType03_1[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType03_1[]=
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1823,7 +1103,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType04_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType04_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1836,7 +1116,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType05_1[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType05_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1849,7 +1129,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType06_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType06_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1862,7 +1142,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType07_1[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType07_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1875,7 +1155,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
+static const SiS_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1890,7 +1170,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1905,7 +1185,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1920,7 +1200,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
 {
 	{ 0, 524},
 	{ 0, 524},
@@ -1932,7 +1212,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 524}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
 {
 	{ 0, 524},
 	{ 0, 524},
@@ -1944,7 +1224,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0, 524}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0d_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType0d_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1957,7 +1237,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0e_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0e_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1970,7 +1250,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0f_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0f_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1983,7 +1263,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType00_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType00_2[]=
 {
 	{980, 528},
 	{980, 503},
@@ -1996,7 +1276,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType01_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType01_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2009,7 +1289,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType02_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType02_2[]=
 {
 	{1368, 754},
 	{1368, 729},
@@ -2024,7 +1304,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType03_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType03_2[]=
 {
 	{ 0,   0},
 	{ 0,   0},
@@ -2035,7 +1315,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType04_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType04_2[]=
 {
 	{ 0,   0},
 	{ 0,   0},
@@ -2048,7 +1328,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType05_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType05_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2061,7 +1341,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType06_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType06_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2074,7 +1354,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType07_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType07_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2087,7 +1367,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
+static const SiS_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
 {
 	{1308, 741},
 	{1308, 716},
@@ -2102,7 +1382,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{   0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
 {
 	{1083, 622},
 	{1083, 597},
@@ -2115,7 +1395,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{   0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
 {
 	{1568, 920},
 	{1568, 895},
@@ -2141,7 +1421,7 @@ static const SiS310_LVDSDesStruct  SiS31
 #endif
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
 {
 	{1152, 622},
 	{1152, 597},
@@ -2154,7 +1434,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
 {
 	{1152, 622},
 	{1152, 597},
@@ -2167,7 +1447,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0d_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0d_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2180,7 +1460,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0e_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType0e_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2193,7 +1473,7 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0f_2[] = 
+static const SiS_LVDSDesStruct  SiS310_PanelType0f_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -2206,14 +1486,37 @@ static const SiS310_LVDSDesStruct  SiS31
 	{ 0,   0}
 };
 
-/* CRT1 CRTC for SlaveModes and LCDA */
+static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_1[]=
+{
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0, 806},
+	{ 0,   0}
+};
 
-typedef struct _SiS310_LVDSCRT1DataStruct
+static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_2[] =
 {
- 	UCHAR CR[15];
-} SiS310_LVDSCRT1DataStruct;
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0}
+};
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
+/* CRT1 CRTC for SlaveModes and LCDA */
+
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
 {
  {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -2235,7 +1538,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
 {
  {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -2257,7 +1560,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
 {
  {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
    0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
@@ -2279,7 +1582,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
 {
  {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
    0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
@@ -2301,7 +1604,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
 {
  {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
    0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
@@ -2326,7 +1629,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
 {
  {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
    0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
@@ -2351,7 +1654,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
 {
  {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
    0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
@@ -2376,7 +1679,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
 {
  {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
    0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
@@ -2401,7 +1704,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
 {
  {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
    0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
@@ -2429,7 +1732,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =
 {
  {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
    0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
@@ -2454,7 +1757,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =
 {
  {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
    0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
@@ -2482,7 +1785,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] =
 {
  {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
    0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
@@ -2507,7 +1810,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
 {
   {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
     0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
@@ -2567,7 +1870,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] =
 {
  {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
    0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
@@ -2627,7 +1930,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =
 {
  {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
    0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
@@ -2687,7 +1990,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =
 {
  {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
    0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
@@ -2747,7 +2050,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
 {
  {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
    0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
@@ -2813,7 +2116,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
 {
  {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
    0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
@@ -2879,7 +2182,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
 {
  {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
    0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
@@ -2945,7 +2248,7 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] =
 {
  {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
    0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
@@ -3011,9 +2314,66 @@ static const SiS310_LVDSCRT1DataStruct  
 #endif
 };
 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+   0x01}}
+};
+
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1_H[] =
+{
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},
+ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+   0x01}},
+ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+   0x01}}
+};
+
+
 /* CRT1 CRTC for Chrontel TV slave modes */
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =
 { 
  {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
    0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -3038,7 +2398,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
 {
  {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
    0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -3063,7 +2423,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =    
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =
 { 
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -3088,7 +2448,7 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
 {
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -3113,12 +2473,8 @@ static const SiS310_LVDSCRT1DataStruct  
    0x01 }}
 };
 
-typedef struct _SiS310_CHTVRegDataStruct
-{
- 	UCHAR Reg[16];
-} SiS310_CHTVRegDataStruct;
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
 {
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3138,7 +2494,7 @@ static const SiS310_CHTVRegDataStruct Si
       for PAL-M and PAL-N all above is corrected.
     */
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
 {
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3149,7 +2505,7 @@ static const SiS310_CHTVRegDataStruct Si
  {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3160,7 +2516,7 @@ static const SiS310_CHTVRegDataStruct Si
  {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3171,7 +2527,7 @@ static const SiS310_CHTVRegDataStruct Si
  {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
 {
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3187,7 +2543,7 @@ static const SiS310_CHTVRegDataStruct Si
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
 {
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3203,7 +2559,7 @@ static const SiS310_CHTVRegDataStruct Si
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -3219,7 +2575,7 @@ static const SiS310_CHTVRegDataStruct Si
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/init.c linux-2.4.26-pre6/drivers/video/sis/init.c
--- linux-2.4.25/drivers/video/sis/init.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/init.c	2004-03-25 00:18:37.000000000 +0000
@@ -34,13 +34,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -78,7 +75,6 @@
 
 #if defined(ALLOC_PRAGMA)
 #pragma alloc_text(PAGE,SiSSetMode)
-#pragma alloc_text(PAGE,SiSInit)
 #endif
 
 /*********************************************/
@@ -108,17 +104,20 @@ InitCommonPointer(SiS_Private *SiS_Pr, P
    SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
    SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
    SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;
-   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
+
    SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
    SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
    SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
+#if 0
+   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
    SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
+#endif
 
    SiS_Pr->SiS_StPALData   = SiS_StPALData;
    SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
    SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
    SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
-/* SiS_Pr->SiS_St1HiTVData = SiS_St1HiTVData;  */
+   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData; 
    SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
    SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
    SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
@@ -131,16 +130,17 @@ InitCommonPointer(SiS_Private *SiS_Pr, P
    SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
    SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
 
+   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
+   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
+   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
+   SiS_Pr->SiS_LCD1280x768_3Data    = SiS_LCD1280x768_3Data;
+   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
    SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
-   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
-   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
+   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
+   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
    SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
-   SiS_Pr->SiS_NoScaleData1400x1050 = SiS_NoScaleData1400x1050;
-   SiS_Pr->SiS_NoScaleData1600x1200 = SiS_NoScaleData1600x1200;
-   SiS_Pr->SiS_ExtLCD1280x768Data   = SiS_ExtLCD1280x768Data;
-   SiS_Pr->SiS_StLCD1280x768Data    = SiS_StLCD1280x768Data;
-   SiS_Pr->SiS_NoScaleData1280x768  = SiS_NoScaleData1280x768;
+   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
 
    SiS_Pr->SiS_LVDS320x480Data_1   = SiS_LVDS320x480Data_1;
@@ -169,41 +169,12 @@ InitCommonPointer(SiS_Private *SiS_Pr, P
    SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
    SiS_Pr->SiS_LVDS640x480Data_2   = SiS_LVDS640x480Data_2;
 
-   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
-   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
-   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
-   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
    SiS_Pr->SiS_LVDS848x480Data_1   = SiS_LVDS848x480Data_1;
    SiS_Pr->SiS_LVDS848x480Data_2   = SiS_LVDS848x480Data_2;
-
-   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
-   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
-
-   SiS_Pr->SiS_LCDA1024x768Data_1  = SiS_LCDA1024x768Data_1;
-   SiS_Pr->SiS_LCDA1024x768Data_2  = SiS_LCDA1024x768Data_2;
-   SiS_Pr->SiS_LCDA1280x1024Data_1 = SiS_LCDA1280x1024Data_1;
-   SiS_Pr->SiS_LCDA1280x1024Data_2 = SiS_LCDA1280x1024Data_2;
-   SiS_Pr->SiS_LCDA1400x1050Data_1 = SiS_LCDA1400x1050Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_2 = SiS_LCDA1400x1050Data_2;
-   SiS_Pr->SiS_LCDA1600x1200Data_1 = SiS_LCDA1600x1200Data_1;
-   SiS_Pr->SiS_LCDA1600x1200Data_2 = SiS_LCDA1600x1200Data_2;
-
-   SiS_Pr->LVDS1024x768Des_1  = SiS_PanelType1076_1;
-   SiS_Pr->LVDS1280x1024Des_1 = SiS_PanelType1210_1;
-   SiS_Pr->LVDS1400x1050Des_1 = SiS_PanelType1296_1;
-   SiS_Pr->LVDS1600x1200Des_1 = SiS_PanelType1600_1;
-   SiS_Pr->LVDS1024x768Des_2  = SiS_PanelType1076_2;
-   SiS_Pr->LVDS1280x1024Des_2 = SiS_PanelType1210_2;
-   SiS_Pr->LVDS1400x1050Des_2 = SiS_PanelType1296_2;
-   SiS_Pr->LVDS1600x1200Des_2 = SiS_PanelType1600_2;
-
-   SiS_Pr->SiS_PanelTypeNS_1 = SiS_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = SiS_PanelTypeNS_2;
-
-   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
-   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
-   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
-   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
+   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
+   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
 
    SiS_Pr->SiS_LVDSCRT11280x768_1    = SiS_LVDSCRT11280x768_1;
    SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
@@ -218,14 +189,23 @@ InitCommonPointer(SiS_Private *SiS_Pr, P
    SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
    SiS_Pr->SiS_LVDSCRT11152x768_2_H  = SiS_LVDSCRT11152x768_2_H;
    SiS_Pr->SiS_LVDSCRT1320x480_1     = SiS_LVDSCRT1320x480_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS_LVDSCRT1XXXxXXX_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS_LVDSCRT1XXXxXXX_1_H;
    SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
    SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
    SiS_Pr->SiS_LVDSCRT1640x480_2     = SiS_LVDSCRT1640x480_2;
    SiS_Pr->SiS_LVDSCRT1640x480_2_H   = SiS_LVDSCRT1640x480_2_H;
    SiS_Pr->SiS_LVDSCRT1640x480_3     = SiS_LVDSCRT1640x480_3;
    SiS_Pr->SiS_LVDSCRT1640x480_3_H   = SiS_LVDSCRT1640x480_3_H;
+
+   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
+   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
+
+   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
+   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
+   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
+   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+
+   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
+   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
 }
 
 #ifdef SIS300
@@ -262,19 +242,18 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
    SiS_StandTable[0x1c].CRTC[4] = 0x54;
    SiS_StandTable[0x1c].CRTC[5] = 0x80;
 
-   SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS300_SModeIDTable;
-   SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS300_EModeIDTable;
-   SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS300_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS300_CRT1Table;
+   SiS_Pr->SiS_SModeIDTable  = SiS300_SModeIDTable;
+   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
+   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
+   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
    if(HwInfo->jChipType == SIS_300) {
-      SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_300; /* 300 */
+      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_300; /* 300 */
    } else {
-      SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630, 730 */
+      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_630; /* 630, 730 */
    }
-   SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS300_VCLKData;
+   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
    SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
-   SiS_Pr->SiS_ScreenOffset  = SiS300_ScreenOffset;
 
    SiS_Pr->SiS_SR15  = SiS300_SR15;
 
@@ -303,97 +282,102 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
    SiS_Pr->pSiS_YCSenseData2    = &SiS300_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data;
-   SiS_Pr->SiS_StLCD1280x1024Data   = (SiS_LCDDataStruct *)SiS300_StLCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data;
-   SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768;
-   SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024;
+   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
 
-   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
-#if 0
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS;
-#endif
-
-   SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; 			   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; 			   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData;
-
-   SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS300_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS300_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS300_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS300_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS300_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS300_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS300_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS300_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS300_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS300_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS300_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS300_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS300_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS300_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS300_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1;
+   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2;
+   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
+
+   SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1;
+   SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1;
+   SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1;
+   SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1;
+   SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1;
+   SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1;
+   SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1;
+   SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1;
+   SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1;
+   SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1;
+   SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1;
+   SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1;
+   SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1;
+   SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1;
+   SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1;
+   SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1;
+   SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2;
+   SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2;
+   SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2;
+   SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2;
+   SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2;
+   SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2;
+   SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2;
+   SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2;
+   SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2;
+   SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2;
+   SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2;
+   SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2;
+   SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2;
+   SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2;
+   SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2;
+   SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2;
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2;
 
    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1a;
-      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2a;
+      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a;
+      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a;
    }
    if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1b;
-      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2b;
+      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b;
+      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b;
    }
 
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1SOPAL;
-   SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_SOPAL;
+   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS300_LVDSCRT1800x600_1;
+   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS300_LVDSCRT1800x600_1_H;
+   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS300_LVDSCRT1800x600_2;
+   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS300_LVDSCRT1800x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS300_LVDSCRT11024x768_1;
+   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS300_LVDSCRT11024x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS300_LVDSCRT11024x768_2;
+   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS300_LVDSCRT11024x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS300_LVDSCRT11280x1024_1;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS300_LVDSCRT11280x1024_2;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS300_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS300_LVDSCRT1XXXxXXX_1_H;
+
+   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
    SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
@@ -403,40 +387,6 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
    SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_2;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_2;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_3;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3;
-
-   /* LCDResInfo will on 300 series be translated to 315 series definitions */
-   SiS_Pr->SiS_Panel320x480   = Panel_320x480;
-   SiS_Pr->SiS_Panel640x480   = Panel_640x480;
-   SiS_Pr->SiS_Panel800x600   = Panel_800x600;
-   SiS_Pr->SiS_Panel1024x768  = Panel_1024x768;
-   SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024;
-   SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
-   SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
-   SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
-   SiS_Pr->SiS_Panel1600x1200 = 255;  		   /* Something illegal */
-   SiS_Pr->SiS_Panel1400x1050 = 255;
-   SiS_Pr->SiS_Panel640x480_2 = 255;
-   SiS_Pr->SiS_Panel640x480_3 = 255;
-   SiS_Pr->SiS_Panel1152x864  = 255;
-   SiS_Pr->SiS_PanelMax       = Panel_320x480;     /* highest value */
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;     /* Lowest value LVDS */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;    /* lowest value 301 */
-   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
-   SiS_Pr->SiS_PanelBarco1366 = Panel_Barco1366;
 }
 #endif
 
@@ -474,23 +424,24 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
    SiS_StandTable[0x1c].CRTC[4] = 0x55;
    SiS_StandTable[0x1c].CRTC[5] = 0x81;
 
-   SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS310_SModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS310_EModeIDTable;
+   SiS_Pr->SiS_SModeIDTable  = SiS310_SModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
    SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS310_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS310_CRT1Table;
-   if(HwInfo->jChipType >= SIS_661) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_660;  /* 661/741/760 */
+   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
+   if(HwInfo->jChipType >= SIS_760) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
+   } else if(HwInfo->jChipType >= SIS_661) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
    } else if(HwInfo->jChipType == SIS_330) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330;  /* 330 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
    } else if(HwInfo->jChipType > SIS_315PRO) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650;  /* 550, 650, 740 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
    } else {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315;  /* 315 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
    }
-   SiS_Pr->SiS_MCLKData_1    = (SiS_MCLKDataStruct *)SiS310_MCLKData_1;
-   SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS310_VCLKData;
-   SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData;
-   SiS_Pr->SiS_ScreenOffset  = SiS310_ScreenOffset;
+   SiS_Pr->SiS_MCLKData_1    = SiS310_MCLKData_1;
+   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
+   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
 
    SiS_Pr->SiS_SR15  = SiS310_SR15;
 
@@ -519,124 +470,96 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
    SiS_Pr->pSiS_YCSenseData2    = &SiS310_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data;
-   SiS_Pr->SiS_StLCD1280x1024Data   = (SiS_LCDDataStruct *)SiS310_StLCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data;
-   SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768;
-   SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024;
-
-   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS;
-
-   SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData;
-   SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALMData;
-   SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData;
-   SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData;
-   SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData;
-
-   SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS310_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS310_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS310_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS310_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS310_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS310_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS310_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS310_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS310_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS310_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS310_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS310_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS310_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS310_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS310_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS310_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS310_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_2;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_2;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_3;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3;
-
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-
-   SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALM;
-   SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALM;
-   SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN;
-   SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN;
-   SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL;
-
-   SiS_Pr->SiS_LCDACRT11024x768_1    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1;
-   SiS_Pr->SiS_LCDACRT11280x1024_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1;
-   SiS_Pr->SiS_LCDACRT11400x1050_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1;
-   SiS_Pr->SiS_LCDACRT11600x1200_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1;
-   SiS_Pr->SiS_LCDACRT11024x768_1_H  = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1_H;
-   SiS_Pr->SiS_LCDACRT11280x1024_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1_H;
-   SiS_Pr->SiS_LCDACRT11400x1050_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1_H;
-   SiS_Pr->SiS_LCDACRT11600x1200_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1_H;
-   SiS_Pr->SiS_LCDACRT11024x768_2    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2;
-   SiS_Pr->SiS_LCDACRT11280x1024_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2;
-   SiS_Pr->SiS_LCDACRT11400x1050_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2;
-   SiS_Pr->SiS_LCDACRT11600x1200_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2;
-   SiS_Pr->SiS_LCDACRT11024x768_2_H  = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2_H;
-   SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H;
-   SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H;
-   SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H;
+   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
+
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
+
+   SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1;
+   SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1;
+   SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1;
+   SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1;
+   SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1;
+   SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1;
+   SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1;
+   SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1;
+   SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1;
+   SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1;
+   SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1;
+   SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1;
+   SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1;
+   SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1;
+   SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1;
+   SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1;
+   SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2;
+   SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2;
+   SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2;
+   SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2;
+   SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2;
+   SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2;
+   SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2;
+   SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2;
+   SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2;
+   SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2;
+   SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2;
+   SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2;
+   SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2;
+   SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2;
+   SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2;
+   SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2;
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
+   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
+   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
+   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
+   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
+
+   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS310_LVDSCRT1800x600_1;
+   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS310_LVDSCRT11024x768_1;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS310_LVDSCRT11280x1024_1;
+   SiS_Pr->SiS_LVDSCRT11400x1050_1   = SiS310_LVDSCRT11400x1050_1;
+   SiS_Pr->SiS_LVDSCRT11600x1200_1   = SiS310_LVDSCRT11600x1200_1;
+   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS310_LVDSCRT1800x600_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS310_LVDSCRT11024x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H;
+   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H;
+   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H;
+   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS310_LVDSCRT1800x600_2;
+   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS310_LVDSCRT11024x768_2;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS310_LVDSCRT11280x1024_2;
+   SiS_Pr->SiS_LVDSCRT11400x1050_2   = SiS310_LVDSCRT11400x1050_2;
+   SiS_Pr->SiS_LVDSCRT11600x1200_2   = SiS310_LVDSCRT11600x1200_2;
+   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS310_LVDSCRT1800x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS310_LVDSCRT11024x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H;
+   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H;
+   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS310_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS310_LVDSCRT1XXXxXXX_1_H;
+   SiS_Pr->SiS_CHTVCRT1UNTSC         = SiS310_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC         = SiS310_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL          = SiS310_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL          = SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL         = SiS310_CHTVCRT1OPAL;
+
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
 
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
@@ -645,28 +568,8 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
    SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
    SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
    SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
-   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;   
+   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
-
-   SiS_Pr->SiS_Panel320x480   = Panel_320x480;
-   SiS_Pr->SiS_Panel640x480   = Panel_640x480;
-   SiS_Pr->SiS_Panel800x600   = Panel_800x600;
-   SiS_Pr->SiS_Panel1024x768  = Panel_1024x768;
-   SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024;
-   SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
-   SiS_Pr->SiS_Panel1600x1200 = Panel_1600x1200;
-   SiS_Pr->SiS_Panel1400x1050 = Panel_1400x1050;
-   SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1152x864  = Panel_1152x864;
-   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
-   SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
-   SiS_Pr->SiS_Panel640x480_2 = Panel_640x480_2;
-   SiS_Pr->SiS_Panel640x480_3 = Panel_640x480_3;
-   SiS_Pr->SiS_PanelMax       = Panel_320x480;    /* highest value */
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
-   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
-   SiS_Pr->SiS_PanelBarco1366 = 255;
 }
 #endif
 
@@ -707,7 +610,8 @@ SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_
 /*********************************************/
 
 USHORT
-SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN)
+SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
+              int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
 {
    USHORT ModeIndex = 0;
 
@@ -775,10 +679,23 @@ SiS_GetModeID(int VGAEngine, ULONG VBFla
 	  }
 	  break;
      case 1280:
-          if(VDisplay == 1024)        ModeIndex = ModeIndex_1280x1024[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
+          if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	  else if(VDisplay == 800) {
+	     if(VGAEngine == SIS_315_VGA) {
+	        if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 800)) {
+	           ModeIndex = ModeIndex_1280x800[Depth];
+	        } else if(!(VBFlags & CRT1_LCDA)) {
+	           ModeIndex = ModeIndex_1280x800[Depth];
+	        }
+	     }
+	  } else if(VDisplay == 720) {
+	     if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 720)) {
+	        ModeIndex = ModeIndex_1280x720[Depth];
+	     } else if(!(VBFlags & CRT1_LCDA)) {
+	        ModeIndex = ModeIndex_1280x720[Depth];
+	     }
+	  } else if(!(VBFlags & CRT1_LCDA)) {
              if(VDisplay == 960)      ModeIndex = ModeIndex_1280x960[Depth];
-	     else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth];
 	     else if(VDisplay == 768) {
 	        if(VGAEngine == SIS_300_VGA) {
 	           ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -798,12 +715,25 @@ SiS_GetModeID(int VGAEngine, ULONG VBFla
           break;
      case 1400:
           if(VGAEngine == SIS_315_VGA) {
-	     if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+	     if(VDisplay == 1050) {
+	        if((VBFlags & CRT1_LCDA) &&
+	           (((LCDwidth == 1400) && (LCDheight == 1050)) ||
+		    ((LCDwidth == 1600) && (LCDheight == 1200)))) {
+	           ModeIndex = ModeIndex_1400x1050[Depth];
+	        } else if(!(VBFlags & CRT1_LCDA)) {
+	           ModeIndex = ModeIndex_1400x1050[Depth];
+	        }
+	     }
 	  }
           break;
      case 1600:
           if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
           break;
+     case 1680:
+          if(VGAEngine == SIS_315_VGA) {
+             if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+	  }
+          break;
      case 1920:
           if(!(VBFlags & CRT1_LCDA)) {
              if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
@@ -848,14 +778,18 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG V
              break;
      	case 400:
 	     if(CustomT != CUT_PANEL848) {
-          	if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+	        if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
+          	   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+		}
 	     }
              break;
 	case 512:
 	     if(CustomT != CUT_PANEL848) {
-		if(VDisplay == 384) {
+	        if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
 		   if(LCDwidth != 1024 || LCDheight != 600) {
-		      ModeIndex = ModeIndex_512x384[Depth];
+		      if(VDisplay == 384) {
+		         ModeIndex = ModeIndex_512x384[Depth];
+		      }
 		   }
 		}
 	     }
@@ -895,6 +829,9 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG V
 	        if((VDisplay == 768) && (LCDheight == 768)) {
 		   ModeIndex = ModeIndex_310_1280x768[Depth];
 		}
+		if((VDisplay == 800) && (LCDheight == 800)) {
+		   ModeIndex = ModeIndex_310_1280x768[Depth];
+		}
 	     }
 	     break;
 	case 1360:
@@ -946,7 +883,7 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG V
 	case 1280:
 	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 	     else if(VDisplay == 768) {
-		if((LCDheight == 768) ||
+		if((LCDheight == 768) || (LCDwidth == 1680) ||
 		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
 		   if(VGAEngine == SIS_300_VGA) {
 		      ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -959,20 +896,41 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG V
 		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
 		   ModeIndex = ModeIndex_1280x960[Depth];
 		}
+	     } else if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 800) {
+		   if((LCDheight == 800) || (LCDwidth == 1680) ||
+		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		      ModeIndex = ModeIndex_1280x800[Depth];
+		   }
+		} else if(VDisplay == 720) {
+		   if((LCDheight == 720) || (LCDwidth == 1680) ||
+		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		      ModeIndex = ModeIndex_1280x720[Depth];
+		   }
+		}
 	     }
 	     break;
 	case 1400:
 	     if(VGAEngine == SIS_315_VGA) {
 	        if(VBFlags & (VB_301B | VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
-		   if(LCDheight != 1200) {
-	              if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+		   if((LCDwidth == 1400) || (LCDwidth == 1600) || (LCDwidth == 1680)) {
+		      ModeIndex = ModeIndex_1400x1050[Depth];
 		   }
 		}
 	     }
 	     break;
 	case 1600:
-	     if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
-	        if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
+	           if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+		}
+	     }
+	     break;
+	case 1680:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
+	           if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		}
 	     }
 	     break;
       }
@@ -1021,8 +979,8 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VB
              if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
              break;
       	case 512:
-	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR525P | TV_YPBPR750P))) ||
-	         (VBFlags & TV_HIVISION) 					     ||
+	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
+	         (VBFlags & TV_HIVISION) 					      ||
 	         ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 	        if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 	     }
@@ -1032,19 +990,21 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VB
 	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 	     break;
 	case 720:
-	     if(!(VBFlags & TV_HIVISION)) {
+	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
                 if(VDisplay == 480) {
 		   if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM)))
                       ModeIndex = ModeIndex_720x480[Depth];
                 } else if(VDisplay == 576) {
-		   if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))
+		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
                       ModeIndex = ModeIndex_720x576[Depth];
                 }
 	     }
              break;
 	case 768:
-	     if(!(VBFlags & TV_HIVISION)) {
-	        if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) {
+	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
+	        if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
           	   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 		}
              }
@@ -1052,7 +1012,7 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VB
 	case 800:
 	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 	     else if(VDisplay == 480) {
-	        if(VBFlags & TV_HIVISION) {
+	        if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 		   ModeIndex = ModeIndex_800x480[Depth];
 		}
 	     }
@@ -1063,15 +1023,22 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VB
 		   ModeIndex = ModeIndex_1024x768[Depth];
 		}
 	     } else if(VDisplay == 576) {
-	        if(VBFlags & TV_HIVISION) {
+	        if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 		   ModeIndex = ModeIndex_1024x576[Depth];
 		}
 	     }
 	     break;
 	case 1280:
-	     if(VBFlags & TV_HIVISION) {
-	        if(VDisplay == 720)       ModeIndex = ModeIndex_1280x720[Depth];
-		else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	     if(VDisplay == 720) {
+	        if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
+	           ModeIndex = ModeIndex_1280x720[Depth];
+		}
+	     } else if(VDisplay == 1024) {
+	        if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+	           ModeIndex = ModeIndex_1280x1024[Depth];
+		}
 	     }
 	     break;
       }
@@ -1138,6 +1105,7 @@ SiS_GetModeID_VGA2(int VGAEngine, ULONG 
 		   }
 		} else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 		else if(VDisplay == 720)    ModeIndex = ModeIndex_1280x720[Depth];
+		else if(VDisplay == 800)    ModeIndex = ModeIndex_1280x800[Depth];
 		else if(VDisplay == 960)    ModeIndex = ModeIndex_1280x960[Depth];
 		break;
         case 1360:
@@ -1155,6 +1123,13 @@ SiS_GetModeID_VGA2(int VGAEngine, ULONG 
 		   }
 		}
 		break;
+	case 1680:
+		if(VGAEngine == SIS_315_VGA) {
+		   if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
+	              if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		   }
+		}
+		break;
    }
 
    return ModeIndex;
@@ -1252,13 +1227,13 @@ SiS_SetRegOR(SISIOADDRESS Port,USHORT In
 void
 SiS_DisplayOn(SiS_Private *SiS_Pr)
 {
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x00);
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 }
 
 void
 SiS_DisplayOff(SiS_Private *SiS_Pr)
 {
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x20);
+   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
 }
 
 
@@ -1301,6 +1276,15 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSI
 {
    unsigned char cr5f, temp1, temp2;
 
+   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
+   /* (SR11 is used for DDC and in enable/disablebridge) */
+   SiS_Pr->SiS_SensibleSR11 = FALSE;
+   SiS_Pr->SiS_MyCR63 = 0x63;
+   if(HwInfo->jChipType >= SIS_661) {
+      SiS_Pr->SiS_SensibleSR11 = TRUE;
+      SiS_Pr->SiS_MyCR63 = 0x53;
+   }
+
    /* You should use the macros, not these flags directly */
 
    SiS_Pr->SiS_SysFlags = 0;
@@ -1338,6 +1322,10 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSI
 	 }
       }
    }
+   if(HwInfo->jChipType == SIS_760) {
+      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
+      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760UMA;
+   }
 }
 
 /*********************************************/
@@ -1410,18 +1398,19 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_
 
    SiS_Pr->SiS_ChrontelInit = 0;
 
+   /* Check for SiS30x first */
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+   if((temp == 1) || (temp == 2)) return;
+
    switch(HwInfo->jChipType) {
 #ifdef SIS300
    case SIS_540:
    case SIS_630:
    case SIS_730:
-        /* Check for SiS30x first */
-        temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-	if((temp == 1) || (temp == 2)) return;
       	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
-      	if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+      	if((temp >= 2) && (temp <= 5)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)   		SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
       	if((temp == 4) || (temp == 5)) {
 		/* Save power status (and error check) - UNUSED */
 		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
@@ -1436,8 +1425,8 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_
    case SIS_330:
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
-      	if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)  SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+      	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)  			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
         break;
    case SIS_661:
    case SIS_741:
@@ -1445,9 +1434,9 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_
    case SIS_760:
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       	temp = (temp & 0xe0) >> 5;
-      	if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)  SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-	if(temp == 4)  SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
+      	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)  			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+	if(temp == 4)  			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
         break;
 #endif
    default:
@@ -1475,44 +1464,72 @@ SiS_SetEnableFstn(SiS_Private *SiS_Pr, i
 /*        HELPER: Determine ROM usage        */
 /*********************************************/
 
+BOOLEAN
+SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT romversoffs, romvmaj = 1, romvmin = 0;
+
+   if(HwInfo->jChipType >= SIS_661) {
+      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
+      if(romversoffs) {
+	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
+	    romvmaj = ROMAddr[romversoffs] - '0';
+	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
+	 }
+      }
+      if((romvmaj != 0) || (romvmin >= 92)) {
+	 return TRUE;
+      }
+   } else if(IS_SIS650740) {
+      if((ROMAddr[0x1a] == 'N') &&
+         (ROMAddr[0x1b] == 'e') &&
+         (ROMAddr[0x1c] == 'w') &&
+         (ROMAddr[0x1d] == 'V')) {
+	 return TRUE;
+      }
+   }
+   return FALSE;
+}
+
 static void
 SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT romptr = 0;
+
+   SiS_Pr->SiS_UseROM = FALSE;
+   SiS_Pr->SiS_ROMNew = FALSE;
 
    if((ROMAddr) && (HwInfo->UseROM)) {
-      if((ROMAddr[0x00] != 0x55) || (ROMAddr[0x01] != 0xAA)) {
-         SiS_Pr->SiS_UseROM = FALSE;
-      } else if(HwInfo->jChipType == SIS_300) {
-        /* 300: We check if the code starts below 0x220 by
-	 * checking the jmp instruction at the beginning
-	 * of the BIOS image.
-	 */
-	 if((ROMAddr[3] == 0xe9) &&
-	    ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
+      if(HwInfo->jChipType == SIS_300) {
+         /* 300: We check if the code starts below 0x220 by
+	  * checking the jmp instruction at the beginning
+	  * of the BIOS image.
+	  */
+	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
 	    SiS_Pr->SiS_UseROM = TRUE;
-	 else
-	    SiS_Pr->SiS_UseROM = FALSE;
       } else if(HwInfo->jChipType < SIS_315H) {
-#if 0
-        /* Rest of 300 series: We don't use the ROM image if
-	 * the BIOS version < 2.0.0 as such old BIOSes don't
-	 * have the needed data at the expected locations.
-	 */
-         if(ROMAddr[0x06] < '2')  SiS_Pr->SiS_UseROM = FALSE;
-	 else                     SiS_Pr->SiS_UseROM = TRUE;
-#else
-	/* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
-	 * the others do as well
-	 */
+	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
+	  * the others do as well
+	  */
 	 SiS_Pr->SiS_UseROM = TRUE;
-#endif
       } else {
          /* 315/330 series stick to the standard */
 	 SiS_Pr->SiS_UseROM = TRUE;
+	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
+	    /* Find out about LCD data table entry size */
+	    if((romptr = SISGETROMW(0x0102))) {
+	       if(ROMAddr[romptr + (32 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 32;
+	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 34;
+	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 36;
+	    }
+	 }
       }
-   } else SiS_Pr->SiS_UseROM = FALSE;
-
+   }
 }
 
 /*********************************************/
@@ -1597,7 +1614,8 @@ SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_
 
   SiS_Pr->SiS_VBType = 0;
 
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) return;
+  if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+     return;
 
   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
 
@@ -1608,7 +1626,6 @@ SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_
   if(flag >= 2) {
      SiS_Pr->SiS_VBType = VB_SIS302B;
   } else if(flag == 1) {
-     SiS_Pr->SiS_VBType = VB_SIS301;
      if(rev >= 0xC0) {
        	SiS_Pr->SiS_VBType = VB_SIS301C;
      } else if(rev >= 0xB0) {
@@ -1616,20 +1633,17 @@ SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_
 	/* Check if 30xB DH version (no LCD support, use Panel Link instead) */
     	nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
         if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+     } else {
+        SiS_Pr->SiS_VBType = VB_SIS301;
      }
   }
   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
-     if(rev >= 0xD0) {
-	SiS_Pr->SiS_VBType &= ~(VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_NoLCD);
-	if(rev >= 0xE0) {
-	   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
-	   if(flag == 0xff)
-	      SiS_Pr->SiS_VBType |= VB_SIS302LV;
-	   else
-	      SiS_Pr->SiS_VBType |= VB_SIS302ELV;
-	} else {
-	   SiS_Pr->SiS_VBType |= VB_SIS301LV;
-	}
+     if(rev >= 0xE0) {
+	flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
+	if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
+	else 	 	 SiS_Pr->SiS_VBType = VB_SIS302ELV;
+     } else if(rev >= 0xD0) {
+	SiS_Pr->SiS_VBType = VB_SIS301LV;
      }
   }
 }
@@ -1685,12 +1699,24 @@ GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW
 
   case SIS_661:
   case SIS_741:
-  case SIS_660:
-  case SIS_760:
         counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
 	AdapterMemorySize = 1 << counter;
       	AdapterMemorySize *= (1024*1024);
         break;
+
+  case SIS_660:
+  case SIS_760:
+        counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
+	if(counter) {
+	   AdapterMemorySize = 1 << counter;
+      	   AdapterMemorySize *= (1024*1024);
+	}
+	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x78) & 0x30;
+	if(counter) {
+	   if(counter == 0x10) AdapterMemorySize += (32 * 1024 * 1024);
+	   else		       AdapterMemorySize += (64 * 1024 * 1024);
+	}
+	break;
 #endif
 
 #ifdef SIS300
@@ -1758,7 +1784,10 @@ SiS_Get310DRAMType(SiS_Private *SiS_Pr, 
    if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
      data = *SiS_Pr->pSiS_SoftSetting & 0x03;
    } else {
-     if(HwInfo->jChipType >= SIS_661) {
+     if(HwInfo->jChipType >= SIS_660) {
+        /* data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; */
+	data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+     } else if(HwInfo->jChipType >= SIS_661) {
         data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
      } else if(IS_SIS550650740) {
         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
@@ -1932,6 +1961,43 @@ SiS_SetLowModeTest(SiS_Private *SiS_Pr, 
 }
 
 /*********************************************/
+/*            HELPER: ENABLE CRT1            */
+/*********************************************/
+
+static void
+SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+      if(IS_SIS650) {
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+	 if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+      } else if(IS_SIS661741660760) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+	 if(!SiS_Pr->SiS_ROMNew) {
+	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+	 }
+      }
+   }
+}
+
+static void
+SiS_HandleCRT1(SiS_Private *SiS_Pr)
+{
+  SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+#if 0
+  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+     }
+  }
+#endif
+}
+
+/*********************************************/
 /*           HELPER: GetColorDepth           */
 /*********************************************/
 
@@ -1965,28 +2031,22 @@ USHORT
 SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
               USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
 {
-  USHORT temp,colordepth,infoflag;
+  USHORT xres, temp, colordepth, infoflag;
 
   if(SiS_Pr->UseCustomMode) {
      infoflag = SiS_Pr->CInfoFlag;
-     temp = SiS_Pr->CHDisplay / 16;
+     xres = SiS_Pr->CHDisplay;
   } else {
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-     temp = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeOffset;
-     temp = SiS_Pr->SiS_ScreenOffset[temp];
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex);
 
+  temp = xres / 16;
   if(infoflag & InterlaceMode) temp <<= 1;
-
   temp *= colordepth;
-
-  if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) ||
-        ModeNo == 0x3f ||
-	ModeNo == 0x42 ||
-	ModeNo == 0x45 ) ||
-      (SiS_Pr->UseCustomMode && (SiS_Pr->CHDisplay % 16)) ) {
+  if(xres % 16) {
      colordepth >>= 1;
      temp += colordepth;
   }
@@ -2091,9 +2151,15 @@ SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSI
      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);                     /* Set CRTC(3d4) */
   }
-  if( ( (HwInfo->jChipType == SIS_630) ||
-        (HwInfo->jChipType == SIS_730) )  &&
-      (HwInfo->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
+  if(HwInfo->jChipType >= SIS_661) {
+     SiS_SetupCR5x(SiS_Pr, HwInfo);
+     for(i = 0x13; i <= 0x14; i++) {
+        CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+        SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+     }
+  } else if( ( (HwInfo->jChipType == SIS_630) ||
+               (HwInfo->jChipType == SIS_730) )  &&
+             (HwInfo->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
            SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
@@ -2194,7 +2260,7 @@ SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHO
 /*********************************************/
 
 static void
-SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 {
   USHORT i;
 
@@ -2204,6 +2270,11 @@ SiS_ClearExt1Regs(SiS_Private *SiS_Pr, P
 
   if(HwInfo->jChipType >= SIS_315H) {
      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+     if(ModeNo <= 0x13) {
+        if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+	}
+     }
   }
 }
 
@@ -2267,45 +2338,6 @@ SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USH
 /*                  CRTC/2                   */
 /*********************************************/
 
-#ifdef SIS315H
-static void
-SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-		   USHORT RefreshRateTableIndex, USHORT *ResIndex,
-		   USHORT *DisplayType)
- {
-  USHORT modeflag = 0;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     *ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     *ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  *ResIndex &= 0x3F;
-
-  *DisplayType = SiS_Pr->SiS_LCDResInfo;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 32;
-  if(modeflag & HalfDCLK)                 *DisplayType += 16;
-
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        *DisplayType = 100;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2;
-        if(modeflag & HalfDCLK)                 *DisplayType += 1;
-     }
-  } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        *DisplayType = 104;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2;
-        if(modeflag & HalfDCLK)                 *DisplayType += 1;
-     }
-  }
-
-}
-#endif
-
 static void
 SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 USHORT RefreshRateTableIndex,
@@ -2313,10 +2345,6 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USH
 {
   UCHAR  index;
   USHORT temp,i,j,modeflag;
-#ifdef SIS315H
-  USHORT ResIndex,DisplayType;
-  const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL;
-#endif
 
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);		/* unlock cr0-7 */
 
@@ -2324,7 +2352,7 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USH
 
      modeflag = SiS_Pr->CModeFlag;
 
-     for(i=0,j=0;i<=07;i++,j++) {
+     for(i=0,j=0;i<=7;i++,j++) {
         SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
      }
      for(j=0x10;i<=10;i++,j++) {
@@ -2342,7 +2370,7 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USH
 
      temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
      if(modeflag & DoubleScanMode) temp |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
 
   } else {
 
@@ -2352,87 +2380,28 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USH
         modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      }
 
-     if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-
-#ifdef SIS315H
-
-        SiS_GetLCDACRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, &ResIndex, &DisplayType);
-
-        switch(DisplayType) {
-        case Panel_1024x768      : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
-        case Panel_1280x1024     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1;    break;
-        case Panel_1400x1050     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1;    break;
-        case Panel_1600x1200     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1;    break;
-        case Panel_1024x768  + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1_H;   break;
-        case Panel_1280x1024 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1_H;  break;
-        case Panel_1400x1050 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1_H;  break;
-        case Panel_1600x1200 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1_H;  break;
-        case Panel_1024x768  + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2;     break;
-        case Panel_1280x1024 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2;    break;
-        case Panel_1400x1050 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2;    break;
-        case Panel_1600x1200 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2;    break;
-        case Panel_1024x768  + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2_H;   break;
-        case Panel_1280x1024 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H;  break;
-        case Panel_1400x1050 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2_H;  break;
-        case Panel_1600x1200 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2_H;  break;
-        case 100:	  	   LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1;         break;
-        case 101:		   LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1_H;       break;
-        case 102:		   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2;    break;
-        case 103:		   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H;  break;
-        case 104:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1;           break;
-        case 105:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1_H;         break;
-        case 106:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2;           break;
-        case 107:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2_H;         break;
-        default:                   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
-        }
-
-        for(i=0, j=0; i<=0x07; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x10, j=8; i<=0x12; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x15, j=11; i<=0x16; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x0A, j=13; i<=0x0C; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
+     index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 
-        temp = (LCDACRT1Ptr+ResIndex)->CR[16] & 0xE0;
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
-        temp = ((LCDACRT1Ptr+ResIndex)->CR[16] & 0x01) << 5;
-        if(modeflag & DoubleScanMode) temp |= 0x80;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
-
-#endif
-
-     } else {
-
-        index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
-        for(i=0,j=0;i<=07;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x10;i<=10;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x15;i<=12;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x0A;i<=15;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
+     for(i=0,j=0;i<=7;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x10;i<=10;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x15;i<=12;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x0A;i<=15;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
 
-        temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
+     temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+     SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
 
-        temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
-        if(modeflag & DoubleScanMode)  temp |= 0x80;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
+     temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+     if(modeflag & DoubleScanMode)  temp |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
 
-     }
   }
 
   if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
@@ -2470,7 +2439,7 @@ SiS_SetCRT1Offset(SiS_Private *SiS_Pr, U
 
    DisplayUnit <<= 5;
    temp = (DisplayUnit & 0xff00) >> 8;
-   if (DisplayUnit & 0xff) temp++;
+   if(DisplayUnit & 0xff) temp++;
    temp++;
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
 }
@@ -2905,7 +2874,8 @@ SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr,
 {
   USHORT modeflag;
 
-  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);  /* disable auto-threshold */
+  /* disable auto-threshold */
+  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
@@ -2913,30 +2883,19 @@ SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr,
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if(HwInfo->jChipType >= SIS_661) {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-     if(ModeNo > 0x13) {
+  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+  if(ModeNo > 0x13) {
+     if(HwInfo->jChipType >= SIS_661) {
         if(!(modeflag & HalfDCLK)) {
 	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-	   if(ModeNo != 0x38) {
-	      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-	   }
+	   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
 	}
-     }
-  } else {
-     if(ModeNo > 0x13) {
-        if( (!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+     } else {
+        if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-        } else {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-        }
-     } else {
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+	}
      }
   }
 }
@@ -2951,33 +2910,29 @@ SiS_SetVCLKState(SiS_Private *SiS_Pr, PS
                  USHORT ModeNo, USHORT RefreshRateTableIndex,
                  USHORT ModeIdIndex)
 {
-  USHORT data, data2=0;
-  USHORT VCLK, index=0;
+  USHORT data=0, VCLK=0, index=0;
 
-  if(ModeNo <= 0x13) VCLK = 0;
-  else {
+  if(ModeNo > 0x13) {
      if(SiS_Pr->UseCustomMode) {
         VCLK = SiS_Pr->CSRClock;
      } else {
         index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
-	               RefreshRateTableIndex,HwInfo);
+	                      RefreshRateTableIndex,HwInfo);
         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
      }
   }
 
-  if(HwInfo->jChipType < SIS_315H) {		/* 300 series */
+  if(HwInfo->jChipType < SIS_315H) {
 
-     data2 = 0x00;
-     if(VCLK > 150) data2 |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data2);
+     if(VCLK > 150) data |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
 
-     data2 = 0x00;
-     if(VCLK >= 150) data2 |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2);
+     data = 0x00;
+     if(VCLK >= 150) data |= 0x08;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
 
-  } else { 					/* 315 series */
+  } else {
 
-     data = 0;
      if(VCLK >= 166) data |= 0x0c;
      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
 
@@ -2986,23 +2941,31 @@ SiS_SetVCLKState(SiS_Private *SiS_Pr, PS
      }
   }
 
-  data2 = 0x03;
-  if((VCLK >= 135) && (VCLK < 160))      data2 = 0x02;
-  else if((VCLK >= 160) && (VCLK < 260)) data2 = 0x01;
-  else if(VCLK >= 260)                   data2 = 0x00;
+  /* DAC speed */
+  if(HwInfo->jChipType >= SIS_661) {
 
-  if(HwInfo->jChipType == SIS_540) {
-     if((VCLK == 203) || (VCLK < 234)) data2 = 0x02;
-  }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
 
-  if(HwInfo->jChipType < SIS_315H) {
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data2);  	/* DAC speed */
   } else {
-     if(HwInfo->jChipType > SIS_315PRO) {
-        /* This "if" is done in 330 and 650/LVDS/301LV BIOSes; Not in 315 BIOS */
-        if(ModeNo > 0x13) data2 &= 0xfc;
+
+     data = 0x03;
+     if((VCLK >= 135) && (VCLK < 160))      data = 0x02;
+     else if((VCLK >= 160) && (VCLK < 260)) data = 0x01;
+     else if(VCLK >= 260)                   data = 0x00;
+
+     if(HwInfo->jChipType == SIS_540) {
+        if((VCLK == 203) || (VCLK < 234))   data = 0x02;
+     }
+
+     if(HwInfo->jChipType < SIS_315H) {
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+     } else {
+        if(HwInfo->jChipType > SIS_315PRO) {
+           if(ModeNo > 0x13) data &= 0xfc;
+        }
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
      }
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data2);  	/* DAC speed */
+
   }
 }
 
@@ -3010,75 +2973,51 @@ static void
 SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
                     USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex)
 {
-  USHORT data,data2;
-  USHORT infoflag=0,modeflag;
+  USHORT data,infoflag=0,modeflag;
   USHORT resindex,xres;
 #ifdef SIS315H
-  USHORT data3;
+  USHORT data2,data3;
   ULONG  longdata;
-#if 0
-  resinfo = 0;
-#endif
+  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
 #endif
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
      infoflag = SiS_Pr->CInfoFlag;
+     xres = SiS_Pr->CHDisplay;
   } else {
+     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
      if(ModeNo > 0x13) {
     	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
     	infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-#ifdef SIS315H
-#if 0
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#endif
-#endif
+	xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
      } else {
     	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+	xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
      }
   }
 
   /* Disable DPMS */
   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
 
-  if(ModeNo > 0x13) data = infoflag;
-  else data = 0;
-
-  data2 = 0;
+  data = 0;
   if(ModeNo > 0x13) {
      if(SiS_Pr->SiS_ModeType > 0x02) {
-        data2 |= 0x02;
-        data2 |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
-     }
-  }
-
-#ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n",
-  	data, HwInfo->jChipType);
-#endif
-
-  if(data & InterlaceMode) data2 |= 0x20;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data2);
-
-  if(SiS_Pr->UseCustomMode) {
-     xres = SiS_Pr->CHDisplay;
-  } else {
-     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
-     if(ModeNo <= 0x13) {
-      	xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
-     } else {
-      	xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+        data |= 0x02;
+        data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
      }
+     if(infoflag & InterlaceMode) data |= 0x20;
   }
+  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
 
   if(HwInfo->jChipType != SIS_300) {
-     data = 0x0000;
+     data = 0;
      if(infoflag & InterlaceMode) {
-        if(xres <= 800) data = 0x0020;
+        if(xres <= 800)       data = 0x0020;
         else if(xres <= 1024) data = 0x0035;
-        else data = 0x0048;
+        else                  data = 0x0048;
      }
-     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0x00FF));
+     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF));
      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8));
   }
 
@@ -3086,18 +3025,12 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
   }
 
+  data = 0;
+  if(modeflag & LineCompareOff) data = 0x08;
   if(HwInfo->jChipType == SIS_300) {
-     if(modeflag & LineCompareOff) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x08);
-     } else {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xF7);
-     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
   } else {
-     if(modeflag & LineCompareOff) {
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08);
-     } else {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7);
-     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(ModeNo > 0x13) {
   	   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40);
@@ -3105,9 +3038,13 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
      }
   }
 
+  if(HwInfo->jChipType >= SIS_661) {
+     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+  }
+
 #ifdef SIS315H
-  /* 315 BIOS sets SR17 at this point */
   if(HwInfo->jChipType == SIS_315PRO) {
+
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
      data = SiS_Pr->SiS_SR15[2][data];
      if(SiS_Pr->SiS_ModeType == ModeText) {
@@ -3126,12 +3063,18 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
 	}
      }
      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-  }
 
-  /* 330 BIOS sets SR17 at this point */
-  if(HwInfo->jChipType == SIS_330) {
+  } else if( (HwInfo->jChipType == SIS_330) ||
+             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760UMA))) {
+
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
-     data = SiS_Pr->SiS_SR15[2][data];
+     if(HwInfo->jChipType == SIS_330) {
+        data = SiS_Pr->SiS_SR15[2][data];
+     } else {
+        if(SiS_Pr->SiS_ROMNew) 	    data = ROMAddr[0xf6];
+        else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+	else                        data = 0xba;
+     }
      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
         data &= 0xc7;
      } else {
@@ -3144,31 +3087,38 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
 	}
 
 	data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
-	if(!data3) data3++;
-
-	data2 *= data3;
+	if(data3) data2 *= data3;
 
 	longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024;
 
 	data2 = longdata / data2;
 
-	if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
-           if(data2 >= 0x19c)      data = 0xba;
-	   else if(data2 >= 0x140) data = 0x7a;
-	   else if(data2 >= 0x101) data = 0x3a;
-	   else if(data2 >= 0xf5)  data = 0x32;
-	   else if(data2 >= 0xe2)  data = 0x2a;
-	   else if(data2 >= 0xc4)  data = 0x22;
-	   else if(data2 >= 0xac)  data = 0x1a;
-	   else if(data2 >= 0x9e)  data = 0x12;
-	   else if(data2 >= 0x8e)  data = 0x0a;
+	if(HwInfo->jChipType == SIS_330) {
+	   if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+              if     (data2 >= 0x19c) data = 0xba;
+	      else if(data2 >= 0x140) data = 0x7a;
+	      else if(data2 >= 0x101) data = 0x3a;
+	      else if(data2 >= 0xf5)  data = 0x32;
+	      else if(data2 >= 0xe2)  data = 0x2a;
+	      else if(data2 >= 0xc4)  data = 0x22;
+	      else if(data2 >= 0xac)  data = 0x1a;
+	      else if(data2 >= 0x9e)  data = 0x12;
+	      else if(data2 >= 0x8e)  data = 0x0a;
+	      else                    data = 0x02;
+	   } else {
+	      if(data2 >= 0x127)      data = 0xba;
+	      else                    data = 0x7a;
+	   }
+	} else {
+	   if     (data2 >= 0x190) data = 0xba;
+	   else if(data2 >= 0xff)  data = 0x7a;
+	   else if(data2 >= 0xd3)  data = 0x3a;
+	   else if(data2 >= 0xa9)  data = 0x1a;
+	   else if(data2 >= 0x93)  data = 0x0a;
 	   else                    data = 0x02;
-	 } else {
-	   if(data2 >= 0x127)      data = 0xba;
-	   else                    data = 0x7a;
-	 }
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
   }
 #endif
 
@@ -3190,46 +3140,6 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
      } else {
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
      }
-#if 0   /* What is SR0E[D5:6]? */
-     if(HwInfo->jChipType >= SIS_661) {
-        data = 0;
-        if((ModeNo == 6) || ((ModeNo >= 0x0e) && (ModeNo <= 0x13))) {
-	   data |= 0x20;
-	}
-	if(SiS_Pr->SiS_ModeType != ModeVGA) {
-	   if(SiS_Pr->UseCustomMode) {
-              if((xres >= 640) && (SiS_Pr->CVDisplay >= 480)) {
-	         data |= 0x40;
-	      }
-	      if((xres > 1280) && (SiS_Pr->CVDisplay > 1024)) {
-	         data |= 0x60;
-	      }
-	   }
-	} else if(ModeNo > 0x13) {   /* These are in the CRT1 table, and set by CRT1CRTC */
-	   if(resinfo >= SIS_RI_640x480) {
-	      if(resinfo <= SIS_RI_2048x1536) {
-	         data |= 0x40;
-		 if(resinfo > SIS_RI_1280x1024) {
-		    data |= 0x60;
-		    if(resinfo != SIS_RI_1600x1200) {
-		       data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x0e);
-		       data += 0x60;
-		       SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e);
-		       data = 0;
-		    }
-		 }
-	      }
-	      if(resinfo == SIS_RI_1152x864) {
-		 data = 0x40;
-	      }
-	      if(resinfo == SIS_RI_1400x1050) { /* TW */
-		 data = 0x60;
-	      }
-	   }
-	}
-	SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0e,data);
-     }
-#endif
   }
 #endif
 }
@@ -3404,7 +3314,7 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, PS
   SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex);
   SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo);
   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
-  SiS_ClearExt1Regs(SiS_Pr,HwInfo);
+  SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo);
   SiS_ResetCRT1VCLK(SiS_Pr, HwInfo);
 
   SiS_Pr->SiS_SelectCRT2Rate = 0;
@@ -3469,22 +3379,31 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, PS
   }
 }
 
+
+
 /*********************************************/
-/*            HELPER: ENABLE CRT1            */
+/*         HELPER: RESET VIDEO BRIDGE        */
 /*********************************************/
 
 static void
-SiS_HandleCRT1(SiS_Private *SiS_Pr)
+SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf);
-#if 0
-  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
-     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
-        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40);
-     }
-  }
-#endif
+   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT temp;
+
+   if(SiS_Pr->SiS_UseROM) {
+      if(HwInfo->jChipType < SIS_330) {
+         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      } else if(HwInfo->jChipType >= SIS_661) {
+         temp = ROMAddr[0x7e];
+         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80];
+         if(HwInfo->jChipType >= SIS_660)                  temp |= 0x40;
+         else if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      }
+   }
 }
 
 /*********************************************/
@@ -3573,13 +3492,12 @@ BOOLEAN
 SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
 #endif
 {
-   ULONG   temp;
    USHORT  ModeIdIndex;
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
    SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
-   unsigned char backupreg=0, tempr1, tempr2;
+   unsigned char backupreg=0;
 #ifndef LINUX_XF86
    USHORT  KeepLockReg;
+   ULONG   temp;
 
    SiS_Pr->UseCustomMode = FALSE;
    SiS_Pr->CRT1UsesCustomMode = FALSE;
@@ -3590,37 +3508,26 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
    }
 
    SiSInitPtr(SiS_Pr, HwInfo);
-
    SiSRegInit(SiS_Pr, BaseAddr);
-
    SiS_GetSysFlags(SiS_Pr, HwInfo);
 
-#ifdef LINUX_XF86
+#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
    else
 #endif
          SiS_Pr->SiS_VGAINFO = 0x11;
 
    SiSInitPCIetc(SiS_Pr, HwInfo);
-
    SiSSetLVDSetc(SiS_Pr, HwInfo);
-
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
-   if(!SiS_Pr->UseCustomMode) {
-      ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f);
-   }
+   SiS_Pr->SiS_flag_clearbuffer = 0;
 
-#ifdef LINUX_XF86
-   /* We never clear the buffer in X */
-   ModeNo |= 0x8000;
+   if(!SiS_Pr->UseCustomMode) {
+#ifndef LINUX_XF86
+      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
 #endif
-
-   if(ModeNo & 0x8000) {
-     	ModeNo &= 0x7fff;
-     	SiS_Pr->SiS_flag_clearbuffer = 0;
-   } else {
-     	SiS_Pr->SiS_flag_clearbuffer = 1;
+      ModeNo &= 0x7f;
    }
 
 #ifndef LINUX_XF86
@@ -3642,23 +3549,9 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         SiS_UnLockCRT2(SiS_Pr,HwInfo);
-	 if(ROMAddr && SiS_Pr->SiS_UseROM) {
-	    if(HwInfo->jChipType < SIS_330) {
-               temp = ROMAddr[VB310Data_1_2_Offset];
-	       temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-            }
-	    if(HwInfo->jChipType > SIS_330) {
-	       temp = ROMAddr[0x7e];
-	       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-	    }
-	 }
+         SiS_ResetVB(SiS_Pr, HwInfo);
 	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-
 	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3679,27 +3572,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
 #endif
 
    if(HwInfo->jChipType >= SIS_315H) {
-#if 0
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-            SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         }
-      }
-#endif
-
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(IS_SIS650) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	 } else if(IS_SIS661741660760) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-	 }
-      }
+      SiS_SetupCR5x(SiS_Pr, HwInfo);
    }
 
    if(SiS_Pr->UseCustomMode) {
@@ -3743,7 +3616,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         if(HwInfo->jChipType < SIS_661) {
+         if(!SiS_Pr->SiS_ROMNew) {
 	    if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
 	    } else {
@@ -3753,14 +3626,6 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
 
 	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
 
-	 tempr1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	 tempr2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00);
-	 if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7;
-	 else			      tempr2 |= 0x08;
-	 if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB;
-	 else			      tempr2 |= 0x04;
-	 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,tempr2);
-
 	 if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
 	    if((ModeNo == 0x03) || (ModeNo == 0x10)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
@@ -3768,7 +3633,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
             }
 	 }
 
-	 if(tempr1 & SetCRT2ToLCD) {
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
 	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	 }
       } else if((HwInfo->jChipType == SIS_630) ||
@@ -3840,12 +3705,10 @@ BOOLEAN
 SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
                DisplayModePtr mode, BOOLEAN IsCustom)
 {
-   ULONG   temp;
    USHORT  ModeIdIndex;
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
    SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
    UShort  ModeNo   = 0;
-   unsigned char tempr1, tempr2, backupreg=0;
+   unsigned char backupreg=0;
    SISPtr  pSiS     = SISPTR(pScrn);
 #ifdef SISDUALHEAD
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
@@ -3877,17 +3740,15 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, 
    }
 
    SiSRegInit(SiS_Pr, BaseAddr);
-
    SiSInitPtr(SiS_Pr, HwInfo);
-
    SiS_GetSysFlags(SiS_Pr, HwInfo);
-
+#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-
+#else
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#endif
    SiSInitPCIetc(SiS_Pr, HwInfo);
-
    SiSSetLVDSetc(SiS_Pr, HwInfo);
-
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
    /* Save mode info so we can set it from within SetMode for CRT1 */
@@ -3947,23 +3808,9 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, 
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         SiS_UnLockCRT2(SiS_Pr,HwInfo);
-         if(ROMAddr && SiS_Pr->SiS_UseROM) {
-	    if(HwInfo->jChipType < SIS_330) {
-               temp = ROMAddr[VB310Data_1_2_Offset];
-	       temp |= 0x40;
-               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-            }
-	    if(HwInfo->jChipType > SIS_330) {
-	       temp = ROMAddr[0x7e];
-	       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-	    }
-	 }
+	 SiS_ResetVB(SiS_Pr, HwInfo);
 	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-
 	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -4005,7 +3852,7 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, 
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         if(HwInfo->jChipType < SIS_661) {
+         if(!SiS_Pr->SiS_ROMNew) {
 	    if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
 	    } else {
@@ -4015,15 +3862,7 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, 
 
 	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
 
-	 tempr1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	 tempr2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00);
-	 if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7;
-	 else			      tempr2 |= 0x08;
-	 if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB;
-	 else			      tempr2 |= 0x04;
-	 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,tempr2);
-
-	 if(tempr1 & SetCRT2ToLCD) {
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
 	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	 }
       } else if((HwInfo->jChipType == SIS_630) ||
@@ -4081,17 +3920,15 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, 
    }
 
    SiSInitPtr(SiS_Pr, HwInfo);
-
    SiSRegInit(SiS_Pr, BaseAddr);
-
    SiS_GetSysFlags(SiS_Pr, HwInfo);
-
+#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-
+#else
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#endif
    SiSInitPCIetc(SiS_Pr, HwInfo);
-
    SiSSetLVDSetc(SiS_Pr, HwInfo);
-
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
    /* We don't clear the buffer under X */
@@ -4127,27 +3964,7 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, 
    SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
 
    if(HwInfo->jChipType >= SIS_315H) {
-#if 0
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-            SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         }
-      }
-#endif
-
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(IS_SIS650) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	 } else if(IS_SIS661741660760) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-	 }
-      }
+      SiS_SetupCR5x(SiS_Pr, HwInfo);
    }
 
    /* Set mode on CRT1 */
@@ -4316,12 +4133,188 @@ SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS
 }
 #endif
 
+#ifndef GETBITSTR
+#define BITMASK(h,l)    	(((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
+#define GENMASK(mask)   	BITMASK(1?mask,0?mask)
+#define GETBITS(var,mask)   	(((var) & GENMASK(mask)) >> (0?mask))
+#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
+#endif
+
+static void
+SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
+{
+   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */
+   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */
+   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */
+   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */
+   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */
+   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */
+       			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+
+   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal - 2) & 0xFF;			/* CR6 */
+   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal - 2) & 0x100) >> 8)		/* CR7 */
+ 	 		  | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
+	 		  | ((SiS_Pr->CVSyncStart & 0x100) >> 6)
+	 	  	  | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
+			  | 0x10
+	 		  | (((SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
+	 		  | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
+	 		  | ((SiS_Pr->CVSyncStart & 0x200) >> 2);
+
+   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */
+
+   if(depth != 8) {
+      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */
+      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
+   }
+
+#if 0
+   if (mode->VScan >= 32)
+	regp->CRTC[9] |= 0x1F;
+   else if (mode->VScan > 1)
+	regp->CRTC[9] |= mode->VScan - 1;
+#endif
+
+   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart     ) & 0xFF;			/* CR10 */
+   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;		/* CR11 */
+   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */
+   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */
+   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */
+
+   SiS_Pr->CCRT1CRTC[13] =							/* SRA */
+                        GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
+                        GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
+                        GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+                        GETBITSTR((SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
+                        GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
+                        GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
+
+   SiS_Pr->CCRT1CRTC[14] =							/* SRB */
+                        GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
+                        GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
+                        GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+                        GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
+
+
+   SiS_Pr->CCRT1CRTC[15] =							/* SRC */
+                        GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+                        GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+}
+
+void
+SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+{
+   USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE;
+   int i,j;
+
+   /* 1:1 data: use data set by setcrt1crtc() */
+   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+   if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+   } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   if(modeflag & HalfDCLK) VGAHDE >>= 1;
+
+   SiS_Pr->CHDisplay = VGAHDE;
+   SiS_Pr->CHBlankStart = VGAHDE;
+
+   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
+   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
+
+   tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+   tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelXRes;
+   }
+   tempbx += tempax;
+   if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
+
+   tempax = VGAHDE;
+   tempbx = SiS_Pr->CHTotal;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempbx = SiS_Pr->PanelXRes;
+      if(modeflag & HalfDCLK) tempbx >>= 1;
+      tempax += ((tempbx - tempax) >> 1);
+   }
+
+   tempax += SiS_Pr->PanelHRS;
+   SiS_Pr->CHSyncStart = tempax;
+   tempax += SiS_Pr->PanelHRE;
+   SiS_Pr->CHSyncEnd = tempax;
+
+   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelYRes;
+   }
+   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
+
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
+   }
+   tempax += SiS_Pr->PanelVRS;
+   SiS_Pr->CVSyncStart = tempax;
+   tempax += SiS_Pr->PanelVRE;
+   SiS_Pr->CVSyncEnd = tempax;
+
+   SiS_CalcCRRegisters(SiS_Pr, 8);
+   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
+
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i=0,j=0;i<=7;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x10;i<=10;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x15;i<=12;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x0A;i<=15;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+
+   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
+
+   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+   if(modeflag & DoubleScanMode) tempax |= 0x80;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
+
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
+       	SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+	SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
+	SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
+
+   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+   	SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+	SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
+	SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
+	SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+   	SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+	SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
+	SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
+	SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
+#endif
+}
 
 /* ================ XFREE86 ================= */
 
 /* Helper functions */
 
 #ifdef LINUX_XF86
+
 USHORT
 SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags)
 {
@@ -4402,73 +4395,16 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
 
    pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
 
-   pSiS->SiS_Pr->CCRT1CRTC[0]  =  ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff;
-   pSiS->SiS_Pr->CCRT1CRTC[1]  =  (pSiS->SiS_Pr->CHDisplay >> 3) - 1;
-   pSiS->SiS_Pr->CCRT1CRTC[2]  =  (pSiS->SiS_Pr->CHBlankStart >> 3) - 1;
-   pSiS->SiS_Pr->CCRT1CRTC[3]  =  (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
-   pSiS->SiS_Pr->CCRT1CRTC[4]  =  (pSiS->SiS_Pr->CHSyncStart >> 3) + 3;
-   pSiS->SiS_Pr->CCRT1CRTC[5]  =  ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |
-       				  (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
-
-   pSiS->SiS_Pr->CCRT1CRTC[6]  =  (pSiS->SiS_Pr->CVTotal - 2) & 0xFF;
-   pSiS->SiS_Pr->CCRT1CRTC[7]  =  (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8)
- 	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
-	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x100) >> 6)
-	 			| (((pSiS->SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
-	 			| 0x10
-	 			| (((pSiS->SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
-	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
-	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2);
-
-   pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* cr9 */
-
-#if 0
-   if (mode->VScan >= 32)
-	regp->CRTC[9] |= 0x1F;
-   else if (mode->VScan > 1)
-	regp->CRTC[9] |= mode->VScan - 1;
-#endif
-
-   pSiS->SiS_Pr->CCRT1CRTC[8] =  (pSiS->SiS_Pr->CVSyncStart     ) & 0xFF;		/* cr10 */
-   pSiS->SiS_Pr->CCRT1CRTC[9] =  ((pSiS->SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;	/* cr11 */
-   pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay    - 1) & 0xFF;		/* cr12 */
-   pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF;		/* cr15 */
-   pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd   - 1) & 0xFF;		/* cr16 */
-
-   pSiS->SiS_Pr->CCRT1CRTC[13] =
-                        GETBITSTR((pSiS->SiS_Pr->CVTotal     -2), 10:10, 0:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
-                        GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
-                        GETBITSTR((pSiS->SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
-
-   pSiS->SiS_Pr->CCRT1CRTC[14] =
-                        GETBITSTR((pSiS->SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
-                        GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
-
-
-   pSiS->SiS_Pr->CCRT1CRTC[15] =
-                        GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+   SiS_CalcCRRegisters(pSiS->SiS_Pr, depth);
 
    switch(depth) {
-   case 8:
-      	pSiS->SiS_Pr->CModeFlag |= 0x223b;
-	break;
-   case 16:
-      	pSiS->SiS_Pr->CModeFlag |= 0x227d;
-	break;
-   case 32:
-      	pSiS->SiS_Pr->CModeFlag |= 0x22ff;
-	break;		
-   default: 
-   	return 0;	
-   }	
-   
-   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) 
+   case 8:  pSiS->SiS_Pr->CModeFlag |= 0x223b; break;
+   case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break;
+   case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break;
+   default: return 0;
+   }
+
+   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN)
       pSiS->SiS_Pr->CModeFlag |= DoubleScanMode;
 
    if((pSiS->SiS_Pr->CVDisplay >= 1024)	||
@@ -4492,33 +4428,23 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
 
    pSiS->SiS_Pr->UseCustomMode = TRUE;
 #ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n", 
+   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n",
    	pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay);
    xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n",
    	pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag);
    xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-   	pSiS->SiS_Pr->CCRT1CRTC[0],
-	pSiS->SiS_Pr->CCRT1CRTC[1],
-	pSiS->SiS_Pr->CCRT1CRTC[2],
-	pSiS->SiS_Pr->CCRT1CRTC[3],
-	pSiS->SiS_Pr->CCRT1CRTC[4],
-	pSiS->SiS_Pr->CCRT1CRTC[5],
-	pSiS->SiS_Pr->CCRT1CRTC[6],
-	pSiS->SiS_Pr->CCRT1CRTC[7]);
+   	pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1],
+	pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3],
+	pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5],
+	pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]);
    xf86DrvMsg(0, X_INFO, "  0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-   	pSiS->SiS_Pr->CCRT1CRTC[8],
-	pSiS->SiS_Pr->CCRT1CRTC[9],
-	pSiS->SiS_Pr->CCRT1CRTC[10],
-	pSiS->SiS_Pr->CCRT1CRTC[11],
-	pSiS->SiS_Pr->CCRT1CRTC[12],
-	pSiS->SiS_Pr->CCRT1CRTC[13],
-	pSiS->SiS_Pr->CCRT1CRTC[14],
-	pSiS->SiS_Pr->CCRT1CRTC[15]);
+   	pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9],
+	pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11],
+	pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13],
+	pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]);
    xf86DrvMsg(0, X_INFO, "  0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]);
    xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n",
-   	pSiS->SiS_Pr->CSR2B,
-	pSiS->SiS_Pr->CSR2C,
-	pSiS->SiS_Pr->CSRClock);
+   	pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock);
 #endif
    return 1;
 }
@@ -4635,7 +4561,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
       /* Horizontal display enable end */
       HDE = (cr_data & 0xff) |
             ((unsigned short) (sr_data & 0x0C) << 6);
-      E = HDE + 1;
+      E = HDE + 1;  /* 0x80 0x64 */
 
       cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4];
 	/* inSISIDXREG(SISCR, 0x04, cr_data); */
@@ -4643,7 +4569,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
       /* Horizontal retrace (=sync) start */
       HRS = (cr_data & 0xff) |
             ((unsigned short) (sr_data & 0xC0) << 2);
-      F = HRS - E - 3;
+      F = HRS - E - 3;  /* 0x06 0x06 */
 
       cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2];
 	/* inSISIDXREG(SISCR, 0x02, cr_data); */
@@ -4673,7 +4599,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
       B = (temp > 0) ? temp : (temp + 256);
 
       temp = HRE - ((E + F + 3) & 63);
-      C = (temp > 0) ? temp : (temp + 64);
+      C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */
 
       D = B - F - C;
 
@@ -5205,7 +5131,7 @@ sisfb_mode_rate_to_ddata(SiS_Private *Si
        return 0;
 #endif
     }
-    
+
     if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
 
     RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/init.h linux-2.4.26-pre6/drivers/video/sis/init.h
--- linux-2.4.25/drivers/video/sis/init.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/init.h	2004-03-25 00:21:33.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -111,9 +108,11 @@ const USHORT  ModeIndex_1152x864[]     =
 const USHORT  ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
 const USHORT  ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
 const USHORT  ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
+const USHORT  ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
 const USHORT  ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
 const USHORT  ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
 const USHORT  ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
+const USHORT  ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
 const USHORT  ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
 const USHORT  ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
 const USHORT  ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
@@ -253,7 +252,9 @@ static const SiS_ModeResInfoStruct SiS_M
 	{ 1024, 600, 8,16},   /* 0x19 */
 	{ 1152, 768, 8,16},   /* 0x1a */
 	{  768, 576, 8,16},   /* 0x1b */
-	{ 1360,1024, 8,16}    /* 0x1c */
+	{ 1360,1024, 8,16},   /* 0x1c */
+	{ 1280, 800, 8,16},   /* 0x1d */
+	{ 1680,1050, 8,16}    /* 0x1e */
 };
 
 static SiS_StandTableStruct SiS_StandTable[]=
@@ -758,6 +759,7 @@ static const UCHAR SiS_HiTVSt2Timing[] =
 	0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
 };
 
+#if 0
 static const UCHAR SiS_HiTVTextTiming[] = {
         0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
 	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
@@ -768,6 +770,7 @@ static const UCHAR SiS_HiTVTextTiming[] 
         0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
 	0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
 };
+#endif
 
 static const UCHAR SiS_HiTVGroup3Data[] = {
         0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
@@ -791,6 +794,7 @@ static const UCHAR SiS_HiTVGroup3Simu[] 
 	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
 };
 
+#if 0
 static const UCHAR SiS_HiTVGroup3Text[] = {
         0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
 	0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
@@ -801,6 +805,7 @@ static const UCHAR SiS_HiTVGroup3Text[] 
 	0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
 	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
 };
+#endif
 
 static const UCHAR SiS_NTSCPhase[]    = {0x21,0xed,0xba,0x08};
 static const UCHAR SiS_PALPhase[]     = {0x2a,0x05,0xe3,0x00};
@@ -814,7 +819,7 @@ static const UCHAR SiS_SpecialPhase[] = 
 static const UCHAR SiS_SpecialPhaseM[]= {0x1e,0x83,0x0a,0xe0};
 static const UCHAR SiS_SpecialPhaseJ[]= {0x25,0xd4,0xfd,0x5e};
 
-static const SiS_TVDataStruct  SiS_StPALData[]=
+static const SiS_TVDataStruct  SiS_StPALData[] =
 {
  {    1,   1, 864, 525,1270, 400, 100,   0, 760,0xf4,0xff,0x1c,0x22},
  {    1,   1, 864, 525,1270, 350, 100,   0, 760,0xf4,0xff,0x1c,0x22},
@@ -838,7 +843,7 @@ static const SiS_TVDataStruct  SiS_ExtPA
  {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20}   /* 1024x768 (for NTSC equ) */
 };
 
-static const SiS_TVDataStruct  SiS_StNTSCData[]=
+static const SiS_TVDataStruct  SiS_StNTSCData[] =
 {
  {    1,   1, 858, 525,1270, 400,  50,   0, 760,0xf1,0x04,0x1f,0x18},
  {    1,   1, 858, 525,1270, 350,  50,   0, 640,0xf1,0x04,0x1f,0x18},
@@ -847,7 +852,7 @@ static const SiS_TVDataStruct  SiS_StNTS
  {    1,   1, 858, 525,1270, 480,   0,   0, 760,0xf1,0x04,0x1f,0x18}
 };
 
-static const SiS_TVDataStruct  SiS_ExtNTSCData[]=
+static const SiS_TVDataStruct  SiS_ExtNTSCData[] =
 {
  {  143,  65, 858, 443,1270, 440, 171,   0, 171,0xf1,0x04,0x1f,0x18},    /* 640x400, 320x200 */
  {   88,  35, 858, 393,1270, 440, 171,   0, 171,0xf1,0x04,0x1f,0x18},
@@ -855,39 +860,49 @@ static const SiS_TVDataStruct  SiS_ExtNT
  {  143,  70, 924, 393,1270, 440,  92,   0,  92,0xf4,0x0b,0x1c,0x0a},
  {  143,  76, 836, 523,1270, 440, 224,   0,   0,0xf1,0x05,0x1f,0x16},    /* 640x480, 320x240 */
  {  143, 120,1056, 643,1270, 440,   0, 128,   0,0xf4,0x10,0x1c,0x00},    /* 800x600, 400x300  */
- {  143,  76, 836, 523,1270, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
 /*{   2,   1, 858, 503,1270, 480,   0, 128,   0,0xee,0x0c,0x22,0x08},*/  /* 720x480  (old, from 650) */
- {    1,   1,1100, 811,1412, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
+ {  143,  76, 836, 523,1270, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
 /*{  65,  64,1056, 791,1270, 480, 638,   0,   0,0xEE,0x0C,0x22,0x08} */  /* 1024x768 (525i) */
+ {    1,   1,1100, 811,1412, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
  {   65,  64,1056, 791,1270, 480, 455,   0,   0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
 };
 
-static const SiS_TVDataStruct  SiS_St2HiTVData[]=
+static const SiS_TVDataStruct  SiS_StHiTVData[] =  /* Slave + TVSimu */
+{
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x150,128, 0, 0x00,0x00,0x00,0x00}
+};
+
+static const SiS_TVDataStruct  SiS_St2HiTVData[] = /* Slave */
 {
  {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},
  {    1,   1, 0x37c,0x233,0x2b2,0x2bc, 	  0,  0, 0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x3e8,0x233,0x311,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    5,   2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
  {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
 };
 
-static const SiS_TVDataStruct  SiS_ExtHiTVData[]=
+static const SiS_TVDataStruct  SiS_ExtHiTVData[] =
 {
  {    6,   1, 0x348,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    3,   1, 0x348,0x1e3,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    6,   1, 0x348,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    5,   1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00},  /* 640x480   */
  {   16,   5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x600   */
  {   25,  12, 0x4ec,0x353,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
  {    5,   4, 0x627,0x464,0x670,0x3c0,0x128,  0, 0, 0x00,0x00,0x00,0x00},  /* 1280x1024 */
- {    4,   1, 0x41a,0x233,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x480   */
+ {    4,   1, 0x41a,0x233,0x60c,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x480   */
  {    5,   2, 0x578,0x293,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},  /* 1024x576  */
  {    8,   5, 0x6d6,0x323,0x670,0x3c0,0x128,  0, 0, 0x00,0x00,0x00,0x00}   /* 1280x720  */
 };
 
-static const SiS_TVDataStruct  SiS_St525pData[]=
+static const SiS_TVDataStruct  SiS_St525pData[] =
 {
  {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
  {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
@@ -896,7 +911,7 @@ static const SiS_TVDataStruct  SiS_St525
  {    1,   1, 0x6b4,0x20d,0x4f6,0x1e0,    0,  0, 0x2f8, 0x00,0x00,0x00,0x00}
 };
 
-static const SiS_TVDataStruct  SiS_St750pData[]=
+static const SiS_TVDataStruct  SiS_St750pData[] =
 {
  {    1,   1, 0x672,0x2ee,0x500,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
  {    1,   1, 0x672,0x2ee,0x500,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
@@ -905,8 +920,21 @@ static const SiS_TVDataStruct  SiS_St750
  {    1,   1, 0x672,0x2ee,0x500,0x1e0,    0,  0, 0x2f8, 0x00,0x00,0x00,0x00}
 };
 
-static const SiS_TVDataStruct  SiS_Ext750pData[]=
+static const SiS_TVDataStruct  SiS_Ext750pData[] =
 {
+#if 1
+ {  143,  65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
+ {   88,  35, 0x35a,0x189,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
+ {   18,   5, 0x339,0x1ae,0x500,0x2d0,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
+ {  143,  70, 0x39c,0x189,0x4f6,0x1b8,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
+ {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480  */
+ {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600  */
+ {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480  */
+ {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768 */
+ {    5,   2, 0x3a7,0x226,0x500,0x2a8,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x576  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720 */
+#endif
+#if 0
  {    3,   1, 0x3a7,0x1d6,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
  {   24,   7, 0x3a7,0x1a4,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3a7,0x1d6,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
@@ -915,63 +943,105 @@ static const SiS_TVDataStruct  SiS_Ext75
  {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600   */
  {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480   */
  {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720  */
+#endif
+#if 0
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* TEST (0.93) */
+ {   17,   6, 0x339,0x203,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {   17,   6, 0x339,0x203,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {   85,  46, 0x3f4,0x27b,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480   */
+ {   17,  16, 0x55f,0x323,0x460,0x2a8,0x2b6,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600   */
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480   */
+ {  187,  74, 0x39d,0x203,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00}   /* 1280x720  */
+#endif
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+static const SiS_LCDDataStruct  SiS_LCD1280x720Data[] =  
 {
-	{    9,   2, 800, 500,1800,1000},
-	{    9,   2, 800, 500,1800,1000},
-	{    4,   1, 900, 500,1800,1000},
-	{    4,   1, 900, 500,1800,1000},
-	{    9,   2, 800, 500,1800,1000},
-	{   30,  11,1056, 625,1800,1000},
-	{    5,   3,1350, 800,1800,1000},
-	{    1,   1,1576,1050,1576,1050},
-	{    1,   1,1800,1000,1800,1000}
-};
-
-/* 1280x768 panel data from Fujitsu 7911 (VL-17WDX8).
- * Other 1280x768 panels (with clock != 81000, HTxVT != 1688x802)
- * will be treated as custom panels.
+	{  14,    5,  864,  432, 1344,  806 }, /* 640x400 */
+	{  16,    5,  864,  378, 1344,  806 },
+	{  14,    5,  864,  432, 1344,  806 },
+	{  16,    5,  864,  378, 1344,  806 },
+	{  24,   11,  924,  523, 1344,  806 }, /* 640x480 */
+	{   7,    5, 1152,  664, 1344,  806 }, /* 800x600 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1344,  806, 1344,  806 }  /* 1280x720 */
+};
+
+/* About 1280x768: For TMDS, Panel_1280x768 will only be set if
+ * the panel is a Fujitsu 7911 (VL-17WDX8) (with clock 81, 1688x802)
+ * Other TMDS panels of this resolution will be treated as custom.
+ * For LVDS, we know two types. Data follows:
  */
 
-static const SiS_LCDDataStruct  SiS_StLCD1280x768Data[] =
+static const SiS_LCDDataStruct  SiS_StLCD1280x768_2Data[] =
 {
-	{ 211,  100, 2100,  408, 1688,  802 }, /* These values are *wrong* */
-	{ 211,   64, 1536,  358, 1688,  802 }, /* (which is why they aren't used yet) */
-	{ 211,  100, 2100,  408, 1688,  802 },
-	{ 211,   64, 1536,  358, 1688,  802 },
-	{ 211,   48,  840,  488, 1688,  802 },
-	{ 211,   72, 1008,  609, 1688,  802 },
-	{ 211,  128, 1400,  776, 1688,  802 },
-	{ 211,  205, 1680, 1041, 1688,  802 },
-	{ 1,      1, 1688,  802, 1688,  802 }  /* That's the only one that is correct */
-};
-
-static const SiS_LCDDataStruct  SiS_ExtLCD1280x768Data[] =
-{
-	{ 211,  100, 2100,  408, 1688,  802 }, /* These values are *wrong* */
-	{ 211,   64, 1536,  358, 1688,  802 }, /* (which is why they aren't used yet) */
-	{ 211,  100, 2100,  408, 1688,  802 },
-	{ 211,   64, 1536,  358, 1688,  802 },
-	{ 211,   48,  840,  488, 1688,  802 },
-	{ 211,   72, 1008,  609, 1688,  802 },
-	{ 211,  128, 1400,  776, 1688,  802 },
-	{ 211,  205, 1680, 1041, 1688,  802 },
-	{ 1,      1, 1688,  802, 1688,  802 }  /* That's the only one that is correct */
-};
-
-static const SiS_LCDDataStruct  SiS_NoScaleData1280x768[] =
-{
-        { 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802}
+	{  64,   21,  858,  434, 1408,  806 }, /* 640x400 */
+	{  32,    9,  858,  372, 1408,  806 },
+	{  64,   21,  858,  434, 1408,  806 },
+	{  32,    9,  858,  372, 1408,  806 },
+	{ 143,   68, 1024,  527, 1408,  806 }, /* 640x480 */
+	{  64,   51, 1364,  663, 1408,  806 }, /* 800x600 */
+	{  88,   81, 1296,  806, 1408,  806 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }  /* 1280x768 */
+};
+
+static const SiS_LCDDataStruct  SiS_ExtLCD1280x768_2Data[] =
+{
+	{  64,   25, 1056,  422, 1408,  806 }, /*, 664 */
+	{ 128,   39,  884,  396, 1408,  806 }, /*, 640 */
+	{  64,   25, 1056,  422, 1408,  806 }, /*, 664 */
+	{ 128,   39,  884,  396, 1408,  806 }, /*, 640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /*, 664 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /*, 768 */
+	{  88,   81, 1296,  806, 1408,  806 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x768_3Data[] =
+{
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /* ,664 */	/* 640x480 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /* ,768 */	/* 800x600 */
+	{  64,   61, 1342,  806, 1408,  806 },			/* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }			/* 1280x768 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x800Data[] =
+{
+	{ 128,   51, 1122,  412, 1408,  816 }, /* 640x400 */
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{ 128,   51, 1122,  412, 1408,  816 },
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{   8,    3,  880,  491, 1408,  816 }, /* 640x480 */
+	{  11,    6, 1024,  612, 1408,  816 }, /* 800x600 */
+	{  22,   21, 1400,  784, 1408,  816 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  816, 1408,  816 }  /* 1280x800 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+{
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{   30,  11, 1056,  625, 1800, 1000 },
+	{    5,   3, 1350,  800, 1800, 1000 },
+	{    1,   1, 1576, 1050, 1576, 1050 },
+	{    1,   1, 1800, 1000, 1800, 1000 }
 };
 
 static const SiS_LCDDataStruct  SiS_StLCD1400x1050Data[] =
@@ -989,28 +1059,32 @@ static const SiS_LCDDataStruct  SiS_StLC
 
 static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
 {
-	{ 211,  100, 2100,  408, 1688, 1066 },
+	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 */
 	{ 211,   64, 1536,  358, 1688, 1066 },
 	{ 211,  100, 2100,  408, 1688, 1066 },
 	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,   48,  840,  488, 1688, 1066 },
-	{ 211,   72, 1008,  609, 1688, 1066 },
+	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 */
+	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 */
 	{ 211,  128, 1400,  776, 1688, 1066 },
 	{ 211,  205, 1680, 1041, 1688, 1066 },
 	{   1,    1, 1688, 1066, 1688, 1066 }
 };
 
-static const SiS_LCDDataStruct  SiS_NoScaleData1400x1050[] =
+static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
 {
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 }
+	{  95,   24, 1260,  410, 1900, 1066 }, /*  0 640x400 */
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   24, 1260,  410, 1900, 1066 },
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   32, 1400,  490, 1900, 1066 }, /*  4 640x480 */
+	{  95,   42, 1470,  610, 1900, 1066 }, /*  5 800x600 */
+	{  95,   64, 1750,  784, 1900, 1066 }, /*  6 1024x768 */
+	{  95,   94, 1900, 1055, 1900, 1066 }, /*  7 1280x1024 */
+	{  41,   31, 1900,  806, 1900, 1066 }, /*  8 1280x768 */
+	{  95,   69, 1800,  817, 1900, 1066 }, /*  9 1280x800 patch */
+	{  13,    9, 1900,  739, 1900, 1066 }, /* 10 1280x720 */
+	{  95,   94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch */
+	{   1,    1, 1900, 1066, 1900, 1066 }  /* 12 1680x1050 */
 };
 
 static const SiS_LCDDataStruct  SiS_StLCD1600x1200Data[] =
@@ -1041,422 +1115,29 @@ static const SiS_LCDDataStruct  SiS_ExtL
 	{ 1, 1,2160,1250, 2160, 1250 }
 };
 
-static const SiS_LCDDataStruct  SiS_NoScaleData1600x1200[] =
-{
-        {1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-};
-
 static const SiS_LCDDataStruct  SiS_NoScaleData[] =
 {
-	{ 1, 1, 800, 449, 800, 449 },
+	{ 1, 1, 800, 449, 800, 449 },  /* 0x00: 320x200, 640x400 */
 	{ 1, 1, 800, 449, 800, 449 },
 	{ 1, 1, 900, 449, 900, 449 },
 	{ 1, 1, 900, 449, 900, 449 },
-	{ 1, 1, 800, 525, 800, 525 },
-	{ 1, 1,1056, 628,1056, 628 },
-	{ 1, 1,1344, 806,1344, 806 },
-	{ 1, 1,1688,1066,1688,1066 },
-        { 1, 1,1688, 802,1688, 802 },  /* 1280x768: 802 was 806 in both cases */
-        { 1, 1,2160,1250,2160,1250 },  /* 1600x1200 */
-	{ 1, 1,1800,1000,1800,1000 }   /* 1280x960 */
-};
-
-/* *** LCDA *** */
-
-static const SiS_LVDSDataStruct  SiS_LCDA1024x768Data_1[]=
-{
-	{  960, 438,1344, 806},
-	{  960, 388,1344, 806},
-	{ 1040, 438,1344, 806},
-	{ 1040, 388,1344, 806},
-	{  960, 518,1344, 806},   /* 640x480 */
-	{ 1120, 638,1344, 806},   /* 800x600 */
-	{ 1344, 806,1344, 806},   /* 1024x768 */
-#if 0
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 518,1344, 806},   /* 640x480 */
-	{1050, 638,1344, 806},   /* 800x600 */
-	{1344, 806,1344, 806},   /* 1024x768 */
-#endif
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1024x768Data_2[]=
-{
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1280x1024Data_1[]=
-{ /* Acer, Compaq */
-	{1048, 442,1688,1066},
-	{1048, 392,1688,1066},
-	{1128, 442,1688,1066},
-	{1128, 392,1688,1066},
-	{1048, 522,1688,1066},
-	{1208, 642,1688,1066},
-	{1432, 810,1688,1066},
-	{1688,1066,1688,1066}
+	{ 1, 1, 800, 525, 800, 525 },  /* 0x04: 320x240, 640x480  */
+	{ 1, 1,1056, 628,1056, 628 },  /* 0x05: 400x300, 800x600  */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x06: 512x384, 1024x768 */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x07: 1280x1024 */
+        { 1, 1,1688, 802,1688, 802 },  /* 0x08: 1280x768: Fujitsu, TMDS only */
+        { 1, 1,2160,1250,2160,1250 },  /* 0x09: 1600x1200 */
+	{ 1, 1,1800,1000,1800,1000 },  /* 0x0a: 1280x960  */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x0b: 1400x1050 */
+	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS)  */
+	{ 1, 1,1408, 816,1408, 816 },  /* 0x0d: 1280x800  */
+	{ 1, 1,1900,1066,1900,1066 },  /* 0x0e: 1680x1050 (LVDS) */
+	{ 1, 1,1408, 806,1408, 806 },  /* 0x0f: 1280x768_2 */
+	{ 1, 1,1664, 798,1664, 798 },  /* 0x10: 1280x768_3 */
+	{ 1, 1,1688, 802,1688, 802 },  /* 0x11: 1280x768: Std, TMDS only */
+	{ 1, 1,1344, 806,1344, 806 }   /* 0x12: 1280x720 (LVDS)  */
 };
 
-static const SiS_LVDSDataStruct  SiS_LCDA1280x1024Data_2[]=
-{ /* Corrected (illegal in Acer, correct in Compaq) */
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1400x1050Data_1[]=
-{ /* Clevo */
-        { 928, 416, 1688,1066},
-	{ 928, 366, 1688,1066},
-	{1008, 416, 1688,1066},
-	{1008, 366, 1688,1066},
-	{1200, 530, 1688,1066},
-	{1088, 616, 1688,1066},
-	{1312, 784, 1688,1066},
-	{1568,1040, 1688,1066},
-	{1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1400x1050Data_2[]=
-{ /* Clevo */
-    	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
-{ /* Clevo (Temporary data)  */
-	{1200, 450, 2048,1250},
-	{1200, 400, 2048,1250},
-	{1280, 450, 2048,1250},
-	{1280, 400, 2048,1250},
-	{1200, 530, 2048,1250},
-	{1360, 650, 2048,1250},
-	{1584, 818, 2048,1250},
-	{1688,1066, 2048,1250},
-	{1688,1066, 2048,1250},
-	{2048,1250, 2048,1250}   /* this should be correct */
-#if 0
-	{2160,1250, 2048,1250}   /* ? */
-#endif
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_2[]=
-{ /* Clevo (Temporary data. Seems invalid.) */
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250}
-};
-
-/* LVDS SKEW for LCDA */
-
-static const SiS_LVDSDesStruct SiS_PanelType1076_1[]=
-{  /* 1024x768 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},   /* 805; was 0, 0 -> top line cut away (26/09/03) */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1076_2[]=
-{  /* 1024x768; not expanded */
-	{ 1184, 622 },
-	{ 1184, 597 },
-	{ 1184, 622 },
-	{ 1184, 597 },
-	{ 1152, 650 },  /* 622 */
-	{ 1232, 722 },
-	{    0, 0   },  /* 805; was 0, 0 -> top line cut away (26/09/03) */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1210_1[]=
-{  /* 1280x1024 */
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 , 1065},  /* Acer */
-	{ 0 ,    0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1210_2[]=
-{  /* 1280x1024; not expanded */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1296_1[]=
-{  /* 1400x1050 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 1065}   /* Was 0,0 */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1296_2[]=
-{  /* 1400x1050; not expanded */
-	{ 1308, 741 },
-	{ 1308, 716 },
-	{ 1308, 741 },
-	{ 1308, 716 },
-	{ 1308, 781 },
-	{ 1388, 841 },
-	{ 1500, 925 },
-	{ 1628,1053 },
-	{    0,1065 }
-#if 0
-	{ 808 , 740},
-	{ 0   , 715},
-	{ 632 , 740},
-	{ 632 , 715},
-	{ 1307, 780},
-	{ 1387,1157},
-	{ 1499, 924},
-	{ 1627,1052},
-	{ 0 , 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1600_1[]=
-{  /* 1600x1200 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1600_2[]=
-{  /* 1600x1200; not expanded */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-#ifdef SIS315H
-
-/* LCDA CRT1 custom data */
-
-static const SiS_LCDACRT1DataStruct  Compaq1280x1024_LCDACRT1_1[]=
-{
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x63,0x96,0x6c,0x1a,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x7f,0x92,0x88,0x96,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa8,0x16,0x28,0x5a,
-   0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Compaq1280x1024_LCDACRT1_1_H[]=
-{
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1,
-   0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1,
-   0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x31,0x84,0x3a,0x88,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x3f,0x92,0x48,0x96,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_1[]=
-{
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x63,0x8B,0x69,0x1A,0x7c,0xf0,
-   0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x26,
-   0x01}},
- {{0xA3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_1_H[]=
-{
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x32,0x1b,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x45,
-   0x00}},
- {{0x55,0x31,0x31,0x99,0x46,0x1d,0x7c,0xf0,
-   0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x55,
-   0x01}},
- {{0x63,0x3F,0x3F,0x87,0x4A,0x93,0x24,0xF5,
-   0x02,0x88,0xFF,0xFF,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_2[]=
-{
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_2_H[]=
-{
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x7f,0x86,0xdf,0xdf,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x71,0x31,0x31,0x95,0x46,0x97,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x01,
-   0x01 }},
- {{0x63,0x3f,0x3f,0x87,0x46,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-#endif  /* 315 */
 
 /**************************************************************/
 /* LVDS ----------------------------------------------------- */
@@ -1507,9 +1188,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{ 848, 389,1060, 629},
 	{ 848, 518,1060, 629},
 	{1056, 628,1056, 628},
-	{1056, 628,1056, 628},
-	{ 800, 449,1000, 644},
-	{ 800, 525,1000, 635}
+	{1056, 628,1056, 628}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS800x600Data_2[]=
@@ -1520,9 +1199,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{1056, 628,1056, 628},
 	{1056, 628,1056, 628},
 	{1056, 628,1056, 628},
-	{1056, 628,1056, 628},
-	{ 800, 449,1000, 644},
-	{ 800, 525,1000, 635}
+	{1056, 628,1056, 628}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_1[]=
@@ -1534,8 +1211,6 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{ 840, 518,1344, 806},   /* 640x480 */
 	{1050, 638,1344, 806},   /* 800x600 */
 	{1344, 806,1344, 806},   /* 1024x768 */
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_2[]=
@@ -1547,11 +1222,8 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
 };
 
-
 static const SiS_LVDSDataStruct  SiS_LVDS1280x1024Data_1[]=
 {
 	{1048, 442,1688,1066},
@@ -1702,9 +1374,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{ 840, 560,1344, 800},
 	{ 840, 689,1344, 800},
 	{1050, 800,1344, 800},
-	{1344, 800,1344, 800},
-	{ 800, 449,1280, 789},
-	{ 800, 525,1280, 785}
+	{1344, 800,1344, 800}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x600Data_2[] =
@@ -1715,9 +1385,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{1344, 800,1344, 800},
 	{1344, 800,1344, 800},
 	{1344, 800,1344, 800},
-	{1344, 800,1344, 800},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 800,1344, 800}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_1[] =
@@ -1728,9 +1396,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{ 840, 409,1344, 806},
 	{ 840, 518,1344, 806},
 	{1050, 638,1344, 806},
-	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 806,1344, 806}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_2[] =
@@ -1741,9 +1407,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 806,1344, 806}
 };
 
 /* Pass 1:1 data */
@@ -1756,7 +1420,7 @@ static const SiS_LVDSDataStruct  SiS_LVD
 	{ 800, 525,  800, 525},  /*  640x480   */
 	{1056, 628, 1056, 628},  /*  800x600   */
 	{1344, 806, 1344, 806},  /* 1024x768   */
-	{1344,1066, 1344,1066},  /* 1280x1024  */  /* INSERTED ! */
+	{1688,1066, 1688,1066},  /* 1280x1024  */  /* INSERTED ! */
  	{1688, 806, 1688, 806},  /* 1280x768   */
 	/* No other panels ! */
 };
@@ -1871,36 +1535,6 @@ static const SiS_LVDSDataStruct  SiS_CHT
         {1160, 840,1160, 840}
 };
 
-/* LVDS Skew */
-
-static const SiS_LVDSDesStruct  SiS_PanelTypeNS_1[]=
-{
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 0,   0},
-	{ 0,   0},
-	{ 0,   0},
-	{ 0, 806},
-	{ 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS_PanelTypeNS_2[] =
-{
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
 /* Chrontel TV Skew */
 
 static const SiS_LVDSDesStruct  SiS_CHTVUNTSCDesData[]=
@@ -2439,63 +2073,6 @@ static const SiS_LVDSCRT1DataStruct  SiS
    0x01}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
-   0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-
 /**************************************************************/
 /* COMMON --------------------------------------------------- */
 /**************************************************************/
@@ -2756,7 +2333,8 @@ static const SiS_PlasmaTables SiS_Plasma
    { 0x0000 }
 };
 
-USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
+USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
+			  int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
 USHORT  SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN,
                           USHORT CustomT, int LCDwith, int LCDheight);
 USHORT  SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
@@ -2777,6 +2355,7 @@ void	SiS_DisplayOn(SiS_Private *SiS_Pr);
 void	SiS_DisplayOff(SiS_Private *SiS_Pr);
 void	SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
 void	SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void	SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
@@ -2787,6 +2366,7 @@ USHORT	SiS_GetColorDepth(SiS_Private *Si
 USHORT	SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
               USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo);
 void	SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex);
+void	SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 #ifdef LINUX_XF86
 BOOLEAN	SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch);
 BOOLEAN	SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/init301.c linux-2.4.26-pre6/drivers/video/sis/init301.c
--- linux-2.4.25/drivers/video/sis/init301.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/init301.c	2004-03-25 00:17:15.000000000 +0000
@@ -34,13 +34,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -76,10 +73,6 @@
 
 #include "init301.h"
 
-#if 0
-#define TWNEWPANEL
-#endif
-
 #ifdef SIS300
 #include "oem300.h"
 #endif
@@ -91,6 +84,8 @@
 #define SiS_I2CDELAY      1000
 #define SiS_I2CDELAYSHORT  150
 
+static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
+
 /*********************************************/
 /*         HELPER: Lock/Unlock CRT2          */
 /*********************************************/
@@ -98,146 +93,75 @@
 void
 SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  if(HwInfo->jChipType >= SIS_315H)
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
-  else
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
+   if(HwInfo->jChipType >= SIS_315H)
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+   else
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 }
 
 void
 SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  if(HwInfo->jChipType >= SIS_315H)
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
-  else
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
+   if(HwInfo->jChipType >= SIS_315H)
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
+   else
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
 }
 
 /*********************************************/
-/*            HELPER: Enable CRT2            */
+/*            HELPER: Write SR11             */
 /*********************************************/
 
-void
-SiS_EnableCRT2(SiS_Private *SiS_Pr)
+static void
+SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
 {
-  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+   if(HwInfo->jChipType >= SIS_661) DataAND &= 0x0f;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 }
 
 /*********************************************/
 /*    HELPER: Get Pointer to LCD structure   */
 /*********************************************/
 
-/* For 661 series only */
 #ifdef SIS315H
-#if 0   /* Need to wait until hardware using this really exists */
 static UCHAR *
-GetLCDPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int tabletype,
-             USHORT ModeNo, USHORT ModeIdIndex, USHORT RRTI)
+GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  UCHAR *ROMAddr =  HwInfo->pjVirtualRomBase;
-  UCHAR *tableptr = NULL;
-  UCHAR tablelengths[] = { 8, 7, 6, 6, 8, 6, 0, 0, 0 };
-  USHORT modeflag, CRT2Index, tablelength, lcdid, myid, tableptri;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     CRT2Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT2CRTC;
-     /* This is total bullshit: */
-     if(SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO == SIS_RI_720x576) CRT2Index = 10;
-  }
-
-  if(tabletype <= 1) {
-#if 0	/* Not yet implemented */
-     if(ModeNo <= 0x13) {
-        CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex]. + 5;
-     } else {
-        CRT2Index = SiS_Pr->SiS_RefIndex[RRTI]. + 5;
-     }
-     if(tabletype & 1) CRT2Index >>= 4;
-#endif
-  }
-
-  CRT2Index &= 0x0f;
-
-  tablelength = tablelengths[tabletype];
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     if((tabletype == 5) || (tabletype == 7)) tablelength = 8;
-     if((tabletype == 3) || (tabletype == 8)) tablelength = 8;
-  }
-
-  if(!tablelength) return NULL;
-
-  tableptri = ROMAddr[0x222] | (ROMAddr[0x223] << 8);
-  tableptri += (tabletype << 1);
-  if(!tableptri) return NULL;
-  tableptr = &ROMAddr[tableptri];
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   UCHAR  *myptr = NULL;
+   USHORT romindex = 0;
 
-  do {
-     lcdid = tableptr[0];
-     if(lcdid == 0xff) break;
-     myid = SiS_Pr->SiS_LCDResInfo;
-     if((lcdid & 0x80) && (lcdid != 0x80)) {
-        lcdid &= 0x7f;
-	myid = SiS_Pr->SiS_LCDTypeInfo;
-     }
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) myid &= ~0x1f;
-
-     if(myid == lcdid) {
-	lcdid = tableptr[1] | (tableptr[2] << 8);
-	myid = SiS_Pr->SiS_LCDInfo661;
-	if(modeflag & HalfDCLK) myid |= 0x200;
-	if(ModeNo <= 0x13)      myid |= 0x400;
-	lcdid &= myid;
-	myid = tableptr[3] | (tableptr[4] << 8);
-	if(lcdid == myid) break;
-     }
-     tableptr += 7;
-  } while (1);
-
-  if(lcdid == myid) {
-     lcdid = tableptr[5] | (tableptr[6] << 8);
-     lcdid += (tablelength * CRT2Index);
-     return((UCHAR *)&ROMAddr[lcdid]);
-  }
+   /* Use the BIOS tables only for LVDS panels; DVI is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    */
 
-  return NULL;
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+      myptr = (UCHAR *)SiS_LCDStruct661;
+      romindex = SISGETROMW(0x100);  /* 10c, 0.93: 10e */
+      if(romindex) {
+         romindex += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x7d) & 0x1f) * 26);
+         myptr = &ROMAddr[romindex];
+      }
+   }
+   return myptr;
 }
-#endif
 
-static UCHAR *
-GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static USHORT
+GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-   USHORT lcdres = SiS_Pr->SiS_LCDResInfo;
-   USHORT lcdtype = SiS_Pr->SiS_LCDTypeInfo;
-   USHORT romindex=0;
-   UCHAR  *myptr = NULL;
-   UCHAR  lcdid;
+   USHORT romptr = 0;
 
-   if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-      romindex = ROMAddr[0x256] | (ROMAddr[0x257] << 8);
-   }
-   if(romindex) {
-      myptr = &ROMAddr[romindex];
-   } else {
-      myptr = (UCHAR *)SiS_LCDStruct661;
-   }
+   /* Use the BIOS tables only for LVDS panels; DVI is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    */
 
-   while(myptr[0] != 0xff) {
-      lcdid = myptr[0];
-      if((lcdid & 0x80) && (lcdid != 0x80)) {
-         lcdres = lcdtype;
-	 lcdid &= 0x7f;
-      }
-      if(lcdid == lcdres) break;
-      myptr += 26;
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+      romptr = SISGETROMW(0x102);  /* 2ad */
+      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
    }
-   if(myptr[0] == 0xff) return NULL;
 
-   return myptr;
+   return(romptr);
 }
 #endif
 
@@ -250,71 +174,72 @@ SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, 
                    USHORT RefreshRateTableIndex, USHORT *i,
 		   PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempbx,infoflag;
-
-  tempbx = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+  USHORT checkmask=0,modeid,infoflag;
 
-  tempax = 0;
+  modeid = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 
-      	tempax |= SupportRAMDAC2;
+      	checkmask |= SupportRAMDAC2;
 	if(HwInfo->jChipType >= SIS_315H) {
-	   tempax |= SupportRAMDAC2_135;
+	   checkmask |= SupportRAMDAC2_135;
 	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      tempax |= SupportRAMDAC2_162;
+	      checkmask |= SupportRAMDAC2_162;
 	      if(SiS_Pr->SiS_VBType & VB_SIS301C) {
-		 tempax |= SupportRAMDAC2_202;
+		 checkmask |= SupportRAMDAC2_202;
 	      }
 	   }
 	}
 
      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 
-     	tempax |= SupportLCD;
+     	checkmask |= SupportLCD;
 	if(HwInfo->jChipType >= SIS_315H) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	         if(tempbx == 0x2e) {  /* 640x480 */
-		    tempax |= Support64048060Hz;
-		 }
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	         if(modeid == 0x2e) checkmask |= Support64048060Hz;
 	      }
 	   }
 	}
 
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-      	tempax |= SupportHiVision;
+      	checkmask |= SupportHiVision;
 
      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
 
-        tempax |= SupportTV;
+        checkmask |= SupportTV;
 	if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	   tempax |= SupportTV1024;
+	   checkmask |= SupportTV1024;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	         checkmask |= SupportYPbPr750p;
+	      }
+	   }
 	}
 
      }
 
-  } else {	/* for LVDS  */
+  } else {	/* LVDS */
 
      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-           tempax |= SupportCHTV;
+           checkmask |= SupportCHTV;
       	}
      }
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     	tempax |= SupportLCD;
+     	checkmask |= SupportLCD;
      }
 
   }
 
   /* Look backwards in table for matching CRT2 mode */
-  for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == tempbx; (*i)--) {
+  for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == modeid; (*i)--) {
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
-     if(infoflag & tempax) return(1);
+     if(infoflag & checkmask) return TRUE;
      if((*i) == 0) break;
   }
 
@@ -322,17 +247,17 @@ SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, 
    * for a matching CRT2 mode if no mode was found yet.
    */
   for((*i) = 0; ; (*i)++) {
-     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != tempbx) {
-     	return(0);
+     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != modeid) {
+     	return FALSE;
      }
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
-     if(infoflag & tempax) return(1);
+     if(infoflag & checkmask) return TRUE;
   }
-  return(1);
+  return TRUE;
 }
 
 /*********************************************/
-/*              Get rate pointer             */
+/*              Get rate index               */
 /*********************************************/
 
 USHORT
@@ -357,13 +282,11 @@ SiS_GetRatePtr(SiS_Private *SiS_Pr, USHO
 
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     	if(modeflag & HalfDCLK) return(0);
+     	if(modeflag & HalfDCLK) return 0;
      }
   }
 
-  if(ModeNo < 0x14) return(0xFFFF);
-
-  /* CR33 holds refresh rate index for CRT1 [3:0] and CRT2 [7:4]. */
+  if(ModeNo < 0x14) return 0xFFFF;
 
   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
   backupindex = index;
@@ -378,7 +301,7 @@ SiS_GetRatePtr(SiS_Private *SiS_Pr, USHO
 	}
 	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	   if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
-              temp = LCDRefreshIndex[SiS_Pr->SiS_LCDResInfo];
+              temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
               if(index > temp) index = temp;
 	   }
 	}
@@ -451,37 +374,39 @@ SiS_SaveCRT2Info(SiS_Private *SiS_Pr, US
 /*    HELPER: GET SOME DATA FROM BIOS ROM    */
 /*********************************************/
 
+#ifdef SIS300
 static BOOLEAN
 SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase;
   USHORT temp,temp1;
-  UCHAR *ROMAddr;
 
-  if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4);
-        temp1 = (ROMAddr[0x23c] << 8) | ROMAddr[0x23b];
-        if(temp1 & temp) return(1);
+        temp1 = SISGETROMW(0x23b);
+        if(temp1 & temp) return TRUE;
      }
   }
-  return(0);
+  return FALSE;
 }
 
 static BOOLEAN
 SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase;
   USHORT temp,temp1;
-  UCHAR *ROMAddr;
 
-  if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4);
-        temp1 = (ROMAddr[0x23e] << 8) | ROMAddr[0x23d];
-        if(temp1 & temp) return(1);
+        temp1 = SISGETROMW(0x23d);
+        if(temp1 & temp) return TRUE;
      }
   }
-  return(0);
+  return FALSE;
 }
+#endif
 
 /*********************************************/
 /*          HELPER: DELAY FUNCTIONS          */
@@ -555,7 +480,7 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
          } else {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
          }
-	 if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+	 if(SiS_Pr->SiS_UseROM) {
             if(ROMAddr[0x220] & 0x40) {
                if(!(DelayTime & 0x01)) {
 	          Delay = (USHORT)ROMAddr[0x225];
@@ -573,7 +498,15 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
 
 #ifdef SIS315H
 
-      if(HwInfo->jChipType >= SIS_330) return;
+      if(HwInfo->jChipType >= SIS_661) {
+
+         if(!(DelayTime & 0x01)) {
+	    SiS_DDC2Delay(SiS_Pr, 0x1000);
+         } else {
+	    SiS_DDC2Delay(SiS_Pr, 0x4000);
+         }
+
+      } else if(HwInfo->jChipType >= SIS_330) return;
 
       if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
@@ -598,7 +531,7 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
                } else {
        		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
                }
-	       if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+	       if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
                   if(ROMAddr[0x13c] & 0x40) {
                      if(!(DelayTime & 0x01)) {
 	    	        Delay = (USHORT)ROMAddr[0x17e];
@@ -619,10 +552,7 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
          } else {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
          }
-	 Delay <<= 2;
-	 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	    Delay <<= 5;
-	 }
+	 Delay <<= 8;
 	 SiS_DDC2Delay(SiS_Pr, Delay);
 
       }
@@ -737,10 +667,7 @@ SiS_VBLongWait(SiS_Private *SiS_Pr)
 static BOOLEAN
 SiS_Is301B(SiS_Private *SiS_Pr)
 {
-  USHORT flag;
-
-  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-  if(flag >= 0xb0) return TRUE;
+  if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
   return FALSE;
 }
 
@@ -804,6 +731,27 @@ SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS
 
 #ifdef SIS315H
 static BOOLEAN
+SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
+     if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+  }
+  return FALSE;
+}
+#endif
+
+#ifdef SIS315H
+static BOOLEAN
+SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
+  return FALSE;
+}
+#endif
+
+#ifdef SIS315H
+static BOOLEAN
 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   USHORT flag;
@@ -956,7 +904,7 @@ SiS_SetChrontelGPIO(SiS_Private *SiS_Pr,
    if(!(SiS_Pr->SiS_ChSW)) return;
 
 #ifndef LINUX_XF86
-   SiS_SetRegLong(0xcf8,0x80000874);		   /* get ACPI base */
+   SiS_SetRegLong(0xcf8,0x80000874);		       /* get ACPI base */
    acpibase = SiS_GetRegLong(0xcfc);
 #else
    acpibase = pciReadLong(0x00000800, 0x74);
@@ -974,22 +922,19 @@ SiS_SetChrontelGPIO(SiS_Private *SiS_Pr,
 }
 
 void
-SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo,
-              USHORT ModeIdIndex,PSIS_HW_INFO HwInfo,
-	      int checkcrt2mode)
+SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
+              PSIS_HW_INFO HwInfo, int checkcrt2mode)
 {
   USHORT tempax,tempbx,temp;
   USHORT modeflag, resinfo=0;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-   	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
   SiS_Pr->SiS_SetFlag = 0;
@@ -1001,11 +946,12 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
     	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 #if 0
    	if(HwInfo->jChipType < SIS_661) {
-	   if(SiS_Pr->SiS_YPbPr & YPbPrModeMask) {
+	   /* NO - YPbPr not set yet ! */
+	   if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
 	      temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); 	/* 0x83 */
 	      temp |= SetCRT2ToHiVision;   					/* 0x80 */
    	   }
-	   if(SiS_Pr->SiS_YPbPr & YPbPrSetSVideo) {
+	   if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
 	      temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); 	/* 0x83 */
 	      temp |= SetCRT2ToSVIDEO;  					/* 0x08 */
 	   }
@@ -1040,16 +986,28 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
        	      if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
           	 tempbx |= SetCRT2ToLCDA;
 	      }
-	      if(HwInfo->jChipType >= SIS_661) {
-	         if(SiS_Pr->SiS_VBType & (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
-	            if(temp & 0x04) {
-		       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
-		       if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
-		       else             tempbx |= SetCRT2ToYPbPr525750;
-		    }
-	         }
-  	      }
-    	   }
+	   }
+
+	   if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
+	      tempbx &= ~(SetCRT2ToRAMDAC);
+	   }
+
+	   if(HwInfo->jChipType >= SIS_661) {
+	      tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
+	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	      if(SiS_Pr->SiS_VBType & (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
+	         if(temp & 0x04) {
+		    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+		    if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+		    else             tempbx |= SetCRT2ToYPbPr525750;
+		 }
+	      } else if(SiS_Pr->SiS_VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B)) {
+	         if(temp & 0x04) {
+		    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+		    if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+		 }
+	      }
+  	   }
 
 	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -1111,24 +1069,12 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
 				SetPALTV 	   |
 				SwitchCRT2	   |
 				SetSimuScanMode );
-      	   if(tempbx & SetCRT2ToLCDA) {
-              tempbx &= (clearmask | SetCRT2ToLCDA);
-      	   }
-	   if(tempbx & SetCRT2ToRAMDAC) {
-              tempbx &= (clearmask | SetCRT2ToRAMDAC);
-      	   }
-	   if(tempbx & SetCRT2ToLCD) {
-              tempbx &= (clearmask | SetCRT2ToLCD);
-      	   }
-	   if(tempbx & SetCRT2ToSCART) {
-              tempbx &= (clearmask | SetCRT2ToSCART);
-      	   }
-	   if(tempbx & SetCRT2ToHiVision) {
-              tempbx &= (clearmask | SetCRT2ToHiVision);
-      	   }
-	   if(tempbx & SetCRT2ToYPbPr525750) {
-	      tempbx &= (clearmask | SetCRT2ToYPbPr525750);
-	   }
+      	   if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
+	   if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
+	   if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
+	   if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
+	   if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
+	   if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
    	} else {
 	   if(HwInfo->jChipType >= SIS_315H) {
 	      if(tempbx & SetCRT2ToLCDA) {
@@ -1156,14 +1102,12 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
       	   }
     	}
 
-    	if(!(tempbx & DriverMode)){
-      	   tempbx |= SetSimuScanMode;
-    	}
+    	if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
 
 	/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
 	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
 	   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
-	       ((tempbx & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD)) ) {
+	       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
 	       modeflag &= (~CRT2Mode);
 	   }
 	}
@@ -1237,21 +1181,40 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
 void
 SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+
+  UCHAR temp;
+
   /* Note: This variable is only used on 30xLV systems.
    * CR38 has a different meaning on LVDS/CH7019 systems.
    * On 661 and later, these bits moved to CR35.
+   *
+   * On 301, 301B, only HiVision 1080i is supported.
+   * On 30xLV, 301C, only YPbPr 1080i is supported.
    */
 
   SiS_Pr->SiS_YPbPr = 0;
-#ifdef SIS315H
-  if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	   SiS_Pr->SiS_YPbPr = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x38) >> 3);
+  if(HwInfo->jChipType >= SIS_661) return;
+
+  if(SiS_Pr->SiS_VBType) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	SiS_Pr->SiS_YPbPr = YPbPrHiVision;
+     }
+  }
+
+  if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
+        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	if(temp & 0x08) {
+	   switch((temp >> 4)) {
+	   case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
+	   case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
+	   case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
+	   case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
+	   }
 	}
      }
   }
-#endif /* SIS315H */
+
 }
 
 /*********************************************/
@@ -1290,7 +1253,7 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHOR
 	   if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
         }
         if(temp) {
-           if(romindex && ROMAddr && SiS_Pr->SiS_UseROM) {
+           if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
 	      OutputSelect = ROMAddr[romindex];
 	      if(!(OutputSelect & EnablePALMN)) {
                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
@@ -1312,8 +1275,8 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHOR
         }
 	/* Translate HiVision/YPbPr to our new flags */
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	   if(SiS_Pr->SiS_YPbPr == YPbPr750)           SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
-	   else if(SiS_Pr->SiS_YPbPr == YPbPr525)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+	   if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+	   else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
 	   else	if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
 	   else					       SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
 	   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
@@ -1387,6 +1350,22 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHOR
 	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 	   SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
 	}
+	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+	   if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+	      SiS_Pr->SiS_TVMode |= TVAspect169;
+	   } else {
+	      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+	      if(temp1 & 0x02) {
+		 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+		    SiS_Pr->SiS_TVMode |= TVAspect169;
+		 } else {
+		    SiS_Pr->SiS_TVMode |= TVAspect43LB;
+		 }
+	      } else {
+		 SiS_Pr->SiS_TVMode |= TVAspect43;
+	      }
+	   }
+	}
      }
   }
 
@@ -1396,6 +1375,7 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHOR
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
         SiS_Pr->SiS_TVMode |= TVSetPAL;
+	SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
         if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
 	   SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
@@ -1409,6 +1389,7 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHOR
      }
 
      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+        /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
         if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
            if(resinfo == SIS_RI_1024x768) {
               SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
@@ -1433,15 +1414,48 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHOR
   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
 
 #ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "(init301.c: TVMode %x)\n", SiS_Pr->SiS_TVMode);
+  xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
 #endif 
-
 }
 
 /*********************************************/
 /*               GET LCD INFO                */
 /*********************************************/
 
+static USHORT
+SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
+{
+   USHORT temp = SiS_Pr->SiS_LCDResInfo;
+   /* Translate my LCDResInfo to BIOS value */
+   if(temp == Panel_1280x768_2)  temp = Panel_1280x768;
+   if(temp == Panel_1280x768_3)  temp = Panel_1280x768;
+   return temp;
+}
+
+static void
+SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+#ifdef SIS315H
+   UCHAR  *ROMAddr;
+
+   if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+      SiS_Pr->PanelHT  = SISGETROMW(6);
+      SiS_Pr->PanelVT  = SISGETROMW(8);
+      SiS_Pr->PanelHRS = SISGETROMW(10);
+      SiS_Pr->PanelHRE = SISGETROMW(12);
+      SiS_Pr->PanelVRS = SISGETROMW(14);
+      SiS_Pr->PanelVRE = SISGETROMW(16);
+      SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)ROMAddr[18];
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+   }
+#endif
+}
+
 void
 SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 		  PSIS_HW_INFO HwInfo)
@@ -1457,49 +1471,57 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
          { 0,  1,  2,  3,  7,  4,  5,  8,
 	   0,  0, 10,  0,  0,  0,  0, 15 };
 
-  SiS_Pr->SiS_LCDResInfo = 0;
+  SiS_Pr->SiS_LCDResInfo  = 0;
   SiS_Pr->SiS_LCDTypeInfo = 0;
-  SiS_Pr->SiS_LCDInfo = 0;
+  SiS_Pr->SiS_LCDInfo     = 0;
+  SiS_Pr->PanelHRS        = 999; /* HSync start */
+  SiS_Pr->PanelHRE        = 999; /* HSync end */
+  SiS_Pr->PanelVRS        = 999; /* VSync start */
+  SiS_Pr->PanelVRE        = 999; /* VSync end */
 
-  if(SiS_Pr->UseCustomMode) {
+  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(ModeNo <= 0x13) {
-    	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
-
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 
-  if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
+  if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
+  } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
      SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
   } else {
      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
   }
   temp &= 0x0f;
   if(HwInfo->jChipType < SIS_315H) {
-      /* Translate 300 series LCDRes to 315 series for unified usage */
-      temp = SiS300SeriesLCDRes[temp];
+     /* Translate 300 series LCDRes to 315 series for unified usage */
+     temp = SiS300SeriesLCDRes[temp];
   }
-  SiS_Pr->SiS_LCDResInfo = temp;
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  if(HwInfo->jChipType == SIS_550) {
+     if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
+     if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
   }
 
-  if((!SiS_Pr->CP_HaveCustomData) || (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_PanelCustom)) {
-     if(SiS_Pr->SiS_LCDResInfo > SiS_Pr->SiS_PanelMax)
-  	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel1024x768;
-  }
+  if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	/* SiS LVDS */
+     if(temp == Panel310_1280x768) {
+        temp = Panel_1280x768_2;
+#ifdef SIS315H
+	if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+	   if((myptr[8] | (myptr[9] << 8)) == 798) temp = Panel_1280x768_3;
+	}
+#endif
+     }
+  } 
+
+  SiS_Pr->SiS_LCDResInfo = temp;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
@@ -1509,113 +1531,285 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
      }
   }
 
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  }
+
+  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+
   switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_800x600:   SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600; break;
-     case Panel_1024x768:  SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024; break;
-     case Panel_640x480_3:
+     case Panel_320x480:    SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelHT   =  400; SiS_Pr->PanelVT   =  525;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
      case Panel_640x480_2:
-     case Panel_640x480:   SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480; break;
-     case Panel_1024x600:  SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600; break;
-     case Panel_1152x864:  SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864; break;
-     case Panel_1280x960:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960; break;
-     case Panel_1152x768:  SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050; break;
-     case Panel_1280x768:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200; break;
-     case Panel_320x480:   SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480; break;
-     case Panel_Custom:    SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
-    			   SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
-			   break;
-     case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024; break;
-     case Panel_848x480:   SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480; break;
-     default:		   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768; break;
+     case Panel_640x480_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+     			    			      SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
+			    SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK40;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK40;
+			    break;
+     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
+     			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+     			    break;
+     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(HwInfo->jChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+			       			      SiS_Pr->PanelVRE  =    5;
+			    }
+			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(HwInfo->jChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+			       			      SiS_Pr->PanelVRE  =    5;
+			    }
+     			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+     			    break;
+     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
+     			    break;
+     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
+     			    SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
+			    SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
+			    SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
+			    /* Data above for TMDS (projector); get from BIOS for LVDS */
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
+			    break;
+     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   16; SiS_Pr->PanelHRE  =   64;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x768_3: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  798;
+			    SiS_Pr->PanelHRS   =  64; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS   =   3; SiS_Pr->PanelVRE  =    7;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_3;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
+     			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
+			    SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
+			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK69_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
+     			    SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
+		 	    if(resinfo == SIS_RI_1280x1024) {
+			       SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
+			       SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
+			    }
+			    break;
+     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112; /* HRE OK for LVDS, not for LCDA */
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
+     			    SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
+			    SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
+     			    SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
+    			    SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+			    SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
+			    SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
+			    if(SiS_Pr->CP_PreferredIndex != -1) {
+			       SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
+    			       SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
+			       SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
+			       SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
+			       SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
+			    }
+			    break;
+     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+     			    break;
+     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+     			    break;
+     default:		    SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    break;
   }
 
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-  if(HwInfo->jChipType < SIS_661) {
-     temp &= ~0xe;
-  } else {
+  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
+
+  if(!(SiS_Pr->UsePanelScaler))        SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+
 #ifdef SIS315H
-     if(!(temp & 0x10)) {
-        if(temp & 0x08) temp |= LCDPass11;
+  if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
-     temp &= ~0xe;
      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-        myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-        if(myptr) {
-           if(myptr[2] & 0x01) temp |= LCDDualLink;
-        }
+        if(SiS_Pr->SiS_ROMNew) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	} else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+           if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     }
+  } else if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
+     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
+        SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+        if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     }
+  }
 #endif
+
+  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+     /* Always center screen on LVDS (if scaling is disabled) */
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        /* Always center screen on SiS LVDS (if scaling is disabled) */
+        SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     } else {
+        /* By default, pass 1:1 on SiS TMDS (if scaling is disabled) */
+        SiS_Pr->SiS_LCDInfo |= LCDPass11;
+        if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     }
   }
-  SiS_Pr->SiS_LCDInfo = temp;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24 */
+        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
      }
   }
 
-  if(!(SiS_Pr->UsePanelScaler))        SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
-	   /* For non-standard LCD resolution, we let the panel scale */
-           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e) {
-	      /* We do not scale to 1280x960 (B/C bridges only) */
-              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	   if(((HwInfo->jChipType >= SIS_315H) && (ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25)) ||
-	      ((HwInfo->jChipType < SIS_315H)  && (ModeNo == 0x55 || ModeNo == 0x5a || ModeNo == 0x5b))) {
-	      /* We do not scale to 1280x768 (B/C bridges only) */
-              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	      /* No non-scaling data available for LV bridges */
-	      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-	   }
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-           /* No idea about the timing and zoom factors */
-           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
-	      /* We do not scale to 1280x1024 (all bridges) */
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-	      /* No idea about the timing and zoom factors (C bridge only) */
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	}
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-              if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	         SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-	      }
-	   }
+        switch(SiS_Pr->SiS_LCDResInfo) {
+        case Panel_Custom:
+		/* For non-standard LCD resolution, we let the panel scale */
+           	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		break;
+	case Panel_1280x720:
+	      	if(SiS_Pr->PanelHT == 1650) {
+		   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		}
+	case Panel_1280x768:	/* TMDS only */
+		/* No idea about the timing and zoom factors */
+           	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		break;
+	case Panel_1280x960:
+	 	SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+		break;
+	case Panel_1280x1024:
+	        if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+		   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
+		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
+		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16) {
+	      	      /* We do not scale to 1280x720/800/960 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+	           if(((HwInfo->jChipType >= SIS_315H) &&
+		       (ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25)) ||
+	              ((HwInfo->jChipType < SIS_315H)  &&
+		       (ModeNo == 0x55 || ModeNo == 0x5a || ModeNo == 0x5b))) {
+	              /* We do not scale to 1280x768 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+		}
+		break;
+	case Panel_1400x1050:
+		if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
+	      	   /* We do not scale to 1280x1024 (all bridges) */
+	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	   	}
+		break;
+	case Panel_1600x1200:
+		if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	      	   /* No idea about the timing and zoom factors (C bridge only) */
+	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	   	}
+		break;
 	}
      }
   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
-#ifdef SIS315H
-     if(HwInfo->jChipType < SIS_661) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) {
-           SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
-	   SiS_Pr->SiS_LCDInfo |= LCDPass11;
-	}
-     }
-#endif
-  } else {
 #ifdef SIS300
+  if(HwInfo->jChipType < SIS_315H) {
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+        if(SiS_Pr->SiS_UseROM) {
 	   if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
               if(!(ROMAddr[0x235] & 0x02)) {
 	         SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
@@ -1627,34 +1821,59 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
            SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
 	}
      }
+  }
 #endif
+
+  /* Special cases */
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
+
+  if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+     SiS_Pr->SiS_LCDInfo |= LCDPass11;
+  }
+
+  /* (In)validate LCDPass11 flag */
+  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
   }
 
-  /* Trumpion: Assume non-expanding */
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
-     SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+  /* Special cases */
+  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
+      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+     SiS_Pr->PanelHRS = 999;
+     SiS_Pr->PanelHRE = 999;
   }
 
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-     SiS_Pr->SiS_LCDInfo &= (~LCDPass11);
+  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+     SiS_Pr->PanelVRS = 999;
+     SiS_Pr->PanelVRE = 999;
   }
 
 #ifdef SIS315H
   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	/* Enable 302LV/302ELV dual link mode.
-	 * For 661, this is done above.
-	 */
-        if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)) {
-	   /* (Sets this in SenseLCD; new paneltypes) */
-	   SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
-        if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
-	   SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
+     if(!(SiS_Pr->SiS_ROMNew)) {
+        if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	   /* Enable 302LV/302ELV dual link mode.
+	    * For 661, this is done above.
+	    */
+           if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
+	      /* (Sets this in SenseLCD; new paneltypes) */
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+           if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+              (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+        }
      }
   }
 #endif
@@ -1662,37 +1881,37 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
   if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
 
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	   if(ModeNo > 0x13) {
-	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-                 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
-                    SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+	   if(ModeNo == 0x12) {
+	      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	         SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
+	   } else if(ModeNo > 0x13) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+	         if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	            if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+                       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+		    }
 		 }
-              }
-           }
-        }
-	if(ModeNo == 0x12) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	      SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
 	   }
 	}
      }
 
      if(modeflag & HalfDCLK) {
-        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-           if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-	      if(!(((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (HwInfo->jChipType < SIS_315H)) &&
-	                                      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480))) {
-                 if(ModeNo > 0x13) {
-                    if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-                       if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-                    } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-                       if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-                    }
-                 }
-	      } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-           } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-        } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+        } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(ModeNo > 0x13) {
+           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+              if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+           } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+              if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+           }
+	}
      }
 
   }
@@ -1705,14 +1924,6 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
   }
 
-  SiS_Pr->SiS_LCDInfo661 = 0;
-  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) SiS_Pr->SiS_LCDInfo661 |= 0x0001;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) SiS_Pr->SiS_LCDInfo661 |= 0x0002;
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11)     SiS_Pr->SiS_LCDInfo661 |= 0x0008;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) SiS_Pr->SiS_LCDInfo661 |= 0x0010;
-  SiS_Pr->SiS_LCDInfo661 |= (SiS_Pr->SiS_LCDInfo & 0xe0);
-  if(SiS_Pr->SiS_LCDInfo & LCDDualLink)   SiS_Pr->SiS_LCDInfo661 |= 0x0100;
-
 #ifdef LINUX_KERNEL
 #ifdef TWDEBUG
   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
@@ -1734,54 +1945,21 @@ USHORT
 SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx;
-  const USHORT LCDXlat0VCLK[4]    = {VCLK40,       VCLK40,       VCLK40,       VCLK40};
-  const USHORT LVDSXlat1VCLK[4]   = {VCLK40,       VCLK40,       VCLK40,       VCLK40};
-  const USHORT LVDSXlat4VCLK[4]   = {VCLK28,       VCLK28,       VCLK28,       VCLK28};
-#ifdef SIS300
-  const USHORT LCDXlat1VCLK300[4] = {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-  const USHORT LCDXlat2VCLK300[4] = {VCLK108_2_300,VCLK108_2_300,VCLK108_2_300,VCLK108_2_300};
-  const USHORT LVDSXlat2VCLK300[4]= {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-  const USHORT LVDSXlat3VCLK300[4]= {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-#endif
-#ifdef SIS315H
-  const USHORT LCDXlat1VCLK310[4] = {VCLK65_315,   VCLK65_315,   VCLK65_315,   VCLK65_315};
-  const USHORT LCDXlat2VCLK310[4] = {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
-  const USHORT LVDSXlat2VCLK310[4]= {VCLK65_315,   VCLK65_315,   VCLK65_315,   VCLK65_315};
-  const USHORT LVDSXlat3VCLK310[4]= {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
-#endif
-  USHORT CRT2Index,VCLKIndex=0;
-  USHORT modeflag,resinfo;
-  const UCHAR  *CHTVVCLKPtr = NULL;
-  const USHORT *LCDXlatVCLK1 = NULL;
-  const USHORT *LCDXlatVCLK2 = NULL;
-  const USHORT *LVDSXlatVCLK2 = NULL;
-  const USHORT *LVDSXlatVCLK3 = NULL;
-
-  if(HwInfo->jChipType >= SIS_315H) {
-#ifdef SIS315H
-     LCDXlatVCLK1 = LCDXlat1VCLK310;
-     LCDXlatVCLK2 = LCDXlat2VCLK310;
-     LVDSXlatVCLK2 = LVDSXlat2VCLK310;
-     LVDSXlatVCLK3 = LVDSXlat3VCLK310;
-#endif
-  } else {
-#ifdef SIS300
-     LCDXlatVCLK1 = LCDXlat1VCLK300;
-     LCDXlatVCLK2 = LCDXlat2VCLK300;
-     LVDSXlatVCLK2 = LVDSXlat2VCLK300;
-     LVDSXlatVCLK3 = LVDSXlat3VCLK300;
-#endif
-  }
+  USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
+  USHORT modeflag,resinfo,tempbx;
+  const UCHAR *CHTVVCLKPtr = NULL;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
      CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+     if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
   }
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
@@ -1789,50 +1967,18 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
         CRT2Index >>= 6;
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      /*  LCD */
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      	/*  LCD */
 
            if(HwInfo->jChipType < SIS_315H) {
-	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-	         VCLKIndex = LCDXlat0VCLK[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	         VCLKIndex = VCLK81_300;	/* guessed */
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-		 VCLKIndex = VCLK108_3_300;
-		 if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_300;
-	      } else {
-	    	 VCLKIndex = LCDXlatVCLK2[CRT2Index];
-	      }
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
 	   } else {
-	      if( (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) ||
-	          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-      	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-		    VCLKIndex = VCLK108_2_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-		    VCLKIndex = VCLK81_315;  	/* guessed */
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-		    VCLKIndex = VCLK108_2_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-		    VCLKIndex = VCLK162_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-		    VCLKIndex = VCLK108_3_315;
-		    if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-		    VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	         } else {
-		    VCLKIndex = LCDXlatVCLK2[CRT2Index];
-      	         }
-	      } else {
-                 VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));  /*  Port 3cch */
-         	 VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        	 if(ModeNo > 0x13) {
-          	    VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-        	 }
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	         VCLKIndex = VCLKIndexGEN;
+		 if(resinfo == SIS_RI_1280x720) VCLKIndex = VCLK_1280x720;
+		 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		    if(SiS_Pr->PanelHT == 1344) VCLKIndex = VCLK_1280x720_2;
+		 }
 		 if(ModeNo <= 0x13) {
 		    if(HwInfo->jChipType <= SIS_315PRO) {
 		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
@@ -1848,34 +1994,28 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
 	      }
 	   }
 
-        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /*  TV */
+        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 	/*  TV */
 
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
-     	      else                                  VCLKIndex = HiTVVCLK;
+              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) 		VCLKIndex = HiTVVCLKDIV2;
+     	      else                                  		VCLKIndex = HiTVVCLK;
               if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-            	 if(modeflag & Charx8Dot) 	    VCLKIndex = HiTVSimuVCLK;
-            	 else 			  	    VCLKIndex = HiTVTextVCLK;
+            	 if(modeflag & Charx8Dot) 	    		VCLKIndex = HiTVSimuVCLK;
+            	 else 			  	    		VCLKIndex = HiTVTextVCLK;
               }
-           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK - TVCLKBASE_315;
-	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   VCLKIndex = TVVCLKDIV2;
-	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)     VCLKIndex = TVVCLKDIV2;
-           else         		            	  VCLKIndex = TVVCLK;
+           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) 	VCLKIndex = YPbPr750pVCLK;
+	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   	VCLKIndex = TVVCLKDIV2;
+	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)     	VCLKIndex = TVVCLKDIV2;
+           else         		            	  	VCLKIndex = TVVCLK;
 
-	   if(HwInfo->jChipType < SIS_315H) {
-              VCLKIndex += TVCLKBASE_300;
-  	   } else {
-	      VCLKIndex += TVCLKBASE_315;
-	   }
+	   if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+  	   else 	                    VCLKIndex += TVCLKBASE_315;
 
-        } else {         					/* VGA2 */
+        } else {         						/* VGA2 */
 
-           VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-           VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-           if(ModeNo > 0x13) {
-              VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	      if(HwInfo->jChipType < SIS_315H) {
-          	 VCLKIndex &= 0x3f;
+	   VCLKIndex = VCLKIndexGEN;
+	   if(HwInfo->jChipType < SIS_315H) {
+              if(ModeNo > 0x13) {
 		 if( (HwInfo->jChipType == SIS_630) &&
 		     (HwInfo->jChipRevision >= 0x30)) {
 		    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
@@ -1888,12 +2028,9 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
 
      } else {   /* If not programming CRT2 */
 
-        VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-        VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        if(ModeNo > 0x13) {
-           VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	   if(HwInfo->jChipType < SIS_315H) {
-              VCLKIndex &= 0x3f;
+        VCLKIndex = VCLKIndexGEN;
+	if(HwInfo->jChipType < SIS_315H) {
+           if(ModeNo > 0x13) {
 	      if( (HwInfo->jChipType != SIS_630) &&
 		  (HwInfo->jChipType != SIS_300) ) {
 		 if(VCLKIndex == 0x1b) VCLKIndex = 0x35;
@@ -1906,7 +2043,7 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
 
      VCLKIndex = CRT2Index;
 
-     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {  /* programming CRT2 */
+     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
         if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
 
@@ -1942,32 +2079,16 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
 
         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
-	   VCLKIndex >>= 6;
-     	   if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) ||
-	      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480))
-     	      VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480   ||
-	           SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-		   SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)
-	      VCLKIndex = LVDSXlat4VCLK[VCLKIndex];
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
-     	      VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)
-              VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)
-              VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)
-	      VCLKIndex = VCLK68_315;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	      VCLKIndex = VCLK162_315;
-     	   else
-	      VCLKIndex = LVDSXlatVCLK3[VCLKIndex];
-
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-	      /* Special Timing: Barco iQ Pro R series */
-	      VCLKIndex = 0x44;
+	   if(HwInfo->jChipType < SIS_315H) {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
+	   } else {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
 	   }
 
+	   /* Special Timing: Barco iQ Pro R series */
+	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
+
+	   /* Special Timing: 848x480 parallel lvds */
 	   if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
 	      if(HwInfo->jChipType < SIS_315H) {
 		 VCLKIndex = VCLK34_300;
@@ -1980,28 +2101,22 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
 
         } else {
 
-	   VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-           VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-           if(ModeNo > 0x13) {
-              VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	      if(HwInfo->jChipType < SIS_315H) {
-    	 	 VCLKIndex &= 0x3F;
+	   VCLKIndex = VCLKIndexGEN;
+	   if(HwInfo->jChipType < SIS_315H) {
+              if(ModeNo > 0x13) {
+		 if( (HwInfo->jChipType == SIS_630) &&
+                     (HwInfo->jChipRevision >= 0x30) ) {
+		    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
+	         }
               }
-	      if( (HwInfo->jChipType == SIS_630) &&
-                  (HwInfo->jChipRevision >= 0x30) ) {
-		 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
-	      }
 	   }
         }
 
      } else {  /* if not programming CRT2 */
 
-        VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-        VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        if(ModeNo > 0x13) {
-           VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-           if(HwInfo->jChipType < SIS_315H) {
-	      VCLKIndex &= 0x3F;
+        VCLKIndex = VCLKIndexGEN;
+	if(HwInfo->jChipType < SIS_315H) {
+           if(ModeNo > 0x13) {
 	      if( (HwInfo->jChipType != SIS_630) &&
 	          (HwInfo->jChipType != SIS_300) ) {
 		 if(VCLKIndex == 0x1b) VCLKIndex = 0x35;
@@ -2045,12 +2160,10 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
   
   /* BIOS does not do this (neither 301 nor LVDS) */
@@ -2168,8 +2281,8 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
         }
 
         if((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301)) {
-	   if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)) {
+	   if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1280x960)) {
 	      tempah |= 0x80;
 	   }
         } else {
@@ -2196,9 +2309,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
        	   }
         }
 
-	if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)  ||
-	   ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) &&
+	if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	   (SiS_Pr->SiS_LCDResInfo == Panel_1280x960)  ||
+	   ((SiS_Pr->SiS_LCDResInfo == Panel_Custom) &&
 	    (SiS_Pr->CP_MaxX >= 1280) && (SiS_Pr->CP_MaxY >= 960))) {
 	   tempah |= 0x80;
         }
@@ -2336,7 +2449,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
 	}
 
-	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here */
+	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here (old BIOS) */
 
 #endif /* SIS315H */
 
@@ -2398,14 +2511,8 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 USHORT
 SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
 {
-  USHORT resindex;
-
-  if(ModeNo <= 0x13)
-     resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  else
-     resindex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
-  return(resindex);
+  if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+  else               return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
 }
 
 static void
@@ -2415,8 +2522,12 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,U
   USHORT xres,yres,modeflag=0,resindex;
 
   if(SiS_Pr->UseCustomMode) {
-     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = SiS_Pr->CHDisplay;
-     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+     xres = SiS_Pr->CHDisplay;
+     if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
+     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+     yres = SiS_Pr->CVDisplay;
+     if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
+     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
      return;
   }
 
@@ -2431,7 +2542,7 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,U
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if((!SiS_Pr->SiS_IF_DEF_DSTN) && (!SiS_Pr->SiS_IF_DEF_FSTN)) {
+  if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
 
      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
@@ -2442,72 +2553,64 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,U
         }
      }
 
-     if(ModeNo > 0x13) {
-  	if(modeflag & HalfDCLK)       xres *= 2;
-  	if(modeflag & DoubleScanMode) yres *= 2;
-     }
+     if(modeflag & HalfDCLK)       xres *= 2;
+     if(modeflag & DoubleScanMode) yres *= 2;
 
   }
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
            if(xres == 720) xres = 640;
-	} else {
-	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {           /* 301BDH */
-	        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-                   if(xres == 720) xres = 640;
-		}
-		if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	           yres = 400;
-	           if(HwInfo->jChipType >= SIS_315H) {
-	              if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	           } else {
-	              if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	           }
-	        }
-	   } else {
-	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-	         if(xres == 720) xres = 640;
-	      }
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-		    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        	       if(yres == 1024) yres = 1056;
-      		    }
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-		    if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		       /* BIOS bug - does this regardless of scaling */
-      		       if(yres == 400) yres = 405;
-		    }
-      		    if(yres == 350) yres = 360;
-      		    if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-        	       if(yres == 360) yres = 375;
-      		    }
-   	         } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-      		    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        	       if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-          	          if(yres == 350) yres = 357;
-          	          if(yres == 400) yres = 420;
-            	          if(yres == 480) yres = 525;
-        	       }
-      		    }
-    	         }
+	}
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   switch(SiS_Pr->SiS_LCDResInfo) {
+	   case Panel_1024x768:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+          	    if(yres == 350) yres = 357;
+          	    if(yres == 400) yres = 420;
+            	    if(yres == 480) yres = 525;
+        	 }
+      	      }
+	      break;
+	   case Panel_1280x1024:
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		 /* BIOS bug - does this regardless of scaling */
+      		 if(yres == 400) yres = 405;
 	      }
+      	      if(yres == 350) yres = 360;
+      	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+                 if(yres == 360) yres = 375;
+      	      }
+	      break;
+	   case Panel_1600x1200:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        	 if(yres == 1024) yres = 1056;
+      	      }
+	      break;
 	   }
 	}
+
   } else {
-    	if(xres == 720) xres = 640;
-	if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	   yres = 400;
-	   if(HwInfo->jChipType >= SIS_315H) {
-	      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	   } else {
-	      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	   }
-	   if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-	      yres = 480;
-	   }
+
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+           if(xres == 720) xres = 640;
 	}
+     } else if(xres == 720) xres = 640;
+
+     if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+	yres = 400;
+        if(HwInfo->jChipType >= SIS_315H) {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+        } else {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+        }
+        if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN)  yres = 480;
+     }
+
   }
   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
@@ -2522,103 +2625,84 @@ SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, 
 		   USHORT RefreshRateTableIndex, USHORT *ResIndex,
 		   USHORT *DisplayType)
  {
-  USHORT tempbx,modeflag=0;
-  USHORT Flag,CRT2CRTC;
+  USHORT modeflag=0;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
      }
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))    return FALSE;
   } else
      return FALSE;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     CRT2CRTC = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     CRT2CRTC = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
-  Flag = 1;
-  tempbx = 0;
-  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-        Flag = 0;
-        tempbx = 18;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-      	   tempbx += 2;
-	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
-	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	   }
-	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-	      tempbx = 18;  /* PALM uses NTSC data */
-	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	   } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-	      tempbx = 20;  /* PALN uses PAL data  */
-	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	   }
-        }
+  (*ResIndex) &= 0x3F;
+
+  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+     (*DisplayType) = 18;
+     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+      	(*DisplayType) += 2;
+	if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	   if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
+	}
+	if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	   (*DisplayType) = 18;  /* PALM uses NTSC data */
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+	} else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	   (*DisplayType) = 20;  /* PALN uses PAL data  */
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+	}
+     }
+  } else {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:   (*DisplayType) = 50; break;
+     case Panel_640x480_2: (*DisplayType) = 52; break;
+     case Panel_640x480_3: (*DisplayType) = 54; break;
+     case Panel_800x600:   (*DisplayType) =  0; break;
+     case Panel_1024x600:  (*DisplayType) = 23; break;
+     case Panel_1024x768:  (*DisplayType) =  4; break;
+     case Panel_1152x768:  (*DisplayType) = 27; break;
+     case Panel_1280x768:  (*DisplayType) = 40; break;
+     case Panel_1280x1024: (*DisplayType) =  8; break;
+     case Panel_1400x1050: (*DisplayType) = 14; break;
+     case Panel_1600x1200: (*DisplayType) = 36; break;
+     default: return FALSE;
      }
-  }
-  if(Flag) {
-     tempbx = SiS_Pr->SiS_LCDResInfo;
-     tempbx -= SiS_Pr->SiS_PanelMinLVDS;
-     if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 6;
-        if(modeflag & HalfDCLK) tempbx += 3;
-     } else {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-           tempbx = 14;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-           tempbx = 23;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-           tempbx = 27;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-           tempbx = 36;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-           tempbx = 40;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-           tempbx = 54;
-	   if(modeflag & HalfDCLK) tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
-           tempbx = 52;
-	   if(modeflag & HalfDCLK) tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-           tempbx = 50;
-	   if(modeflag & HalfDCLK) tempbx++;
-        }
 
+     if(modeflag & HalfDCLK) (*DisplayType)++;
+
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+     case Panel_640x480_2:
+     case Panel_640x480_3:
+        break;
+     default:
+        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
      }
+
      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        tempbx = 12;
-	if(modeflag & HalfDCLK) tempbx++;
+        (*DisplayType) = 12;
+	if(modeflag & HalfDCLK) (*DisplayType)++;
      }
   }
 
 #if 0
   if(SiS_Pr->SiS_IF_DEF_FSTN) {
      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
-        tempbx = 22;
+        (*DisplayType) = 22;
      }
   }
 #endif
 
-  *ResIndex = CRT2CRTC & 0x3F;
-  *DisplayType = tempbx;
   return TRUE;
 }
 
@@ -2627,8 +2711,7 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
 	       USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
 	       PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx=0,tempal=0;
-  USHORT Flag,resinfo=0;
+  USHORT tempbx=0,tempal=0,resinfo=0;
 
   if(ModeNo <= 0x13) {
      tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2641,55 +2724,30 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
 
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-	   tempbx = 15;
-  	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   tempbx = 20;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 21;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 22;
- 	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   tempbx = 23;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 24;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 25;
-#if 0
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	   tempbx = 26;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 27;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 28;
-#endif
- 	} else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)       tempbx = 13;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 14;
-	      else {
-	         tempbx = 29;
-		 if(ModeNo >= 0x13) {
-	            /* see below */
-	            if(resinfo == SIS_RI_1280x960) tempal = 10;
-	         }
-              }
-	   } else {
-	      tempbx = 29;
-	      if(ModeNo >= 0x13) {
-	         /* 1280x768 and 1280x960 have same CRT2CRTC,
-	          * so we change it here if 1280x960 is chosen
-	          */
-	         if(resinfo == SIS_RI_1280x960) tempal = 10;
+        tempbx = SiS_Pr->SiS_LCDResInfo;
+	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
+
+  	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {  /* Pass 1:1 only (center-screen handled outside) */
+	   tempbx = 100;
+	   if(ModeNo >= 0x13) {
+	      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+	      if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	         (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  768)) {
+	         /* Special for Fujitsu 7911 (VL-17WDX8), others custom */
+	         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768)        tempal = 0x08;
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_2) tempal = 0x0f;
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_3) tempal = 0x10;
 	      }
-   	   }
-	} else {
-      	   tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_Panel1024x768;
-      	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-              tempbx += 10;
-       	   }
+	   }
 	}
 
 #ifdef SIS315H
 	if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	      tempbx = 50;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 51;
-	      else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 52;
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	         tempbx = 200;
+	         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+	      }
 	   }
 	}
 #endif
@@ -2697,10 +2755,11 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
      } else {						  	/* TV */
 
      	if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-           if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode);
+           /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
            tempbx = 2;
            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 13;
+	      tempbx = 13;
+              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
            }
 	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 	   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
@@ -2727,9 +2786,14 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
 	   }
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-	         if(resinfo == SIS_RI_1024x768) {
+	         if(resinfo == SIS_RI_1024x768) tempal = 8;
+	      }
+	      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+		 if((resinfo == SIS_RI_720x576) ||
+	            (resinfo == SIS_RI_768x576)) {
 	            tempal = 8;
 	         }
+		 if(resinfo == SIS_RI_1280x720) tempal = 9;
 	      }
 	   }
 	}
@@ -2740,70 +2804,54 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
 
   } else {   /* LVDS, 301B-DH (if running on LCD) */
 
-     Flag = 1;
      tempbx = 0;
-     if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-           Flag = 0;
-           tempbx = 10;
-	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	      tempbx += 2;
-	      if(SiS_Pr->SiS_ModeType > ModeVGA) {
-		 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	      }
-	      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-		 tempbx = 90;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-		 tempbx = 92;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      }
-           }
-        }
-     }
-
-     if(Flag) {
-
-	if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
-	   tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_PanelMinLVDS;
-   	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 3;
-
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	      tempbx = 82;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+        tempbx = 10;
+	if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	   tempbx += 2;
+	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
 	   }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	   tempbx = 18;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-	   tempbx = 6;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
-	   tempbx = 30;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-	   tempbx = 30;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	   tempbx = 15;
-  	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 2;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-	   tempbx = 16;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 2;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   tempbx = 8;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   tempbx = 21;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelBarco1366) {
-	   tempbx = 80;
-   	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	      tempbx = 90;
+	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	      tempbx = 92;
+	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   }
+        }
+     } else {
+        switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:   tempbx = 6;  break;
+	case Panel_640x480_2: tempbx = 30; break;
+	case Panel_640x480_3: tempbx = 30; break;
+	case Panel_800x600:   tempbx = 0;  break;
+	case Panel_1024x600:  tempbx = 15; break;
+	case Panel_1024x768:  tempbx = 2;  break;
+	case Panel_1152x768:  tempbx = 17; break;
+	case Panel_1280x768:  tempbx = 18; break;
+	case Panel_1280x1024: tempbx = 4;  break;
+	case Panel_1400x1050: tempbx = 8;  break;
+	case Panel_1600x1200: tempbx = 21; break;
+	case Panel_Barco1366: tempbx = 80; break;
+	}
+
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:
+	case Panel_640x480_2:
+	case Panel_640x480_3:
+	   break;
+	default:
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
 	}
 
-	if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	   tempbx = 7;
-        }
+	if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
 
-	if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+	if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+	   tempbx = 82;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+	} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
 	   tempbx = 84;
 	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
 	}
@@ -2811,45 +2859,17 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
      }
 
      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempal = 7;
+        if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempal = 7;
   	if(HwInfo->jChipType < SIS_315H) {
 	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++;
 	}
      }
 
-     *CRT2Index = tempbx;
-     *ResIndex = tempal & 0x1F;
+     (*CRT2Index) = tempbx;
+     (*ResIndex) = tempal & 0x1F;
   }
 }
 
-#ifdef SIS315H
-static void
-SiS_GetCRT2PtrA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-		USHORT RefreshRateTableIndex,USHORT *CRT2Index,
-		USHORT *ResIndex)
-{
-  USHORT tempbx,tempal;
-
-  tempbx = SiS_Pr->SiS_LCDResInfo;
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)      tempbx = 4;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempbx = 3;
-  else tempbx -= SiS_Pr->SiS_Panel1024x768;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 5;
-
-  if(ModeNo <= 0x13)
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  /* No customs required yet (Clevo, Compaq, etc) */
-
-  *CRT2Index = tempbx;
-  *ResIndex = tempal & 0x1F;
-}
-#endif
-
 static void
 SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
                    USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
@@ -2910,8 +2930,7 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,U
 
 static void
 SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                    USHORT RefreshRateTableIndex,
-		    PSIS_HW_INFO HwInfo)
+                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
    USHORT CRT2Index, ResIndex;
    const SiS_LVDSDataStruct *LVDSData = NULL;
@@ -2929,23 +2948,55 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,
       SiS_Pr->SiS_RY4COE = 0;
    }
 
-   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-      SiS_GetCRT2PtrA(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                      &CRT2Index,&ResIndex);
-
-      switch (CRT2Index) {
-      	case  0:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_1;    break;
-      	case  1:  LVDSData = SiS_Pr->SiS_LCDA1280x1024Data_1;   break;
-	case  3:  LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_1;   break;
-	case  4:  LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_1;   break;
-      	case  5:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_2;    break;
-      	case  6:  LVDSData = SiS_Pr->SiS_LCDA1280x1024Data_2;   break;
-	case  8:  LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_2;   break;
-	case  9:  LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_2;   break;
-	default:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_1;    break;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	    if(SiS_Pr->UseCustomMode) {
+	       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
+	       SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+	    } else {
+	       if(ModeNo < 0x13) {
+	          ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	       } else {
+	          ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+		  /* Special for our 3 types, others custom (works with default) */
+		  if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	             (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  768)) {
+	             if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768)        ResIndex = 0x08;
+		     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_2) ResIndex = 0x0f;
+		     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_3) ResIndex = 0x10;
+	          }
+		  /* Special for 1280x720 TMDS <> LVDS */
+		  if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	             (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  720)) {
+		     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		        if(SiS_Pr->PanelHT == 1344) ResIndex = 0x12;
+		     }
+	          }
+	       }
+	       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+               SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+               SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+               SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+	    }
+	 } else {
+     	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+	 }
+      } else {
+	 /* This handles custom modes and custom panels */
+	 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+         SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
+         SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
+	 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+	 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
       }
+
+      SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
+
 #endif
 
    } else {
@@ -2956,7 +3007,7 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,
       }
 
       SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                     &CRT2Index, &ResIndex, HwInfo);
+                     		&CRT2Index, &ResIndex, HwInfo);
 
       /* 301BDH needs LVDS Data */
       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
@@ -2964,72 +3015,59 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,
       }
 
       switch (CRT2Index) {
-      	case  0:  LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
-      	case  1:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-      	case  2:  LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
-      	case  3:  LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
-      	case  4:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
-      	case  5:  LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
-	case  6:  LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
-        case  7:  LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
-	case  8:  LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
-	case  9:  LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
-      	case 10:  LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
-      	case 11:  LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
-      	case 12:  LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
-      	case 13:  LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
-      	case 14:  LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
-	case 15:  LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
-	case 16:  LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
-	case 17:  LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
-	case 18:  LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
-	case 19:  LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
-	case 20:  LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
-	case 21:  LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
-	case 22:  LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
-	case 30:  LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
-	case 80:  LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
-	case 81:  LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
-	case 82:  LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
-	case 83:  LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
-	case 84:  LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
-	case 85:  LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
-	case 90:  LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
-      	case 91:  LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
-      	case 92:  LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
-      	case 93:  LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
-	case 99:  LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;  /* Super Overscan */
-	default:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-      }
-   }
-
-   SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
-   SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
-   SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
-   SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-         SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-      }
+      	 case  0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
+	 case  1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
+      	 case  2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+	 case  3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
+      	 case  4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
+      	 case  5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
+	 case  6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
+         case  7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
+	 case  8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
+	 case  9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
+      	 case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
+      	 case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
+      	 case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
+      	 case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
+      	 case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
+	 case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
+	 case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
+	 case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
+	 case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
+	 case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
+	 case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
+	 case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
+	 case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
+	 case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
+	 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
+	 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
+	 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
+	 case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
+	 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
+	 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
+	 case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
+      	 case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
+      	 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
+      	 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
+	 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;  /* Super Overscan */
+	 default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+      }
+
+      SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+      SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+      SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
+      SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
 
-   } else {
-
-      if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+      if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-            if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-               if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-	          SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-                  SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-
-	 	  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-		     if(ResIndex < 0x08) {
-		        SiS_Pr->SiS_HDE = 1280;
-                        SiS_Pr->SiS_VDE = 1024;
-		     }
-		  }
+            if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+	       SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+               SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+	       if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+		  if(ResIndex < 0x08) {
+		     SiS_Pr->SiS_HDE = 1280;
+                     SiS_Pr->SiS_VDE = 1024;
+                  }
                }
             }
          }
@@ -3051,14 +3089,12 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
   
   SiS_Pr->SiS_NewFlickerMode = 0;
@@ -3086,6 +3122,7 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
      } else {
 
         SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -3094,19 +3131,20 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
                     &CRT2Index,&ResIndex,HwInfo);
 
      switch(CRT2Index) {
-       case  2:  TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
-       case  3:  TVPtr = SiS_Pr->SiS_ExtPALData;    break;
-       case  4:  TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
-       case  5:  TVPtr = SiS_Pr->SiS_Ext525iData;   break;
-       case  6:  TVPtr = SiS_Pr->SiS_Ext525pData;   break;
-       case  7:  TVPtr = SiS_Pr->SiS_Ext750pData;   break;
-       case  8:  TVPtr = SiS_Pr->SiS_StPALData;     break;
-       case  9:  TVPtr = SiS_Pr->SiS_StNTSCData;    break;
-       case 10:  TVPtr = SiS_Pr->SiS_St525iData;    break;
-       case 11:  TVPtr = SiS_Pr->SiS_St525pData;    break;
-       case 12:  TVPtr = SiS_Pr->SiS_St750pData;    break;
-       case 14:  TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
-       default:  TVPtr = SiS_Pr->SiS_StPALData;     break;
+        case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
+        case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
+        case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
+        case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
+        case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
+        case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
+        case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
+        case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
+        case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
+        case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
+        case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
+        case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
+        case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
+        default: TVPtr = SiS_Pr->SiS_StPALData;     break;
      }
 
      SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
@@ -3123,9 +3161,11 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-        if(resinfo == SIS_RI_1024x768)  SiS_Pr->SiS_NewFlickerMode = 0x40;
-        if(resinfo == SIS_RI_1280x1024) SiS_Pr->SiS_NewFlickerMode = 0x40;
-        if(resinfo == SIS_RI_1280x720)  SiS_Pr->SiS_NewFlickerMode = 0x40;
+        if((resinfo == SIS_RI_1024x768)  ||
+           (resinfo == SIS_RI_1280x1024) ||
+           (resinfo == SIS_RI_1280x720)) {
+	   SiS_Pr->SiS_NewFlickerMode = 0x40;
+	}
 
         if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
 
@@ -3135,10 +3175,12 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
               SiS_Pr->SiS_HT = StHiTVHT;
               SiS_Pr->SiS_VT = StHiTVVT;
+#if 0
               if(!(modeflag & Charx8Dot)) {
                  SiS_Pr->SiS_HT = StHiTextTVHT;
                  SiS_Pr->SiS_VT = StHiTextTVVT;
               }
+#endif
            }
         }
 
@@ -3183,10 +3225,11 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
+     SiS_Pr->SiS_RVBHCMAX  = 1;
+     SiS_Pr->SiS_RVBHCFACT = 1;
+
      if(SiS_Pr->UseCustomMode) {
 
-        SiS_Pr->SiS_RVBHCMAX  = 1;
-        SiS_Pr->SiS_RVBHCFACT = 1;
         SiS_Pr->SiS_VGAHT     = SiS_Pr->CHTotal;
         SiS_Pr->SiS_VGAVT     = SiS_Pr->CVTotal;
         SiS_Pr->SiS_HT        = SiS_Pr->CHTotal;
@@ -3196,58 +3239,68 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
 
      } else {
 
-        SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                      &CRT2Index,&ResIndex,HwInfo);
+        if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+
+           SiS_Pr->SiS_VGAHT     = SiS_Pr->PanelHT;
+           SiS_Pr->SiS_VGAVT     = SiS_Pr->PanelVT;
+           SiS_Pr->SiS_HT        = SiS_Pr->PanelHT;
+           SiS_Pr->SiS_VT        = SiS_Pr->PanelVT;
+
+	} else {
+
+           SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+                          &CRT2Index,&ResIndex,HwInfo);
 
-        switch(CRT2Index) {
-         case  0: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;        break; /* VESA Timing */
-         case  1: LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;       break; /* VESA Timing */
-         case  5: LCDPtr = SiS_Pr->SiS_StLCD1024x768Data;         break; /* Obviously unused */
-         case  6: LCDPtr = SiS_Pr->SiS_StLCD1280x1024Data;        break; /* Obviously unused */
-         case 10: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;        break; /* Non-VESA Timing */
-         case 11: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;       break; /* Non-VESA Timing */
-         case 13: LCDPtr = SiS_Pr->SiS_NoScaleData1024x768;       break; /* Non-expanding */
-         case 14: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024;      break; /* Non-expanding */
-         case 15: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;           break; /* 1280x960 */
-         case 20: LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;       break; /* VESA Timing */
-         case 21: LCDPtr = SiS_Pr->SiS_NoScaleData1400x1050;      break; /* Non-expanding (let panel scale) */
-         case 22: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;        break; /* Non-VESA Timing (let panel scale) */
-         case 23: LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;       break; /* VESA Timing */
-         case 24: LCDPtr = SiS_Pr->SiS_NoScaleData1600x1200;      break; /* Non-expanding */
-         case 25: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;        break; /* Non-VESA Timing */
-         case 26: LCDPtr = SiS_Pr->SiS_ExtLCD1280x768Data;        break; /* VESA Timing */
-         case 27: LCDPtr = SiS_Pr->SiS_NoScaleData1280x768;       break; /* Non-expanding */
-         case 28: LCDPtr = SiS_Pr->SiS_StLCD1280x768Data;         break; /* Non-VESA Timing */
-         case 29: LCDPtr = SiS_Pr->SiS_NoScaleData;	          break; /* Generic no-scale data */
-#ifdef SIS315H
-	 case 50: LCDPtr = (SiS_LCDDataStruct *)SiS310_ExtCompaq1280x1024Data;	break;
-	 case 51: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024;			break;
-	 case 52: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;	  		break;
-#endif
-         default: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;	  break;
-        }
-
-        SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
-        SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
-        SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
-        SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
-        SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
-        SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+           switch(CRT2Index) {
+	      case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+	      case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
+	      case Panel_1280x720      :
+	      case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
+	      case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
+              case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
+	      case Panel_1280x768_3    :
+	      case Panel_1280x768_3+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x768_3Data;    break;
+	      case Panel_1280x800      :
+	      case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
+	      case Panel_1280x960      :
+	      case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
+              case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
+              case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+              case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
+              case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
+              case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
+              case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
+	      case Panel_1680x1050     :
+	      case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
+	      case 100		       : LCDPtr = SiS_Pr->SiS_NoScaleData;	    break;
+#ifdef SIS315H
+	      case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
+	      case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+#endif
+              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+           }
 
 #ifdef TWDEBUG
-        xf86DrvMsg(0, X_INFO,
-    	    "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+           xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
 #endif
 
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-           tempax = 1024;
+           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
+           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
+           SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
+           SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
+           SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+
+        }
+
+	tempax = SiS_Pr->PanelXRes;
+        tempbx = SiS_Pr->PanelYRes;
+
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
            if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
               if(HwInfo->jChipType < SIS_315H) {
                  if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
                  else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-                 else                               tempbx = 768;
-              } else {
-                 tempbx = 768;
               }
            } else {
               if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
@@ -3256,43 +3309,27 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
               else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
               else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
               else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-              else                               tempbx = 768;
            }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-           tempax = 1280;
-           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
-           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
-           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
-           else                               tempbx = 1024;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-           tempax = 1280;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
            if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
            else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
            else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
-           else                                tempbx = 960;
-	} else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) &&
-	          (HwInfo->jChipType >= SIS_661)) {
-	   tempax = 1400;
-	   tempbx = 1050;
-	   if(SiS_Pr->SiS_VGAVDE == 1024) {
-	      tempax = 1280;
-	      tempbx = 1024;
-	   }
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-           tempax = 1600;
-	   tempbx = 1200;
-	   if((HwInfo->jChipType < SIS_661) || (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))) {
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+        } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
+	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
               if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
               else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
            }
-        } else {
-	   tempax = SiS_Pr->PanelXRes;
-           tempbx = SiS_Pr->PanelYRes;
-	}
+        }
+
         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
            tempax = SiS_Pr->SiS_VGAHDE;
            tempbx = SiS_Pr->SiS_VGAVDE;
         }
+
         SiS_Pr->SiS_HDE = tempax;
         SiS_Pr->SiS_VDE = tempbx;
      }
@@ -3306,31 +3343,15 @@ SiS_GetCRT2Data(SiS_Private *SiS_Pr, USH
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-           SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-        } else {
-
-	   if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-
-	      /* Need LVDS Data for LCD on 301B-DH */
-	      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-	   } else {
-
-	      SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-           }
-
-        }
-
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
      } else {
-
-     	SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
+	if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	   /* Need LVDS Data for LCD on 301B-DH */
+	   SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+	} else {
+	   SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+        }
      }
 
   } else {
@@ -3341,7 +3362,7 @@ SiS_GetCRT2Data(SiS_Private *SiS_Pr, USH
 }
 
 /*********************************************/
-/*            GET LVDS DES DATA              */
+/*         GET LVDS DES (SKEW) DATA          */
 /*********************************************/
 
 static void
@@ -3349,106 +3370,55 @@ SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, U
                   USHORT RefreshRateTableIndex, USHORT *PanelIndex,
 		  USHORT *ResIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx,tempal,modeflag;
+  USHORT modeflag;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
-  tempbx = 0;
+  (*ResIndex) &= 0x1F;
+  (*PanelIndex) = 0;
+
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        tempbx = 50;
-        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) tempbx += 2;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+        (*PanelIndex) = 50;
+        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
         /* Nothing special needed for SOverscan    */
-        /*     PALM uses NTSC data, PALN uses PAL data */
+        /* PALM uses NTSC data, PALN uses PAL data */
      }
   }
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     tempbx = SiS_Pr->SiS_LCDTypeInfo;
+     *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
      if(HwInfo->jChipType >= SIS_661) {
         /* As long as we don's use the BIOS tables, we
 	 * need to convert the TypeInfo as for 315 series
 	 */
-        tempbx = SiS_Pr->SiS_LCDResInfo - 1;
+        (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
      }
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 16;
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        tempbx = 32;
-        if(modeflag & HalfDCLK) tempbx++;
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        (*PanelIndex) += 16;
+        if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+           (*PanelIndex) = 32;
+           if(modeflag & HalfDCLK) (*PanelIndex)++;
+	}
      }
   }
 
   if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  {
-        tempal = 0x07;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
+        (*ResIndex) = 7;
         if(HwInfo->jChipType < SIS_315H) {
-           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++;
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
         }
      }
   }
-
-  *PanelIndex = tempbx;
-  *ResIndex = tempal & 0x1F;
-}
-
-#ifdef SIS315H
-static void
-SiS_GetLVDSDesPtrA(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex, USHORT *PanelIndex, USHORT *ResIndex,
-		   PSIS_HW_INFO HwInfo)
-{
-  USHORT tempbx=0,tempal;
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)      tempbx = 2;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 3;
-  else tempbx = SiS_Pr->SiS_LCDResInfo - 2;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 4;
-
-  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-	   tempbx = 80;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-	}
-     }
-  }
-  if((SiS_Pr->SiS_CustomT == CUT_UNIWILL1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_UNIWILL10242)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	tempbx = 82;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	tempbx = 84;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	tempbx = 86;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-
-  if(ModeNo <= 0x13)
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  *PanelIndex = tempbx;
-  *ResIndex = tempal & 0x1F;
 }
-#endif
 
 static void
 SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
@@ -3458,39 +3428,43 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, 
   USHORT PanelIndex,ResIndex;
   const  SiS_LVDSDesStruct *PanelDesPtr = NULL;
 
-  if((SiS_Pr->UseCustomMode) ||
-     (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
-     SiS_Pr->SiS_LCDHDES = 0;
-     SiS_Pr->SiS_LCDVDES = 0;
+  SiS_Pr->SiS_LCDHDES = 0;
+  SiS_Pr->SiS_LCDVDES = 0;
+
+  if( (SiS_Pr->UseCustomMode) 		         ||
+      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
+      ((SiS_Pr->SiS_VBType & VB_SISVB) &&
+       (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
+       (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
      return;
   }
 
   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-     SiS_GetLVDSDesPtrA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                        &PanelIndex, &ResIndex, HwInfo);
-
-     switch (PanelIndex)
-     {
-     	case  0: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1;   break;  /* --- expanding --- */
-     	case  1: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_1;  break;
-	case  2: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_1;  break;
-	case  3: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_1;  break;
-     	case  4: PanelDesPtr = SiS_Pr->LVDS1024x768Des_2;   break;  /* --- non expanding --- */
-     	case  5: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_2;  break;
-	case  6: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_2;  break;
-	case  7: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_2;  break;
-	case 80: PanelDesPtr = (SiS_LVDSDesStruct *)Clevo1024x768Des_1;   break;  /*  custom  */
-	case 81: PanelDesPtr = (SiS_LVDSDesStruct *)Clevo1024x768Des_2;   break;
-	case 82: PanelDesPtr = (SiS_LVDSDesStruct *)Uniwill1024x768Des_1; break;
-	case 83: PanelDesPtr = (SiS_LVDSDesStruct *)Uniwill1024x768Des_2; break;
-	case 84: PanelDesPtr = (SiS_LVDSDesStruct *)Compaq1280x1024Des_1; break;
-	case 85: PanelDesPtr = (SiS_LVDSDesStruct *)Compaq1280x1024Des_2; break;
-	case 86: PanelDesPtr = (SiS_LVDSDesStruct *)Asus1024x768Des_1;    break;  /*  custom  */
-	case 87: PanelDesPtr = (SiS_LVDSDesStruct *)Asus1024x768Des_2;    break;
-	default: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1;   break;
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        /* non-pass 1:1 only, see above */
+        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+	}
+     }
+     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+        switch(SiS_Pr->SiS_CustomT) {
+        case CUT_UNIWILL1024:
+        case CUT_UNIWILL10242:
+        case CUT_CLEVO1400:
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	   break;
+	}
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	}
      }
 #endif
 
@@ -3499,87 +3473,68 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, 
      SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
                        &PanelIndex, &ResIndex, HwInfo);
 
-     switch (PanelIndex)
-     {
-     	case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;   break;   /* ---  */
-     	case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;   break;
-     	case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;   break;
-     	case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;   break;
-     	case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;   break;
-     	case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;   break;
-     	case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;   break;
-     	case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;   break;
-     	case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;   break;
-     	case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;   break;
-     	case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;   break;
-     	case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;   break;
-     	case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;   break;
-     	case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;   break;
-     	case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;   break;
-     	case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;   break;
-     	case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;   break;    /* --- */
-     	case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;   break;
-     	case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;   break;
-     	case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;   break;
-     	case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;   break;
-     	case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;   break;
-     	case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;   break;
-     	case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;   break;
-     	case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;   break;
-     	case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;   break;
-     	case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;   break;
-     	case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;   break;
-     	case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;   break;
-     	case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;   break;
-     	case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;   break;
-     	case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;   break;
-	case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;   break;    /* pass 1:1 */
-	case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;   break;
-     	case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData;   break; /* TV */
-     	case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData;   break;
-     	case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;    break;
-     	case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;    break;
-	default:
-		 if(HwInfo->jChipType < SIS_315H)
-		    PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;
-		 else
-		    PanelDesPtr = SiS_Pr->SiS_PanelType01_1;
-		 break;
-     }
-  }
-  SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
-  SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD){
-     if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-        if(ModeNo <= 0x13) {
-           modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	   if(!(modeflag & HalfDCLK)) {
-	      SiS_Pr->SiS_LCDHDES = 632;
-	   }
-        }
-     } else {
-        if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) {
-              if(SiS_Pr->SiS_LCDResInfo >= SiS_Pr->SiS_Panel1024x768) {
-                 if(ModeNo <= 0x13) {
-	            modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	            if(HwInfo->jChipType < SIS_315H) {
-	               if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
-	            } else {
-	               if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
-	                  SiS_Pr->SiS_LCDHDES = 480;
-                       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)
-	                  SiS_Pr->SiS_LCDHDES = 804;
-		       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	                  SiS_Pr->SiS_LCDHDES = 704;
-                       if(!(modeflag & HalfDCLK)) {
-                          SiS_Pr->SiS_LCDHDES = 320;
-	                  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)
-	                     SiS_Pr->SiS_LCDHDES = 632;
-		          else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	                     SiS_Pr->SiS_LCDHDES = 542;
-                       }
+     switch(PanelIndex) {
+     	case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;    break;   /* ---  */
+     	case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;    break;
+     	case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;    break;
+     	case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;    break;
+     	case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;    break;
+     	case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;    break;
+     	case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;    break;
+     	case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;    break;
+     	case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;    break;
+     	case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;    break;
+     	case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;    break;
+     	case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;    break;
+     	case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;    break;
+     	case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;    break;
+     	case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;    break;
+     	case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;    break;
+     	case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;    break;    /* --- */
+     	case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;    break;
+     	case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;    break;
+     	case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;    break;
+     	case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;    break;
+     	case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;    break;
+     	case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;    break;
+     	case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;    break;
+     	case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;    break;
+     	case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;    break;
+     	case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;    break;
+     	case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;    break;
+     	case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;    break;
+     	case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;    break;
+     	case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;    break;
+     	case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;    break;
+	case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;    break;    /* pass 1:1 */
+	case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;    break;
+     	case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break;    /* TV */
+     	case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
+     	case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;  break;
+     	case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;  break;
+	default: return;
+     }
+
+     SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+     SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+        if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	   if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
+        } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+              if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+	         if(HwInfo->jChipType < SIS_315H) {
+	            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
+	         } else {
+	            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
+                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+		    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
+                    if(!(modeflag & HalfDCLK)) {
+                       SiS_Pr->SiS_LCDHDES = 320;
+	               if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+		       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
                     }
                  }
               }
@@ -3590,18 +3545,6 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, 
 }
 
 /*********************************************/
-/*          SET CRT2 AUTO-THRESHOLD          */
-/*********************************************/
-
-#ifdef SIS315H
-static void
-SiS_CRT2AutoThreshold(SiS_Private *SiS_Pr)
-{
-  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
-}
-#endif
-
-/*********************************************/
 /*           DISABLE VIDEO BRIDGE            */
 /*********************************************/
 
@@ -3617,7 +3560,6 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 #endif
   USHORT temp=0;
 
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
@@ -3651,7 +3593,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	   } else {
 
 	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	         SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	      }
 	      if(SiS_Is301B(SiS_Pr)) {
@@ -3668,7 +3610,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	      if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	          (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
 	         SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	      }
 	   }
 
@@ -3686,7 +3628,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 #ifdef SET_EMI
 	         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 		    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-	               SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		    }
 		 }
 #endif
@@ -3916,10 +3858,12 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
       } else {     /* ============ For 301 ================ */
 
         if(HwInfo->jChipType < SIS_315H) {
+#ifdef SIS300
            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	      SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	   }
+#endif
 	}
 
         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
@@ -3937,12 +3881,14 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
 	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 	} else {
+#ifdef SIS300
             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
 	    if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	        (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
 		SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+		SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	    }
+#endif
 	}
 
       }
@@ -3962,7 +3908,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	      SiS_WaitVBRetrace(SiS_Pr,HwInfo);
 	   }
 	   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	      SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	   }
 	} else {
@@ -3973,7 +3919,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 		    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
 		       SiS_DisplayOff(SiS_Pr);
 	            }
-	            SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
                  }
               }
@@ -3992,7 +3938,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	    (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
 	   SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+	   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	}
 
 #endif  /* SIS300 */
@@ -4032,7 +3978,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	}
 
 	if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	   SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	}
 
@@ -4101,14 +4047,14 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	   if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	      if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
 	 	 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	      }
 	   }
         }
 
 #endif  /* SIS315H */
 
-    }  /* 310 series */
+    }  /* 315 series */
 
   }  /* LVDS */
 
@@ -4176,7 +4122,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 	    if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
 	       (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
 	       /* This is only for LCD output on 301B-DH via LVDS */
-	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	       if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
 	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	       }
@@ -4195,7 +4141,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 		           SiS_PanelDelay(SiS_Pr, HwInfo, 1);
                        }
 		       SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x00);
+                       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
                    }
 	       }
             } else {
@@ -4229,29 +4175,18 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
 #ifdef SET_EMI
 		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		  }
 #endif
 	       }
 
                if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
 	          tempah = 0x10;
-		  if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		     (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {
-		        if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) == 0x0c) {
-			   tempah = 0x08;
-			} else {
-			   tempah = 0x18;
-			}
-		     }
-		     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-		  } else {
-	             if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	                tempah = 0x08;
-                     }
-		     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
+		     else 			       tempah = 0x08;
 		  }
+		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
 	       }
 
 	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
@@ -4300,13 +4235,11 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 
 	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
 	          tempah = 0x10;
-		  if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {
-		     tempah = 0x18;
-		     if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) == 0x0c) {
-		        tempah = 0x08;
-		     }
+		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
+		     else 			       tempah = 0x08;
 		  }
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
 	       }
 	       
 	    }
@@ -4316,10 +4249,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 	       if(SiS_BridgeInSlave(SiS_Pr)) {
                   tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
                   if(!(tempah & SetCRT2ToRAMDAC)) {
-		     if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		        (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		        if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04)) temp |= 0x20;
-		     } else temp |= 0x20;
+		     if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
 		  }
                }
                SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
@@ -4385,7 +4315,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 	       if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
 #ifdef SET_EMI
 	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		  }
 #endif
 	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
@@ -4630,7 +4560,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 
        if(HwInfo->jChipType < SIS_315H) {
           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	  }
        }
@@ -4663,7 +4593,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
        if(HwInfo->jChipType < SIS_315H) {
           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
 	  }
        }
 
@@ -4681,13 +4611,13 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
 	  }
-          SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	  if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	  }
        }
 
-       SiS_EnableCRT2(SiS_Pr);
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_DisplayOn(SiS_Pr);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
@@ -4712,7 +4642,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
         	   SiS_PanelDelay(SiS_Pr, HwInfo, 1);
 	        }
 	        SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-                SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
              }
 	  }
        }
@@ -4725,12 +4655,12 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 	  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+	     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 0);
           }
        }
 
-       SiS_EnableCRT2(SiS_Pr);
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
 
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
@@ -4804,7 +4734,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
        	  if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
 	     if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 		SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+		SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
 	     }
 	  }
        }
@@ -4821,33 +4751,31 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 /*         SET PART 1 REGISTER GROUP         */
 /*********************************************/
 
-/********** Set CRT2 OFFSET / PITCH **********/
+/* Set CRT2 OFFSET / PITCH */
 static void
-SiS_SetCRT2Offset(SiS_Private *SiS_Pr,USHORT ModeNo,
-                  USHORT ModeIdIndex ,USHORT RefreshRateTableIndex,
-	          PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
+	          USHORT RRTI, PSIS_HW_INFO HwInfo)
 {
   USHORT offset;
   UCHAR temp;
 
   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
 
-  offset = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                         HwInfo);
+  offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-     SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) offset >>= 1;
+  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
+     (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
+     offset >>= 1;
+  }
 
-  temp = (UCHAR)(offset & 0xFF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,temp);
-  temp = (UCHAR)(offset >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
   temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
   if(offset % 8) temp++;
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
 }
 
-/************* Set CRT2 Sync *************/
+/* Set CRT2 sync and PanelLink mode */
 static void
 SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
                 PSIS_HW_INFO HwInfo)
@@ -4869,23 +4797,27 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
         tempah = SiS_Pr->SiS_LCDInfo;
      } else tempah = infoflag >> 8;
-
      tempah &= 0xC0;
-
      tempah |= 0x20;
      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-	   tempah |= 0xc0;
+	   tempah |= 0xf0;
+        }
+	if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+            (SiS_Pr->SiS_IF_DEF_DSTN) ||
+            (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+            (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+           tempah |= 0x30;
         }
      }
-
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(HwInfo->jChipType >= SIS_315H) {
            tempah >>= 3;
+	   tempah &= 0x18;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+	   /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
         } else {
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
         }
@@ -4902,19 +4834,21 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {			/* 630 - 301B(-DH) */
 
 	   tempah = infoflag >> 8;
+	   tempbl = 0;
            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	      if(SiS_Pr->SiS_LCDInfo & LCDSync) {
 	         tempah = SiS_Pr->SiS_LCDInfo;
+		 tempbl = (tempah >> 6) & 0x03;
               }
            }
            tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
- 	   tempah &= 0x3f;
-  	   tempah |= tempbl;
+  	   tempah |= 0xc0;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	   }
 
         } else {							/* 630 - 301 */
 
@@ -4932,43 +4866,72 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
 
 #ifdef SIS315H  /* ------- 315 series ------ */
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	  		/* 315 - 30xLV */
+        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	  		/* 315 - LVDS */
 
-	   if(((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) ||
-	      ((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050))) {
+	   tempbl = 0;
+	   if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
 	      tempah = infoflag >> 8;
+	      if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+	        tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+	      }
+	   } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
+	             (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+       	      tempah = infoflag >> 8;
+	      tempbl = 0x03;
 	   } else {
               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+	      tempbl = (tempah >> 6) & 0x03;
+	      tempbl |= 0x08;
+	      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
 	   }
 	   tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	      }
+	   }
 
-        } else {							/* 315 - 301, 301B */
+        } else {							/* 315 - TMDS */
 
-           tempah = infoflag >> 8;
+           tempah = tempbl = infoflag >> 8;
 	   if(!SiS_Pr->UseCustomMode) {
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      tempbl = 0;
+	      if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	         if(ModeNo <= 0x13) {
+	            tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  	         }
+	      }
+	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	         if(SiS_Pr->SiS_LCDInfo & LCDSync) {
 	            tempah = SiS_Pr->SiS_LCDInfo;
+		    tempbl = (tempah >> 6) & 0x03;
 	         }
 	      }
 	   }
 	   tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
-	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {			/* TEST, imitate BIOS bug */
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	         tempah |= 0xc0;
+	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	      /* Imitate BIOS bug */
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
+	   }
+	   if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	      tempah >>= 3;
+	      tempah &= 0x18;
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+	   } else {
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	            SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+		 }
 	      }
 	   }
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
 
         }
 #endif  /* SIS315H */
@@ -4976,7 +4939,7 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
    }
 }
 
-/******** Set CRT2 FIFO on 300/630/730 *******/
+/* Set CRT2 FIFO on 300/630/730 */
 #ifdef SIS300
 static void
 SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
@@ -5031,7 +4994,7 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
 
   if(!SiS_Pr->CRT1UsesCustomMode) {
 
-     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 	/* get CRT1 ModeNo */
+     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
      SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
      SiS_Pr->SiS_SelectCRT2Rate = 0;
@@ -5040,7 +5003,7 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
      if(CRT1ModeNo >= 0x13) {
         index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
         index &= 0x3F;
-        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;				/* Get VCLK */
+        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;			/* Get VCLK */
 
 	colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex); 	/* Get colordepth */
         colorth >>= 1;
@@ -5050,9 +5013,9 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
   } else {
 
      CRT1ModeNo = 0xfe;
-     VCLK = SiS_Pr->CSRClock_CRT1;						/* Get VCLK */
+     VCLK = SiS_Pr->CSRClock_CRT1;					/* Get VCLK */
      data2 = (SiS_Pr->CModeFlag_CRT1 & ModeInfoFlag) - 2;
-     switch(data2) {								/* Get color depth */
+     switch(data2) {							/* Get color depth */
         case 0 : colorth = 1; break;
         case 1 : colorth = 1; break;
         case 2 : colorth = 2; break;
@@ -5199,10 +5162,10 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
 
        index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
                                refreshratetableindex,HwInfo);
-       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                         	/* Get VCLK  */
+       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                /* Get VCLK  */
 
        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-          if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+          if(SiS_Pr->SiS_UseROM) {
 	     if(ROMAddr[0x220] & 0x01) {
                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
 	     }
@@ -5212,11 +5175,11 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
     } else {
 
        CRT2ModeNo = 0xfe;
-       VCLK = SiS_Pr->CSRClock;							/* Get VCLK */
+       VCLK = SiS_Pr->CSRClock;					/* Get VCLK */
 
     }
 
-    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex);   	/* Get colordepth */
+    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
     colorth >>= 1;
     if(!colorth) colorth++;
 
@@ -5235,8 +5198,8 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
     if(HwInfo->jChipType == SIS_300) {
        if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
        else             temp = (temp & (~0x1F)) | 0x16;
-       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-       		temp = (temp & (~0x1F)) | 0x13;
+       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       	  temp = (temp & (~0x1F)) | 0x13;
        }
     } else {
        if( ( (HwInfo->jChipType == SIS_630) ||
@@ -5266,280 +5229,21 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
 }
 #endif
 
-/**** Set CRT2 FIFO on 315/330 series ****/
-#ifdef SIS315H
-static void
-SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr)
-{
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3F,0x04);
-}
-#endif
-
-/*************** Set LCD-A ***************/
+/* Set CRT2 FIFO on 315/330 series */
 #ifdef SIS315H
 static void
-SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT modeflag,resinfo;
-  USHORT push2,tempax,tempbx,tempcx,temp;
-  ULONG tempeax=0,tempebx,tempecx,tempvcfact;
-
-  /* This is not supported with LCDA */
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
-  if(SiS_Pr->UseCustomMode) return;
-
-  if(IS_SIS330) {
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);			/* Xabre 1.01.03 */
-  } else if(IS_SIS740) {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* 740/LVDS */
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);      	/* 740/LVDS */
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
-     } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);			/* 740/301LV, 301BDH */
-     }
-  } else {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* 650/LVDS */
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);      	/* 650/LVDS */
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);			/* 650/LVDS 1.10.07 */
-     } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);			/* 650/30xLv 1.10.6s */
-     }
-  }
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
-
-  tempax = SiS_Pr->SiS_LCDHDES;
-
-  temp = (tempax & 0x0007);                        		/* BPLHDESKEW[2:0]   */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                         /* Part1_1Ah  */
-  temp = (tempax >> 3) & 0x00FF;                               	/* BPLHDESKEW[10:3]  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                         /* Part1_16h  */
-
-  tempbx = SiS_Pr->SiS_HDE;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-     tempbx = SiS_Pr->PanelXRes;
-  }
-
-  tempax += tempbx;	                                    	/* HDE + HSKEW = lcdhdee  */
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
-
-  temp = tempax;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(temp & 0x07) temp += 8;
-  }
-  temp >>= 3;                                        		/* BPLHDEE  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                        	/* Part1_17h  */
-
-  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;     	            	/* (HT-HDE) / 4  */
-
-  /* 650/30xLV 1.10.6s, 740/LVDS */
-  if( ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
-      ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)        tempcx = 0x28;
- 	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  tempcx = 0x18;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x30;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x40;
-	else                                                          tempcx = 0x30;
-     }
-  }
-
-  tempcx += tempax;  	                                  	/* lcdhrs  */
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
-
-  temp = (tempcx >> 3) & 0x00FF;				/* BPLHRS */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                 		/* Part1_14h  */
-
-  temp += 10;
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   temp += 6;
-	   if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	      temp++;
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
-	         temp += 7;
-		 if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
-		    temp -= 10;
-		 }
-	      }
-	   }
-	}
-     }
-  }
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x07) << 5);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                         /* Part1_15h  */
-
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-     tempax = SiS_Pr->PanelYRes;
-  } else {
-     tempax = SiS_Pr->SiS_VGAVDE;
-  }
-
-  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-  push2 = tempbx;
-
-  tempcx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 2;
-
-  if( ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
-      ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 1;
-   	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)   tempcx = 3;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 3;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 1;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 1;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 1;
-	else                                                           tempcx = 0x0057;
-     }
-  }
-
-  tempbx += tempcx;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     tempbx++;                                                	/* BPLVRS  */
-  }
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);                             /* Part1_18h  */
-
-  tempcx >>= 3;
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 3;
-   	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)   tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 2;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 2;
-	}
-     }
-  }
-  tempcx += tempbx;
-  tempcx++;                                                	/* BPLVRE  */
-  temp = tempcx & 0x000F;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     temp |= 0xC0;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); 		/* Part1_19h  */
-  } else {
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)   temp |= 0x40;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     /* Don't check Part1Port,0x00 -> is not being set if LCDA! */
-     /* We check SR06 instead here: */
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
-     }
-  } else {
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
-     }
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x07,temp);            /* Part1_1Ah */
-
-  tempbx = push2;                                      		/* BPLVDEE */
-
-  tempcx = SiS_Pr->SiS_LCDVDES;                        		/* NPLVDES */
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-        if(resinfo == SIS_RI_800x600) tempcx++;
-     }
-  }
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-     tempbx = tempcx = SiS_Pr->SiS_VGAVDE;
-     tempbx--;
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempcx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);                          /* Part1_1Dh */
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,temp);                          /* Part1_1Ch  */
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,temp);                          /* Part1_1Bh  */
-
-  tempeax = SiS_Pr->SiS_VGAVDE << 18;
-  tempebx = SiS_Pr->SiS_VDE;
-  temp = (USHORT)(tempeax % tempebx);
-  tempeax = tempeax / tempebx;
-  if(temp) tempeax++;
-  tempvcfact = tempeax;
-
-  temp = (USHORT)(tempeax & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
-
-  temp = (USHORT)((tempeax & 0x00FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
-
-  temp = (USHORT)((tempeax & 0x00030000) >> 16);
-  if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
-
-  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
-     temp = (USHORT)(tempeax & 0x00FF);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
-     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
-     temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
-     temp = 0;
-     if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
-  }
-
-  tempeax = SiS_Pr->SiS_VGAHDE << 16;
-  tempebx = SiS_Pr->SiS_HDE;
-  temp = tempeax % tempebx;
-  tempeax /= tempebx;
-  if(temp) tempeax++;
-  if(tempebx == SiS_Pr->SiS_VGAHDE) tempeax = 0xFFFF;
-  tempecx = tempeax;
-  tempeax = ((SiS_Pr->SiS_VGAHDE << 16) / tempecx) - 1;
-  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
-  temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);                          /* Part1_1Fh  */
-
-  tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-  tempbx = (USHORT)(tempeax & 0x0FFFF);
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
-
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)  tempbx = 1;
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempecx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);                         /* Part1_20h */
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,temp);                         /* Part1_21h */
-
-  tempecx >>= 16;   	                                  	/* BPLHCFACT  */
-  if(modeflag & HalfDCLK) tempecx >>= 1;
-  temp = (USHORT)((tempecx & 0x0000FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);                         /* Part1_22h */
-
-  temp = (USHORT)(tempecx & 0x000000FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
+  USHORT temp;
 
-  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
+  temp = 0x04;
+  if(HwInfo->jChipType >= SIS_661) {
+     if((SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8) == 0x80) temp = 0x44;
   }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,temp);
 }
-#endif  /* SIS 315 */
+#endif
 
 static USHORT
 SiS_GetVGAHT2(SiS_Private *SiS_Pr)
@@ -5552,31 +5256,37 @@ SiS_GetVGAHT2(SiS_Private *SiS_Pr)
   return((USHORT) tempax);
 }
 
-/******* Set Part 1 / SiS bridge *********/
+/* Set Part 1 / SiS bridge slave mode */
 static void
 SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
                   PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
 {
   USHORT  push1,push2;
   USHORT  tempax,tempbx,tempcx,temp;
-  USHORT  resinfo,modeflag;
+  USHORT  resinfo,modeflag,xres=0;
   unsigned char p1_7, p1_8;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+     xres = SiS_Pr->CHDisplay;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   /* The following is only done if bridge is in slave mode: */
 
+  if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
+     if(xres >= 1600) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
+     }
+  }
+
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff);                  /* set MAX HT */
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)  modeflag |= Charx8Dot;
@@ -5637,21 +5347,20 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
      } else {
         if(!(modeflag & HalfDCLK)) {
            temp -= 4;
-           if((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) &&
-	      (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200)) {
+           if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
+	      (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
               if(SiS_Pr->SiS_VGAHDE >= 800) {
                  temp -= 7;
 	         if(HwInfo->jChipType < SIS_315H) {
-	            /* 650/301LV(x) does not do this, 630/301B, 300/301LV do */
                     if(SiS_Pr->SiS_ModeType == ModeEGA) {
                        if(SiS_Pr->SiS_VGAVDE == 1024) {
                           temp += 15;
-                          if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
+                          if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
 		  	     temp += 7;
                        }
                     }
 	         }
-		 if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+		 if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
                     if(SiS_Pr->SiS_VGAHDE >= 1280) {
                        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
 		    }
@@ -5715,6 +5424,10 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
 	      p1_7 = 0xab;
 	   }
 	}
+     } else {
+        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+	   if(modeflag & HalfDCLK) p1_7 = 0x30;
+	}
      }
   }
 
@@ -5737,7 +5450,7 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
   else if(tempbx == 525) tempbx = 480;
   push2 = tempbx;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
       	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
            if     (tempbx == 350) tempbx += 5;
            else if(tempbx == 480) tempbx += 5;
@@ -5783,7 +5496,7 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
 	tempbx += (tempax << 1);
      }
   } else if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
 	tempbx += (tempax << 1);
      }
   }
@@ -5860,521 +5573,465 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
      }
   }
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                	/* 0x1A SR0E */
+
+  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
 }
 
-/*********** Set Part 1 / LVDS ***********/
+/* Setup panel link
+ * This is used for LVDS, LCDA and Chrontel TV output
+ * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
+ */
 static void
 SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- 		   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
-  USHORT modeflag, resinfo;
-  USHORT push1, push2, tempax, tempbx, tempcx, temp;
+  USHORT modeflag,resinfo;
+  USHORT push2,tempax,tempbx,tempcx,temp;
+  ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
+  BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
+#ifdef SIS300
+  USHORT crt2crtc;
+#endif
 #ifdef SIS315H
   USHORT pushcx;
 #endif
-  ULONG  tempeax=0, tempebx, tempecx, tempvcfact=0;
-
-  /* This is not supported on LVDS */
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
-  if(SiS_Pr->UseCustomMode) return;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+#ifdef SIS300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+#ifdef SIS300
+     crt2crtc = 0;
+#endif
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef SIS300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
   }
 
-  /* Set up Panel Link */
+  /* is lvds if really LVDS, or SiS 301B-DH with external LVDS transmitter */
+  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+     ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     islvds = TRUE;
+  }
 
-  /* 1. Horizontal setup */
+  /* is really sis if sis bridge, but not 301B-DH */
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     issis = TRUE;
+  }
 
-  tempax = SiS_Pr->SiS_LCDHDES;
-
-  if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-     if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) &&
-         (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
-  	   tempax -= 8;
+  if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+        chkdclkfirst = TRUE;
      }
   }
 
-  tempcx = SiS_Pr->SiS_HT;    				  /* Horiz. Total */
-
-  tempbx = SiS_Pr->SiS_HDE;                               /* Horiz. Display End */
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-     SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-     tempbx >>= 1;
-  }
-
-  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-	   tempbx = SiS_Pr->PanelXRes;
-	} else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   tempbx = SiS_Pr->PanelXRes;
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	      tempbx = 800;
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	         tempbx = 1024;
+#ifdef SIS315H
+  if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+     if(IS_SIS330) {
+        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+     } else if(IS_SIS740) {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+        }
+     } else {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
+	         (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+	         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
 	      }
 	   }
         }
      }
   }
-  tempcx = (tempcx - tempbx) >> 2;		 /* HT-HDE / 4 */
-
-  push1 = tempax;
-
-  tempax += tempbx;
-
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
+#endif
 
-  push2 = tempax;
+  /* Horizontal */
 
-  if((!SiS_Pr->SiS_IF_DEF_FSTN) &&
-     (!SiS_Pr->SiS_IF_DEF_DSTN) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-     	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)        tempcx = 0x0028;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)  tempcx = 0x0018;
-     	      else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	            (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) ) {
-	  	   if(HwInfo->jChipType < SIS_315H) {
-		      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		         tempcx = 0x0017;  /* A901; sometimes 0x0018; */
-		      } else {
-		         tempcx = 0x0017;
-#ifdef TWNEWPANEL
-			 tempcx = 0x0018;
-#endif
-		      }
-		   } else {
-		      tempcx = 0x0018;
-		   }
-	      }
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)  tempcx = 0x0028;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0030;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0030;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0040;
+  tempax = SiS_Pr->SiS_LCDHDES;
+  if(islvds) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+           if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+              (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+  	      tempax -= 8;
 	   }
-        }
+	}
      }
   }
 
-  tempcx += tempax;                              /* lcdhrs  */
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
+  temp = (tempax & 0x0007);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);			/* BPLHDESKEW[2:0]   */
+  temp = (tempax >> 3) & 0x00FF;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);			/* BPLHDESKEW[10:3]  */
 
-  tempax = tempcx >> 3;                          /* BPLHRS */
-  temp = tempax & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);		 /* Part1_14h; Panel Link Horizontal Retrace Start  */
-
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     temp = (tempax & 0x00FF) + 2;
-  } else {
-     temp = (tempax & 0x00FF) + 10;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if((!SiS_Pr->SiS_IF_DEF_DSTN) &&
-	   (!SiS_Pr->SiS_IF_DEF_FSTN) &&
-	   (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-	   (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-	   (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	      temp += 6;
-              if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	         temp++;
-	         if(HwInfo->jChipType >= SIS_315H) {
-	            if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
-	               temp += 7;
-		       if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
-		          temp -= 0x14;
-			  if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x768) {
-			     temp -= 10;
-			  }
-		       }
-	            }
-	         }
-	      }
-           }
-        }
+  tempbx = SiS_Pr->SiS_HDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
+        tempbx >>= 1;
+     }
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        tempbx = SiS_Pr->PanelXRes;
      }
   }
 
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x0007) << 5);
-#if 0
-  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;       /* WRONG? BIOS loads cl, not ah */
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);    	 /* Part1_15h; Panel Link Horizontal Retrace End/Skew */
+  tempax += tempbx;
+  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
 
-  tempbx = push2;
-  tempcx = push1;                                /* lcdhdes  */
+  temp = tempax;
+  if(temp & 0x07) temp += 8;
+  temp >>= 3;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);			/* BPLHDEE  */
 
-  temp = (tempcx & 0x0007);                      /* BPLHDESKEW  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);   	 /* Part1_1Ah; Panel Link Vertical Retrace Start (2:0) */
+  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
 
-  tempcx >>= 3;                                  /* BPLHDES */
-  temp = (tempcx & 0x00FF);
-#if 0 /* Not 550 FSTN */
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(ModeNo == 0x5b) temp--; */
-  }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);    	 /* Part1_16h; Panel Link Horizontal Display Enable Start  */
-
-  if((HwInfo->jChipType < SIS_315H) ||
-     (SiS_Pr->SiS_IF_DEF_FSTN) ||
-     (SiS_Pr->SiS_IF_DEF_DSTN)) {
-     if(tempbx & 0x07) tempbx += 8;
-  }
-  tempbx >>= 3;                                  /* BPLHDEE  */
-  temp = tempbx & 0x00FF;
-#if 0 /* Not 550 FSTN */
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(ModeNo == 0x5b) temp--;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
+     }
   }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);   	 /* Part1_17h; Panel Link Horizontal Display Enable End  */
 
-  /* 2. Vertical setup */
+  tempcx += tempax;
+  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
 
-  if(HwInfo->jChipType < SIS_315H) {
-     tempcx = SiS_Pr->SiS_VGAVT;
-     tempbx = SiS_Pr->SiS_VGAVDE;
-     if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) && (SiS_Pr->SiS_CustomT != CUT_BARCO1024)) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	      tempbx = SiS_Pr->PanelYRes;
+  temp = (tempcx >> 3) & 0x00FF;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+           switch(ModeNo) {
+           case 0x04:
+           case 0x05:
+           case 0x0d: temp = 0x56; break;
+           case 0x10: temp = 0x60; break;
+           case 0x13: temp = 0x5f; break;
+           case 0x40:
+           case 0x41:
+           case 0x4f:
+           case 0x43:
+           case 0x44:
+           case 0x62:
+           case 0x56:
+           case 0x53:
+           case 0x5d:
+           case 0x5e: temp = 0x54; break;
            }
-	}
+        }
      }
-     tempcx -= tempbx;
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);			/* BPLHRS */
 
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     temp += 2;
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        temp += 8;
+        if(SiS_Pr->PanelHRE != 999) {
+           temp = tempcx + SiS_Pr->PanelHRE;
+	   if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
+	   temp >>= 3;
+        }
+     }
   } else {
-
-     tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;           /* VGAVT-VGAVDE  */
-
+     temp += 10;
   }
 
-  tempbx = SiS_Pr->SiS_LCDVDES;	   		 	 	/* VGAVDES  */
-  push1 = tempbx;
+  temp &= 0x1F;
+  temp |= ((tempcx & 0x07) << 5);
+#if 0
+  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;       		/* WRONG? BIOS loads cl, not ah */
+#endif
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);			/* BPLHRE */
 
-  tempax = SiS_Pr->SiS_VGAVDE;
+  /* Vertical */
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-           tempax = 600;
-	   if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	      tempax = 768;
-	   }
-	}
-     } else if( (SiS_Pr->SiS_IF_DEF_TRUMPION == 0)   &&
-                (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
-                ((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) ||
-	         (SiS_Pr->SiS_IF_DEF_FSTN) ||
-	         (SiS_Pr->SiS_IF_DEF_DSTN)) ) {
+  tempax = SiS_Pr->SiS_VGAVDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	tempax = SiS_Pr->PanelYRes;
      }
   }
 
-  tempbx += tempax;
+  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
 
   push2 = tempbx;
 
-  tempcx >>= 1;
-
-  if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
-     (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-	tempcx = 0x0017;
-     } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 0x0003;
-  	   else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)) tempcx = 0x0003;
-           else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 0x0001;
-           else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 0x0001;
-	   else 							  tempcx = 0x0057;
-        } else  {
-     	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 0x0001;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)   tempcx = 0x0001;
-     	   else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)) {
-		   if(HwInfo->jChipType < SIS_315H) {
-		      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		         tempcx = 0x0002;   /* A901; sometimes 0x0003; */
-		      } else {
-			 tempcx = 0x0002;
-#ifdef TWNEWPANEL
-			 tempcx = 0x0003;
-#endif
-		      }
-		   } else tempcx = 0x0003;
-           }
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)  tempcx = 0x0003;
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0001;
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0001;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0001;
-     	   else 							 tempcx = 0x0057;
+  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
+  if(HwInfo->jChipType < SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
 	}
      }
   }
+  if(islvds) tempcx >>= 1;
+  else       tempcx >>= 2;
 
-  tempbx += tempcx;			 	/* BPLVRS  */
-
-  if((HwInfo->jChipType < SIS_315H) ||
-     (SiS_Pr->SiS_IF_DEF_FSTN) ||
-     (SiS_Pr->SiS_IF_DEF_DSTN)) {
-     tempbx++;
+  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+      (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) 		    &&
+      (SiS_Pr->PanelVRS != 999) ) {
+     tempcx = SiS_Pr->PanelVRS;
+     tempbx += tempcx;
+     if(issis) tempbx++;
+  } else {
+     tempbx += tempcx;
+     if(HwInfo->jChipType < SIS_315H) tempbx++;
+     else if(issis)                   tempbx++;
   }
 
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
+  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;	/* BPLVRS  */
 
   temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);       	 /* Part1_18h; Panel Link Vertical Retrace Start  */
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(ModeNo == 0x10) temp = 0xa9;
+     }
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
 
   tempcx >>= 3;
+  tempcx++;
 
-  if((!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if( (HwInfo->jChipType < SIS_315H) &&
-            (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) )     tempcx = 0x0001;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2)  tempcx = 0x0002;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)  tempcx = 0x0002;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)    tempcx = 0x0003;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)   tempcx = 0x0005;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)   tempcx = 0x0005;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 0x0011;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 0x0005;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 0x0002;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 0x0011;
-        else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  {
-     		if(HwInfo->jChipType < SIS_315H) {
-		   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		      tempcx = 0x0004;   /* A901; Other BIOS sets 0x0005; */
-		   } else {
-		      tempcx = 0x0004;
-#ifdef TWNEWPANEL
-		      tempcx = 0x0005;
-#endif
-		   }
-		} else {
-		   tempcx = 0x0005;
-		}
-        }
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
      }
   }
 
-  tempcx = tempcx + tempbx + 1;                  /* BPLVRE  */
+  tempcx += tempbx;
   temp = tempcx & 0x000F;
-  if(SiS_Pr->SiS_IF_DEF_FSTN ||
-     SiS_Pr->SiS_IF_DEF_DSTN ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
-     temp |= 0x30;
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); /* Part1_19h; Panel Link Vertical Retrace End (3:0); Misc.  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);	/* BPLVRE  */
 
-  temp = ((tempbx & 0x0700) >> 8) << 3;          /* BPLDESKEW =0 */
+  temp = ((tempbx >> 8) & 0x07) << 3;
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
      if(SiS_Pr->SiS_HDE != 640) {
-        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)   temp |= 0x40;
+        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
      }
-  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)           temp |= 0x40;
-  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-     if(HwInfo->jChipType >= SIS_315H) {
-        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
-           temp |= 0x80;
+  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
+  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
+  tempbx = 0x87;
+  if((HwInfo->jChipType >= SIS_315H) ||
+     (HwInfo->jChipRevision >= 0x30)) {
+     tempbx = 0x07;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
+     }
+     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
+     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
+	} else {
+	   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
+	}
+     }
+  }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
+
+  tempbx = push2;                                      		/* BPLVDEE */
+
+  tempcx = SiS_Pr->SiS_LCDVDES;                        		/* BPLVDES */
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+        tempbx = SiS_Pr->SiS_VGAVDE - 1;
+        tempcx = SiS_Pr->SiS_VGAVDE;
+	break;
+     case Panel_800x600:
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+           if(resinfo == SIS_RI_800x600) tempcx++;
         }
-     } else {
-	if( (HwInfo->jChipType == SIS_630) ||
-	    (HwInfo->jChipType == SIS_730) ) {
-	   if(HwInfo->jChipRevision >= 0x30) {
-	      temp |= 0x80;
+	break;
+     case Panel_1024x600:
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+           if(resinfo == SIS_RI_1024x600) tempcx++;
+           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	      if(resinfo == SIS_RI_800x600) tempcx++;
 	   }
-	}
+        }
+	break;
+     case Panel_1024x768:
+        if(HwInfo->jChipType < SIS_315H) {
+           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+              if(resinfo == SIS_RI_1024x768) tempcx++;
+	   }
+        }
+	break;
      }
   }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp);  /* Part1_1Ah; Panel Link Control Signal (7:3); Vertical Retrace Start (2:0) */
 
-  if (HwInfo->jChipType < SIS_315H) {
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempcx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
+  /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++;  */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
 
-#ifdef SIS300      /* 300 series */
+  /* Vertical scaling */
 
-        tempeax = SiS_Pr->SiS_VGAVDE << 6;
-        temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
-        tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
-        if(temp != 0) tempeax++;
-        tempebx = tempeax;                         /* BPLVCFACT  */
+  if(HwInfo->jChipType < SIS_315H) {
 
-  	if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
-	   tempebx = 0x003F;
-	}
+#ifdef SIS300      /* 300 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 6;
+     temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
+     tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
+     if(temp) tempeax++;
 
-  	temp = (USHORT)(tempebx & 0x00FF);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      /* Part1_1Eh; Panel Link Vertical Scaling Factor */
+     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
 
+     temp = (USHORT)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      	/* BPLVCFACT */
+     tempvcfact = temp;
 #endif /* SIS300 */
 
   } else {
 
 #ifdef SIS315H  /* 315 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 18;
+     tempebx = SiS_Pr->SiS_VDE;
+     temp = (tempeax % tempebx);
+     tempeax = tempeax / tempebx;
+     if(temp) tempeax++;
+     tempvcfact = tempeax;
 
-        if(HwInfo->jChipType == SIS_740) {
-           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x03);
-        } else {
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,0x23);
-	}
-
-	tempeax = SiS_Pr->SiS_VGAVDE << 18;
-    	temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
-    	tempeax = tempeax / SiS_Pr->SiS_VDE;
-    	if(temp != 0) tempeax++;
-    	tempebx = tempeax;                         /* BPLVCFACT  */
-        tempvcfact = tempeax;
-    	temp = (USHORT)(tempebx & 0x00FF);
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);      /* Part1_37h; Panel Link Vertical Scaling Factor */
-    	temp = (USHORT)((tempebx & 0x00FF00) >> 8);
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);      /* Part1_36h; Panel Link Vertical Scaling Factor */
-    	temp = (USHORT)((tempebx & 0x00030000) >> 16);
-	temp &= 0x03;
-    	if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);      /* Part1_35h; Panel Link Vertical Scaling Factor */
-
-#endif /* SIS315H */
-
-  }
-
-  tempbx = push2;                                  /* BPLVDEE  */
-  tempcx = push1;
-
-  push1 = temp;
-
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-   	if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
-		if(HwInfo->jChipType < SIS_315H) {
-			if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-      				if(resinfo == SIS_RI_1024x600) tempcx++;
-				if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-					if(resinfo == SIS_RI_800x600) tempcx++;
-		    		}
-			} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-      				if(resinfo == SIS_RI_800x600)  tempcx++;
-				if(resinfo == SIS_RI_1024x768) tempcx++; /* Doesnt make sense anyway... */
-			} else  if(resinfo == SIS_RI_1024x768) tempcx++;
-		} else {
-			if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-      				if(resinfo == SIS_RI_800x600)  tempcx++;
-			}
-		}
-	}
-  }
+     temp = (USHORT)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
+     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
+     temp = (USHORT)((tempeax & 0x00030000) >> 16);
+     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        tempcx = SiS_Pr->SiS_VGAVDE;
-        tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
+        temp = (USHORT)(tempeax & 0x00FF);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
+        temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
+        temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
+        temp = 0;
+        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
      }
-  }
-
-  temp = ((tempbx & 0x0700) >> 8) << 3;
-  temp |= ((tempcx & 0x0700) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);     	/* Part1_1Dh; Vertical Display Overflow; Control Signal */
-
-  temp = tempbx & 0x00FF;
-  /* if(SiS_Pr->SiS_IF_DEF_FSTN) temp++;  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,temp);      	/* Part1_1Ch; Panel Link Vertical Display Enable End  */
+#endif
 
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,temp);      	/* Part1_1Bh; Panel Link Vertical Display Enable Start  */
+  }
 
-  /* 3. Additional horizontal setup (scaling, etc) */
+  /* Horizontal scaling */
 
-  tempecx = SiS_Pr->SiS_VGAHDE;
-  if(HwInfo->jChipType >= SIS_315H) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        if(modeflag & HalfDCLK) tempecx >>= 1;
-     }
+  tempeax = SiS_Pr->SiS_VGAHDE;		/* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
+  if(chkdclkfirst) {
+     if(modeflag & HalfDCLK) tempeax >>= 1;
   }
-  tempebx = SiS_Pr->SiS_HDE;
-  if(tempecx == tempebx) tempeax = 0xFFFF;
-  else {
-     tempeax = tempecx;
-     tempeax <<= 16;
-     temp = (USHORT)(tempeax % tempebx);
-     tempeax = tempeax / tempebx;
+  tempebx = tempeax << 16;
+  if(SiS_Pr->SiS_HDE == tempeax) {
+     tempecx = 0xFFFF;
+  } else {
+     tempecx = tempebx / SiS_Pr->SiS_HDE;
      if(HwInfo->jChipType >= SIS_315H) {
-        if(temp) tempeax++;
+        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
      }
   }
-  tempecx = tempeax;
 
   if(HwInfo->jChipType >= SIS_315H) {
-     tempeax = SiS_Pr->SiS_VGAHDE;
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        if(modeflag & HalfDCLK) tempeax >>= 1;
-     }
-     tempeax <<= 16;
-     tempeax = (tempeax / tempecx) - 1;
+     tempeax = (tempebx / tempecx) - 1;
   } else {
      tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
   }
-  tempecx <<= 16;
-  tempecx |= (tempeax & 0xFFFF);
+  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
   temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);  	 /* Part1_1Fh; Panel Link DDA Operational Number in each horiz. line */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
 
-  tempbx = SiS_Pr->SiS_VDE;
   if(HwInfo->jChipType >= SIS_315H) {
      tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-     tempbx = (USHORT)(tempeax & 0x0FFFF);
+     tempbx = (USHORT)(tempeax & 0xFFFF);
   } else {
      tempeax = SiS_Pr->SiS_VGAVDE << 6;
-     tempbx = push1 & 0x3f;
+     tempbx = tempvcfact & 0x3f;
      if(tempbx == 0) tempbx = 64;
      tempeax /= tempbx;
-     tempbx = (USHORT)(tempeax & 0x0FFFF);
+     tempbx = (USHORT)(tempeax & 0xFFFF);
   }
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
-     else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  tempbx = 1;
+     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
   }
 
-  temp = ((tempbx & 0xFF00) >> 8) << 3;
-  temp |= (USHORT)((tempecx & 0x0700) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);  	/* Part1_20h; Overflow register */
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,temp);  	/* Part1_21h; Panel Link Vertical Accumulator Register */
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempecx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
 
-  tempecx >>= 16;                               /* BPLHCFACT  */
-  if((HwInfo->jChipType < SIS_315H) || (SiS_Pr->SiS_IF_DEF_FSTN) || (SiS_Pr->SiS_IF_DEF_DSTN)) {
+  tempecx >>= 16;   	                                  	/* BPLHCFACT  */
+  if(!chkdclkfirst) {
      if(modeflag & HalfDCLK) tempecx >>= 1;
   }
   temp = (USHORT)((tempecx & 0xFF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);     	/* Part1_22h; Panel Link Horizontal Scaling Factor High */
-
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
   temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);         /* Part1_22h; Panel Link Horizontal Scaling Factor Low */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
 
-  /* 630/301B and 630/LVDS do something for 640x480 panels here */
+#ifdef SIS315H
+  if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
+           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	}
+     } else {
+        if(islvds) {
+           if(HwInfo->jChipType == SIS_740) {
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
+           } else {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
+           }
+        }
+     }
+  }
+#endif
+
+#ifdef SIS300
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     int i;
+     UCHAR TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
+     UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+     UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
+     for(i=0; i<5; i++) {
+        SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
+     }
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(ModeNo == 0x13) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
+	   }
+	} else if(ModeNo == 0x10) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
+	   }
+	}
+     }
+     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
+  }
+#endif
 
 #ifdef SIS315H
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
@@ -6384,10 +6041,10 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, 
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x007,0x03);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
      tempax = SiS_Pr->SiS_HDE;                       		/* Blps = lcdhdee(lcdhdes+HDE) + 64 */
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax += 64;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
@@ -6401,8 +6058,8 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, 
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
 
      tempax = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax >>= 1;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
@@ -6410,8 +6067,8 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, 
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
 
      tempeax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempeax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
      tempeax <<= 2;                       			/* BDxFIFOSTOP = (HDE*4)/128 */
      tempebx = 128;
      temp = (USHORT)(tempeax % tempebx);
@@ -6425,8 +6082,8 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, 
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
 
      tempax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax >>= 4;                        			/* BDxWadroff = HDE*4/8/8 */
      pushcx = tempax;
      temp = tempax & 0x00FF;
@@ -6435,8 +6092,8 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, 
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
 
      tempax = SiS_Pr->SiS_VDE;                             	/* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempeax = (tempax * pushcx);
      tempebx = 0x00100000 + tempeax;
      temp = (USHORT)tempebx & 0x000000FF;
@@ -6478,496 +6135,422 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, 
      }
   }
 #endif  /* SIS315H */
-
 }
 
-/************** Set Part 1 ***************/
+/* Set Part 1 */
 static void
 SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
-  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+  UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT  temp=0, tempax=0, tempbx=0, tempcx=0;
-  USHORT  pushbx=0, CRT1Index=0;
+  USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
 #ifdef SIS315H
   USHORT  tempbl=0;
 #endif
-  USHORT  modeflag, resinfo=0;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     return;
+  }
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-	modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
+     CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-#ifdef SIS315H
-     SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
-     SiS_SetGroup1_LCDA(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
-#endif
-
-  } else {
+  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 
-     if( (HwInfo->jChipType >= SIS_315H) &&
+  if( ! ((HwInfo->jChipType >= SIS_315H) &&
          (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
-	 (SiS_Pr->SiS_VBInfo & SetInSlaveMode) ) {
+         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
 
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
-
-     } else {
-
-        SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex,
-      		          RefreshRateTableIndex, HwInfo);
-
-        if (HwInfo->jChipType < SIS_315H ) {
+     if(HwInfo->jChipType < SIS_315H ) {
 #ifdef SIS300
-    	      SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
+  	SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
 #endif
-        } else {
+     } else {
 #ifdef SIS315H
-              SiS_SetCRT2FIFO_310(SiS_Pr);
+        SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
 #endif
-	}
-
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+     }
 
-	/* 1. Horizontal setup */
+     /* 1. Horizontal setup */
 
-        if(HwInfo->jChipType < SIS_315H ) {
+     if(HwInfo->jChipType < SIS_315H ) {
 
 #ifdef SIS300   /* ------------- 300 series --------------*/
 
-    		temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   			/* BTVGA2HT 0x08,0x09 */
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);                   /* CRT2 Horizontal Total */
+    	temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   		  /* BTVGA2HT 0x08,0x09 */
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
 
-    		temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
-    		SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);          /* CRT2 Horizontal Total Overflow [7:4] */
+    	temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-    		temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                       /* BTVGA2HDEE 0x0A,0x0C */
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                   /* CRT2 Horizontal Display Enable End */
+    	temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
 
-    		pushbx = SiS_Pr->SiS_VGAHDE + 12;                               /* bx  BTVGA@HRS 0x0B,0x0C */
-    		tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
-    		tempbx = pushbx + tempcx;
-    		tempcx <<= 1;
-    		tempcx += tempbx;
-
-    		if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-		   if(SiS_Pr->UseCustomMode) {
-		      tempbx = SiS_Pr->CHSyncStart + 12;
-		      tempcx = SiS_Pr->CHSyncEnd + 12;
-		   }
+	pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
+    	tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+    	tempbx = pushbx + tempcx;
+    	tempcx <<= 1;
+    	tempcx += tempbx;
 
-      		   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-		      unsigned char cr4, cr14, cr5, cr15;
-		      if(SiS_Pr->UseCustomMode) {
-		         cr4  = SiS_Pr->CCRT1CRTC[4];
-			 cr14 = SiS_Pr->CCRT1CRTC[14];
-			 cr5  = SiS_Pr->CCRT1CRTC[5];
-			 cr15 = SiS_Pr->CCRT1CRTC[15];
-		      } else {
-		         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-			 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-			 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-			 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-		      }
-        	      tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 1) << 3;
-        	      tempcx = (((cr5 & 0x1F) | ((cr15 & 0x04) << (6-2))) - 1) << 3;
-      		   }
-
-    		   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == SIS_RI_1024x768)){
-        	      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)){
-      			 tempbx = 1040;
-      			 tempcx = 1042;
-      		      }
-    		   }
-	        }
+    	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+	   if(SiS_Pr->UseCustomMode) {
+	      tempbx = SiS_Pr->CHSyncStart + 12;
+	      tempcx = SiS_Pr->CHSyncEnd + 12;
+	   }
+
+      	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	      unsigned char cr4, cr14, cr5, cr15;
+	      if(SiS_Pr->UseCustomMode) {
+	         cr4  = SiS_Pr->CCRT1CRTC[4];
+		 cr14 = SiS_Pr->CCRT1CRTC[14];
+		 cr5  = SiS_Pr->CCRT1CRTC[5];
+		 cr15 = SiS_Pr->CCRT1CRTC[15];
+	      } else {
+	         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+		 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+		 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+		 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+	      }
+              tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 1) << 3;
+              tempcx = (((cr5 & 0x1F) | ((cr15 & 0x04) << (6-2))) - 1) << 3;
+      	   }
+
+    	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      	      tempbx = 1040;
+      	      tempcx = 1044;
+    	   }
+
+	}
+
+    	temp = tempbx & 0x00FF;
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
 
-    		temp = tempbx & 0x00FF;
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);                   /* CRT2 Horizontal Retrace Start */
 #endif /* SIS300 */
 
- 	} else {
+     } else {
 
 #ifdef SIS315H  /* ------------------- 315/330 series --------------- */
 
-	        tempcx = SiS_Pr->SiS_VGAHT;				       /* BTVGA2HT 0x08,0x09 */
-		if(modeflag & HalfDCLK) {
-		    if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		       tempcx >>= 1;
-		    } else {
-		       tempax = SiS_Pr->SiS_VGAHDE >> 1;
-		       tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
-		       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-			  tempcx = SiS_Pr->SiS_HT - tempax;
-		       }
-		    }
-		}
-		tempcx--;
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HT 0x08,0x09 */
+	if(modeflag & HalfDCLK) {
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      tempcx >>= 1;
+	   } else {
+	      tempax = SiS_Pr->SiS_VGAHDE >> 1;
+	      tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
+	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	         tempcx = SiS_Pr->SiS_HT - tempax;
+	      }
+	   }
+	}
+	tempcx--;
 
-		temp = tempcx & 0xff;
-		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);                  /* CRT2 Horizontal Total */
+	temp = tempcx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
 
-		temp = ((tempcx & 0xff00) >> 8) << 4;
-		SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);         /* CRT2 Horizontal Total Overflow [7:4] */
+	temp = ((tempcx & 0xff00) >> 8) << 4;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-		tempcx = SiS_Pr->SiS_VGAHT;				       /* BTVGA2HDEE 0x0A,0x0C */
-		tempbx = SiS_Pr->SiS_VGAHDE;
-		tempcx -= tempbx;
-		tempcx >>= 2;
-		if(modeflag & HalfDCLK) {
-		   tempbx >>= 1;
-		   tempcx >>= 1;
-		}
-		tempbx += 16;
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
+	tempbx = SiS_Pr->SiS_VGAHDE;
+	tempcx -= tempbx;
+	tempcx >>= 2;
+	if(modeflag & HalfDCLK) {
+	   tempbx >>= 1;
+	   tempcx >>= 1;
+	}
+	tempbx += 16;
 
-		temp = tempbx & 0xff;
-		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                  /* CRT2 Horizontal Display Enable End */
+	temp = tempbx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
 
-		pushbx = tempbx;
-		tempcx >>= 1;
-		tempbx += tempcx;
-		tempcx += tempbx;
-
-		if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-		   if(HwInfo->jChipType >= SIS_661) {
-		      if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ||
-		         (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
-			 if(resinfo == SIS_RI_1280x1024) {
-		            tempcx = 0x30;
-			 } else if(resinfo == SIS_RI_1600x1200) {
-			    tempcx = 0xff;
-			 }
-		      }
-		   }
+	pushbx = tempbx;
+	tempcx >>= 1;
+	tempbx += tempcx;
+	tempcx += tempbx;
 
-		   if(SiS_Pr->UseCustomMode) {
-		      tempbx = SiS_Pr->CHSyncStart + 16;
-		      tempcx = SiS_Pr->CHSyncEnd + 16;
-		      tempax = SiS_Pr->SiS_VGAHT;
-		      if(modeflag & HalfDCLK) tempax >>= 1;
-		      tempax--;
-		      if(tempcx > tempax)  tempcx = tempax;
-		   }
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-             	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-		      unsigned char cr4, cr14, cr5, cr15;
-		      if(SiS_Pr->UseCustomMode) {
-		         cr4  = SiS_Pr->CCRT1CRTC[4];
-			 cr14 = SiS_Pr->CCRT1CRTC[14];
-			 cr5  = SiS_Pr->CCRT1CRTC[5];
-			 cr15 = SiS_Pr->CCRT1CRTC[15];
-		      } else {
-		         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-			 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-			 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-			 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-		      }
-                      tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		/* (VGAHRS-3)*8 */
-                      tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; 	/* (VGAHRE-3)*8 */
-		      tempcx &= 0x00FF;
-		      tempcx |= (tempbx & 0xFF00);
-                      tempbx += 16;
-                      tempcx += 16;
-		      tempax = SiS_Pr->SiS_VGAHT;
-		      if(modeflag & HalfDCLK) tempax >>= 1;
-		      tempax--;
-		      if(tempcx > tempax)  tempcx = tempax;
-             	   }
-
-		   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-      		      tempbx = 1040;
-      		      tempcx = 1042;
-      	     	   }
+	   if(HwInfo->jChipType >= SIS_661) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+		 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+		 if(resinfo == SIS_RI_1280x1024) {
+		    tempcx = 0x30;
+		 } else if(resinfo == SIS_RI_1600x1200) {
+		    tempcx = 0xff;
+		 }
+	      }
+	   }
 
-                }
+	   if(SiS_Pr->UseCustomMode) {
+	      tempbx = SiS_Pr->CHSyncStart + 16;
+	      tempcx = SiS_Pr->CHSyncEnd + 16;
+	      tempax = SiS_Pr->SiS_VGAHT;
+	      if(modeflag & HalfDCLK) tempax >>= 1;
+	      tempax--;
+	      if(tempcx > tempax)  tempcx = tempax;
+	   }
 
-		temp = tempbx & 0xff;
-	 	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);                 /* CRT2 Horizontal Retrace Start */
-#endif  /* SIS315H */
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	      unsigned char cr4, cr14, cr5, cr15;
+	      if(SiS_Pr->UseCustomMode) {
+	         cr4  = SiS_Pr->CCRT1CRTC[4];
+		 cr14 = SiS_Pr->CCRT1CRTC[14];
+		 cr5  = SiS_Pr->CCRT1CRTC[5];
+		 cr15 = SiS_Pr->CCRT1CRTC[15];
+	      } else {
+	         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+		 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+		 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+		 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+	      }
+              tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		/* (VGAHRS-3)*8 */
+              tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; 	/* (VGAHRE-3)*8 */
+	      tempcx &= 0x00FF;
+	      tempcx |= (tempbx & 0xFF00);
+              tempbx += 16;
+              tempcx += 16;
+	      tempax = SiS_Pr->SiS_VGAHT;
+	      if(modeflag & HalfDCLK) tempax >>= 1;
+	      tempax--;
+	      if(tempcx > tempax)  tempcx = tempax;
+           }
 
-     	}  /* 315/330 series */
+	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      	      tempbx = 1040;
+      	      tempcx = 1044;   /* HWCursor bug! */
+      	   }
 
-  	/* The following is done for all bridge/chip types/series */
+        }
 
-  	tempax = tempbx & 0xFF00;
-  	tempbx = pushbx;
-  	tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
-  	tempax |= (tempbx & 0xFF00);
-  	temp = (tempax & 0xFF00) >> 8;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                        /* Overflow */
+	temp = tempbx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
+#endif  /* SIS315H */
 
-  	temp = tempcx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                        /* CRT2 Horizontal Retrace End */
+     }  /* 315/330 series */
 
-  	/* 2. Vertical setup */
+     tempax = tempbx & 0xFF00;
+     tempbx = pushbx;
+     tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
+     tempax |= (tempbx & 0xFF00);
+     temp = (tempax & 0xFF00) >> 8;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);
 
-  	tempcx = SiS_Pr->SiS_VGAVT - 1;
-  	temp = tempcx & 0x00FF;
+     temp = tempcx & 0x00FF;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                 /* CRT2 Horizontal Retrace End */
 
-	if(HwInfo->jChipType < SIS_661) {
-           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	      if(HwInfo->jChipType < SIS_315H) {
-	         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
-	               temp--;
-	            }
-                 }
-	      } else {
- 	         temp--;
+     /* 2. Vertical setup */
+
+     tempcx = SiS_Pr->SiS_VGAVT - 1;
+     temp = tempcx & 0x00FF;
+
+     if(HwInfo->jChipType < SIS_661) {
+        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	   if(HwInfo->jChipType < SIS_315H) {
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
+	            temp--;
+	         }
               }
-           } else if(HwInfo->jChipType >= SIS_315H) {
-	      temp--;
-	   }
+	   } else {
+ 	      temp--;
+           }
+        } else if(HwInfo->jChipType >= SIS_315H) {
+	   temp--;
 	}
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                        /* CRT2 Vertical Total */
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
 
-  	tempbx = SiS_Pr->SiS_VGAVDE - 1;
-  	temp = tempbx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,temp);                        /* CRT2 Vertical Display Enable End */
-
-  	temp = ((tempbx & 0xFF00) << 3) >> 8;
-  	temp |= ((tempcx & 0xFF00) >> 8);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                        /* Overflow (and HWCursor Test Mode) */
-
-	if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-           tempbx++;
-   	   tempax = tempbx;
-	   tempcx++;
-	   tempcx -= tempax;
-	   tempcx >>= 2;
-	   tempbx += tempcx;
-	   if(tempcx < 4) tempcx = 4;
-	   tempcx >>= 2;
-	   tempcx += tempbx;
-	   tempcx++;
-	} else {
-  	   tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
-  	   tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
-	}
+     tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     temp = tempbx & 0x00FF;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,temp);                 /* CRT2 Vertical Display Enable End */
 
-  	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     temp = ((tempbx & 0xFF00) << 3) >> 8;
+     temp |= ((tempcx & 0xFF00) >> 8);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow (and HWCursor Test Mode) */
+
+     if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
+        tempbx++;
+   	tempax = tempbx;
+	tempcx++;
+	tempcx -= tempax;
+	tempcx >>= 2;
+	tempbx += tempcx;
+	if(tempcx < 4) tempcx = 4;
+	tempcx >>= 2;
+	tempcx += tempbx;
+	tempcx++;
+     } else {
+  	tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
+  	tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
+     }
 
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+	if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CVSyncStart;
+	   tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
+	}
+
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr8, cr7, cr13, cr9;
 	   if(SiS_Pr->UseCustomMode) {
-	      tempbx = SiS_Pr->CVSyncStart;
-	      tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
-	   }
+	      cr8  = SiS_Pr->CCRT1CRTC[8];
+	      cr7  = SiS_Pr->CCRT1CRTC[7];
+	      cr13 = SiS_Pr->CCRT1CRTC[13];
+	      cr9  = SiS_Pr->CCRT1CRTC[9];
+	   } else {
+	      cr8  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+	      cr7  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+	      cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+	      cr9  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
+	   }
+      	   tempbx = cr8;
+      	   if(cr7 & 0x04)  tempbx |= 0x0100;
+      	   if(cr7 & 0x80)  tempbx |= 0x0200;
+      	   if(cr13 & 0x08) tempbx |= 0x0400;
+      	   tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
+    	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
 
-    	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	      unsigned char cr8, cr7, cr13, cr9;
-	      if(SiS_Pr->UseCustomMode) {
-	         cr8  = SiS_Pr->CCRT1CRTC[8];
-		 cr7  = SiS_Pr->CCRT1CRTC[7];
-		 cr13 = SiS_Pr->CCRT1CRTC[13];
-		 cr9  = SiS_Pr->CCRT1CRTC[9];
-	      } else {
-	         cr8  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
-		 cr7  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-		 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-		 cr9  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
-	      }
-      	      tempbx = cr8;
-      	      if(cr7 & 0x04)  tempbx |= 0x0100;
-      	      if(cr7 & 0x80)  tempbx |= 0x0200;
-      	      if(cr13 & 0x08) tempbx |= 0x0400;
-      	      tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
-    	   }
-  	}
-  	temp = tempbx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);           /* CRT2 Vertical Retrace Start */
-
-  	temp = ((tempbx & 0xFF00) >> 8) << 4;
-  	temp |= (tempcx & 0x000F);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);           /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
+     temp = ((tempbx & 0xFF00) >> 8) << 4;
+     temp |= (tempcx & 0x000F);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
 
-  	/* 3. Panel compensation delay */
+     /* 3. Panel delay compensation */
 
-  	if(HwInfo->jChipType < SIS_315H) {
+     if(HwInfo->jChipType < SIS_315H) {
 
 #ifdef SIS300  /* ---------- 300 series -------------- */
 
-	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	        temp = 0x20;
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   temp = 0x20;
 
-		if(HwInfo->jChipType == SIS_300) {
-		   temp = 0x10;
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  temp = 0x2c;
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-		}
-		if(SiS_Pr->SiS_VBType & VB_SIS301) {
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-		}
-		if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)     temp = 0x24;
-		if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom)       temp = 0x2c;
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 		temp = 0x08;
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-      		   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
-      		   else 					temp = 0x20;
-    	        }
-		if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		    if(ROMAddr[0x220] & 0x80) {
-		        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
-				temp = ROMAddr[0x221];
-			else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
-				temp = ROMAddr[0x222];
-		        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)
-				temp = ROMAddr[0x223];
-			else
-				temp = ROMAddr[0x224];
-			temp &= 0x3c;
-		    }
-		}
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		   if(SiS_Pr->PDC) {
-			temp = SiS_Pr->PDC & 0x3c;
-		   }
-		}
-	   } else {
-	        temp = 0x20;
-		if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) temp = 0x04;
-		}
-		if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-		    if(ROMAddr[0x220] & 0x80) {
-		        temp = ROMAddr[0x220] & 0x3c;
-		    }
-		}
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		   if(SiS_Pr->PDC) {
-		      temp = SiS_Pr->PDC & 0x3c;
-		   }
-		}
+	   if(HwInfo->jChipType == SIS_300) {
+	      temp = 0x10;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 		temp = 0x08;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
+      	      else 					temp = 0x20;
+    	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+	   	    temp = ROMAddr[0x221];
+		 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
+		    temp = ROMAddr[0x222];
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
+		    temp = ROMAddr[0x223];
+		 else
+		    temp = ROMAddr[0x224];
+		 temp &= 0x3c;
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC & 0x3c;
+	   }
+
+	} else {
+	   temp = 0x20;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
+	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         temp = ROMAddr[0x220] & 0x3c;
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
 	   }
+        }
 
-    	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x03C,temp);         /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
 
 #endif  /* SIS300 */
 
-  	} else {
+     } else {
 
 #ifdef SIS315H   /* --------------- 315/330 series ---------------*/
 
-   	   if(HwInfo->jChipType < SIS_661) {
-
-	      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(HwInfo->jChipType < SIS_661) {
 
-                 temp = 0x10;
-                 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  temp = 0x2c;
-    	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-    	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)  temp = 0x24;
-		 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom)    temp = 0x2c;
-		 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-		    temp = 0x08;
-		    if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-		       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  temp = 0x2c;
-      		       else 					temp = 0x20;
-		    }
-		 }
-		 if((SiS_Pr->SiS_VBType & VB_SIS301B302B) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-		    tempbl = 0x00;
-		    if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		       if(HwInfo->jChipType < SIS_330) {
-		          if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		       } else {
-		          if(ROMAddr[0x1bc] & 0x80) tempbl = 0xf0;
-		       }
-		    }
-		 } else {  /* LV (550/301LV checks ROM byte, other LV BIOSes do not) */
-		    tempbl = 0xF0;
-		 }
-		 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {
-		    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-		       if(SiS_Pr->PDC) {
-		          temp = SiS_Pr->PDC;
-		          tempbl = 0;
-		       }
-		    }
-		 }
+	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 
-	      } else {  /* LVDS */
+	      if(HwInfo->jChipType == SIS_740) temp = 0x03;
+	      else 		               temp = 0x00;
 
-	         if(HwInfo->jChipType == SIS_740) {
-		    temp = 0x03;
-	         } else {
-		    temp = 0x00;
-		 }
-	 	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
-		 tempbl = 0xF0;
-		 if(HwInfo->jChipType == SIS_650) {
-		    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		       if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
-		    }
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
+	      tempbl = 0xF0;
+	      if(HwInfo->jChipType == SIS_650) {
+		 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
 		 }
+	      }
 
-		 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-		    temp = 0x08;
-		    tempbl = 0;
-		    if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		       if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		    }
+	      if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
+		 temp = 0x08;
+		 tempbl = 0;
+		 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+		    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
 		 }
 	      }
 
 	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);	    /* Panel Link Delay Compensation */
+	   }
 
-	   } /* < 661 */
+	} /* < 661 */
 
-    	   tempax = 0;
-    	   if (modeflag & DoubleScanMode) tempax |= 0x80;
-    	   if (modeflag & HalfDCLK)       tempax |= 0x40;
-    	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+    	tempax = 0;
+    	if (modeflag & DoubleScanMode) tempax |= 0x80;
+    	if (modeflag & HalfDCLK)       tempax |= 0x40;
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
 #endif  /* SIS315H */
 
-  	}
-
-     }  /* Slavemode */
+     }
 
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+  }  /* Slavemode */
 
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
         /* For 301BDH with LCD, we set up the Panel Link */
-        if( (SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) {
-
-	    SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex,
-	                       HwInfo, RefreshRateTableIndex);
-
-        } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-
-    	    SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex,
-	                      HwInfo, RefreshRateTableIndex);
-        }
-
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+    	SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     }
+  } else {
+     if(HwInfo->jChipType < SIS_315H) {
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
      } else {
-
-        if(HwInfo->jChipType < SIS_315H) {
-
-	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex,
-	                        HwInfo, RefreshRateTableIndex);
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+           if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+    	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
+           }
 	} else {
-
-	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-              if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-    	          SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,
-	                              HwInfo,RefreshRateTableIndex);
-              }
-	   } else {
-	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,
-	                         HwInfo,RefreshRateTableIndex);
-	   }
-
+	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
 	}
-
      }
-  } /* LCDA */
+  }
 }
 
 /*********************************************/
@@ -6978,9 +6561,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
 static UCHAR *
 SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
    const UCHAR  *tableptr = NULL;
-   USHORT a, b, p = 0;
+   USHORT       a, b, p = 0;
 
    a = SiS_Pr->SiS_VGAHDE;
    b = SiS_Pr->SiS_HDE;
@@ -6989,62 +6571,32 @@ SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr
       b = SiS_Pr->SiS_VDE;
    }
 
-   if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
-
-      if(a < b) {
-         p = ROMAddr[0x278] | (ROMAddr[0x279] << 8);
-      } else if(a == b) {
-         p = ROMAddr[0x27a] | (ROMAddr[0x27b] << 8);
-      } else {
-         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	    p = ROMAddr[0x27e] | (ROMAddr[0x27f] << 8);
-	 } else {
-	    p = ROMAddr[0x27c] | (ROMAddr[0x27d] << 8);
-	 }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	 p = ROMAddr[0x280] | (ROMAddr[0x281] << 8);
-	    else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) p = ROMAddr[0x282] | (ROMAddr[0x283] << 8);
-	    else 				 	 p = ROMAddr[0x284] | (ROMAddr[0x285] << 8);
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    p = ROMAddr[0x286] | (ROMAddr[0x287] << 8);
-	 }
-	 do {
-	    if((ROMAddr[p] | ROMAddr[p+1] << 8) == a) break;
-	    p += 0x42;
-	 } while((ROMAddr[p] | ROMAddr[p+1] << 8) != 0xffff);
-	 if((ROMAddr[p] | ROMAddr[p+1] << 8) == 0xffff) p -= 0x42;
-      }
-      p += 2;
-      return(&ROMAddr[p]);
-
+   if(a < b) {
+      tableptr = SiS_Part2CLVX_1;
+   } else if(a == b) {
+      tableptr = SiS_Part2CLVX_2;
    } else {
-
-      if(a < b) {
-         tableptr = SiS_Part2CLVX_1;
-      } else if(a == b) {
-         tableptr = SiS_Part2CLVX_2;
+      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	 tableptr = SiS_Part2CLVX_4;
       } else {
-         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	    tableptr = SiS_Part2CLVX_4;
-	 } else {
-	    tableptr = SiS_Part2CLVX_3;
-	 }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	 tableptr = SiS_Part2CLVX_3;
-	    else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
-	    else 				         tableptr = SiS_Part2CLVX_5;
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    tableptr = SiS_Part2CLVX_6;
-	 }
-	 do {
-	    if((tableptr[p] | tableptr[p+1] << 8) == a) break;
-	    p += 0x42;
-	 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
-	 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
+	 tableptr = SiS_Part2CLVX_3;
       }
-      p += 2;
-      return((UCHAR *)&tableptr[p]);
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	tableptr = SiS_Part2CLVX_3;
+	 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) 	tableptr = SiS_Part2CLVX_3;
+	 else 				         	tableptr = SiS_Part2CLVX_5;
+
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	 tableptr = SiS_Part2CLVX_6;
+      }
+      do {
+	 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
+	 p += 0x42;
+      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
+      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
    }
+   p += 2;
+   return((UCHAR *)&tableptr[p]);
 }
 
 static void
@@ -7055,7 +6607,7 @@ SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr,
    int i, j;
    UCHAR temp;
 
-   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return; 
 
    tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
    for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
@@ -7072,49 +6624,97 @@ SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr,
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
 }
 
-static void
+static BOOLEAN
 SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 		    USHORT RefreshRateTableIndex,USHORT *CRT2Index,
 		    USHORT *ResIndex,PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx,tempal;
-
+  
+  if(HwInfo->jChipType < SIS_315H) return FALSE;
+  
   if(ModeNo <= 0x13)
-      	tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   else
-      	tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  tempbx = SiS_Pr->SiS_LCDResInfo;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx += 16;
-  else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx += 32;
+  (*ResIndex) &= 0x3f;
+  (*CRT2Index) = 0;
 
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tempbx = 100;
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx = 101;
-  	else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 102;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        (*CRT2Index) = 200;
      }
-  } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-           tempbx = 103;
-           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx = 104;
-  	   else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 105;
-	}
-     }
-  }  else if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 106;
+  }
+
+  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
      }
   }
+  return(((*CRT2Index) != 0));
+}
+#endif
+
+#ifdef SIS300
+static void
+SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
+{
+   USHORT tempcx;
+   const UCHAR atable[] = {
+       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
+       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
+   };
+
+   if(!SiS_Pr->UseCustomMode) {
+      if( ( ( (HwInfo->jChipType == SIS_630) ||
+              (HwInfo->jChipType == SIS_730) ) &&
+            (HwInfo->jChipRevision > 2) )  &&
+          (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+          (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
+          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+         if(ModeNo == 0x13) {
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+         } else {
+            if((crt2crtc & 0x3F) == 4) {
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+            }
+         }
+      }
+
+      if(HwInfo->jChipType < SIS_315H) {
+         if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+            crt2crtc &= 0x1f;
+            tempcx = 0;
+            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                  tempcx += 7;
+               }
+            }
+            tempcx += crt2crtc;
+            if(crt2crtc >= 4) {
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+            }
 
-  *CRT2Index = tempbx;
-  *ResIndex = tempal & 0x3F;
+            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                  if(crt2crtc == 4) {
+                     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+                  }
+               }
+            }
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+         }
+      }
+   }
 }
-#endif
 
-#ifdef SIS300
 /* For ECS A907. Highly preliminary. */
 static void
 SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
@@ -7183,15 +6783,81 @@ SiS_SetTVSpecial(SiS_Private *SiS_Pr, US
 	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
 	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
 	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
 	   } else {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x15);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
 	   }
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
 	}
      }
   } else {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x21);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x5a);
+     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
+        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
+     } else {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
+     }
+  }
+}
+
+static void
+SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
+{
+  USHORT temp;
+
+  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+     if(SiS_Pr->SiS_VGAVDE == 525) {
+	temp = 0xc3;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
+     } else if(SiS_Pr->SiS_VGAVDE == 420) {
+	temp = 0x4d;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+     }
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
+	if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
+	   /* Not always for LV, see SetGrp2 */
+	}
+	temp = 1;
+	if(ModeNo <= 0x13) temp = 3;
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
+     }
+#if 0
+     /* 651+301C, for 1280x768 - do I really need that? */
+     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
+        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+	   if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
+	      ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
+	      SiS_SetReg(SiS_Part2Port,0x01,0x2b);
+	      SiS_SetReg(SiS_Part2Port,0x02,0x13);
+	      SiS_SetReg(SiS_Part2Port,0x04,0xe5);
+	      SiS_SetReg(SiS_Part2Port,0x05,0x08);
+	      SiS_SetReg(SiS_Part2Port,0x06,0xe2);
+	      SiS_SetReg(SiS_Part2Port,0x1c,0x21);
+	      SiS_SetReg(SiS_Part2Port,0x1d,0x45);
+	      SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x20,0x00);
+	      SiS_SetReg(SiS_Part2Port,0x21,0xa9);
+	      SiS_SetReg(SiS_Part2Port,0x23,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x25,0x04);
+	   }
+	}
+     }
+#endif
   }
 }
 
@@ -7200,36 +6866,26 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 	      PSIS_HW_INFO HwInfo)
 {
   USHORT      i, j, tempax, tempbx, tempcx, temp;
-  USHORT      push1, push2, modeflag, crt2crtc;
+  USHORT      push1, push2, modeflag, crt2crtc, bridgeoffset;
   ULONG       longtemp, tempeax;
   const       UCHAR *PhasePoint;
   const       UCHAR *TimingPoint;
 #ifdef SIS315H
   USHORT      resindex, CRT2Index;
   const       SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
-#endif
-#ifdef SIS300
-  const UCHAR atable[] = {
-       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
-       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
-  };
-#endif  
 
-#ifdef SIS315H   
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 #endif
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     crt2crtc = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	crt2crtc = 0;
-     } else {
-        modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
   temp = 0;
@@ -7238,26 +6894,25 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
 
-  /* Disable SVIDEO and CVBS signal */
-  if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-     (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-        temp |= 0x0c;
-     }
-  }
+  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) 	      temp |= 0x10;
+
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
 
   PhasePoint  = SiS_Pr->SiS_PALPhase;
   TimingPoint = SiS_Pr->SiS_PALTiming;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
+     TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
         TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-           if(modeflag & Charx8Dot) TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
-           else                     TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
+	   TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
+#if 0
+           if(!(modeflag & Charx8Dot))  TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
+#endif
         }
-     } else TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
+     }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 
@@ -7267,41 +6922,32 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 
      PhasePoint = SiS_Pr->SiS_NTSCPhase;
 
-  } else {
-
-     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+  } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
 
-        TimingPoint = SiS_Pr->SiS_PALTiming;
-        PhasePoint  = SiS_Pr->SiS_PALPhase;
+     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
+         ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+	   (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+        PhasePoint = SiS_Pr->SiS_PALPhase2;
+     }
 
-        if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-            ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-	      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-           PhasePoint = SiS_Pr->SiS_PALPhase2;
-        }
+  } else {
 
-     } else {
+     TimingPoint = SiS_Pr->SiS_NTSCTiming;
+     PhasePoint  = SiS_Pr->SiS_NTSCPhase;
+     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
+	PhasePoint = SiS_Pr->SiS_PALPhase;
+     }
 
-        temp |= 0x10;
-        TimingPoint = SiS_Pr->SiS_NTSCTiming;
-        PhasePoint  = SiS_Pr->SiS_NTSCPhase;
+     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
+	 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+	   (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+        PhasePoint = SiS_Pr->SiS_NTSCPhase2;
 	if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-	   PhasePoint = SiS_Pr->SiS_PALPhase;
+	   PhasePoint = SiS_Pr->SiS_PALPhase2;
 	}
-
-        if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-	    ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-	      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-           PhasePoint = SiS_Pr->SiS_NTSCPhase2;
-	   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-	      PhasePoint = SiS_Pr->SiS_PALPhase2;
-	   }
-        }
-
      }
 
   }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
 
   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
      PhasePoint = SiS_Pr->SiS_PALMPhase;
@@ -7356,7 +7002,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) 	tempax = 950;
   else if(SiS_Pr->SiS_TVMode & TVSetPAL)      	tempax = 520;
-  else 			            		tempax = 440;
+  else 			            		tempax = 440; /* NTSC, YPbPr 525, 750 */
 
   if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
       ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
@@ -7372,10 +7018,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
      temp = tempax + (USHORT)TimingPoint[1];
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
-     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
+     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x19);
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x52);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 19 */
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 52 */
         } else {
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
@@ -7388,10 +7034,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx--;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,temp);
-  temp = (tempcx & 0xFF00) >> 8;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,(tempcx & 0xff));
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
 
   tempcx++;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx++;
@@ -7400,24 +7044,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   push1 = tempcx;
 
   tempcx += 7;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempcx -= 4;
-  }
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,temp);
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
 
-  tempbx = TimingPoint[j] | ((TimingPoint[j+1]) << 8);
+  tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
   tempbx += tempcx;
 
-  push2 = tempbx;
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
   temp = ((tempbx & 0xFF00) >> 8) << 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,temp);
 
-  tempbx = push2;
-
   tempbx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      tempbx -= 4;
@@ -7427,32 +7063,27 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp);
 
   j += 2;
-  tempcx += ((TimingPoint[j] | ((TimingPoint[j+1]) << 8)));
+  tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
   temp = tempcx & 0x00FF;
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,temp);
   temp = ((tempcx & 0xFF00) >> 8) << 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,temp);
 
   tempcx += 8;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempcx -= 4;
-  }
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,temp);
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
 
   tempcx = push1;
 
   j += 2;
   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
 
   tempcx -= 11;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
      tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
   }
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
 
   tempbx = SiS_Pr->SiS_VDE;
   if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
@@ -7488,9 +7119,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {   /* SetFlag?? */
-	         if(ModeNo == 0x03) temp++;
-	      }
+	      if(ModeNo == 0x03) temp++;
 	   }
         }
      }
@@ -7499,20 +7128,19 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 
   temp = (tempcx >> 8) & 0x0F;
   temp |= (((tempbx >> 8) << 6) & 0xC0);
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750 | SetCRT2ToSCART))) {
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
      temp |= 0x10;
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x20;
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
 
-  if((HwInfo->jChipType > SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
-           if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ) {
-              SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
-	   }
-        }
+  /* TEST qqqq */
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+     for(i=0x01, j=0; i<=0x2D; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
+     }
+     for(i=0x39; i<=0x45; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
      }
   }
 
@@ -7524,21 +7152,27 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 	}
      }
      tempbx -= 3;
-     if(HwInfo->jChipType >= SIS_661) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  /* Why not 301B/LV? */
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  /* Why not 301B/LV? */
+        if(HwInfo->jChipType >= SIS_661) {
            temp = 0;
 	   if(tempcx & 0x0400) temp |= 0x20;
 	   if(tempbx & 0x0400) temp |= 0x40;
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x10,temp);
+	} else {
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+              if((SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+                 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+	         (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
+                 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
+	      }
+           }
 	}
      }
      tempbx &= 0x03ff;
      temp = ((tempbx & 0xFF00) >> 8) << 5;
      temp |= 0x18;
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,temp);
-
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
   }
 
   tempbx = 0;
@@ -7597,10 +7231,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
         tempbx = 0x0369;
         tempcx = 0x0061;
      }
-     temp = (tempbx & 0x00FF) ;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,temp);
-     temp = (tempcx & 0x00FF) ;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,temp);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
      temp = (tempcx & 0x0300) >> (8 - 2);
      temp |= ((tempbx >> 8) & 0x03);
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
@@ -7644,13 +7276,12 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   tempbx = SiS_Pr->SiS_HDE;
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   tempbx--;			         	/* RHACTE = HDE - 1 */
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
   temp = (tempbx & 0xFF00) >> 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp);
 
   temp = 0x01;
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(SiS_Pr->SiS_VGAHDE >= 1024) {
            temp = 0x02;
@@ -7665,14 +7296,12 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
 
   tempbx = SiS_Pr->SiS_VDE - 1;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
   temp = ((tempbx & 0xFF00) >> 8) & 0x07;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp);
 
   tempcx = SiS_Pr->SiS_VT - 1;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
 
   temp = ((tempcx & 0xFF00) >> 8) << 5;
 
@@ -7683,31 +7312,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
      }
   }
 
-  /* Must do special for Compaq1280; Acer1280 OK, Clevo1400 OK, COMPAL1400 OK */
-  /* Compaq1280 panel loses sync if using CR37 sync info. */
-  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-     if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
-	if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-	      temp |= ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	   }
-	} else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
-	          (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)) {
-	   temp |= 0x03;
-	} else {
-           temp |= (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) >> 6);
-	   temp |= 0x08;
-	   if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) temp |= 0x04;
-	}
-     } else {
-        if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-	   temp |= ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	}
-     }
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1A,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
 
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
@@ -7715,154 +7320,13 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
 
-#if 0  /* Use the 315/330 series code for now */
-  if((HwInfo->jChipType >= SIS_661)          &&
-     (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
-     (ROMAddr && SiS_Pr->SiS_UseROM)) {
-
-      /* This is done for the LVDS bridges only, since
-       * the TMDS panels already work correctly with
-       * the old code. Besides, we only do that if
-       * we can get the data from the ROM, I am tired
-       * of carrying a lot of tables around.
-       */
-
-#ifdef SIS315H 							/* ------------ 661/741/760 series --------- */
-      UCHAR *myptr = NULL, myptr1 = NULL;
-
-      myptr = (UCHAR *)GetLCDPtr661(SiS_Pr, HwInfo, 6, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      myptr1 = (UCHAR *)GetLCDStructPtr661(SiS_Pr, HwInfo);
-
-      tempbx = (myptr[3] | (myptr[4] << 8)) & 0x0fff;
-      tempcx = SiS_Pr->PanelYRes;
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-         tempcx = SiS_Pr->SiS_VDE;
-      }
-
-      tempcx += tempbx;
-      if(tempcx >= SiS_Pr->SiS_VT) tempcx -= SiS_Pr->SiS_VT;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempbx);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempcx);
-
-      tempcx &= 0x07ff;
-      tempbx &= 0x07ff;
-      temp = (tempcx >> 8) << 3;
-      temp |= (tempbx >> 8);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
-
-      tempbx = (myptr[4] | (myptr[5] << 8)) >> 4;
-      tempcx = myptr1[6];
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempcx = myptr[7];
-
-      tempcx += tempbx;
-      if(tempcx >= SiS_Pr->SiS_VT) tempcx -= SiS_Pr->SiS_VT;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);
-      temp = tempcx & 0x000f;
-      temp |= ((tempbx & 0x0f00) >> 4);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
-
-      tempax = SiS_Pr->SiS_HT;
-      tempbx = (myptr[0] | (myptr[1] << 8)) & 0x0fff;
-      tempcx = SiS_Pr->PanelXRes;
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempcx = SiS_Pr->SiS_HDE;
-
-      if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-         tempax >>= 1;
-	 tempbx >>= 1;
-	 tempcx >>= 1;
-      }
-      if(SiS_Pr->SiS_VBType & VB_SIS302LV)                 tempbx++;
-      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) tempbx++;
-
-      tempcx += tempbx;
-      if(tempcx >= tempax) tempcx -= tempax;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,tempbx);
-      temp = ((tempbx & 0xff00) >> 8) << 4;
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x20,temp);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempcx);
-      temp = tempcx >> 8;
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x25,temp);
-
-      tempax = SiS_Pr->SiS_HT;
-      tempbx = (myptr[1] | (myptr[2] << 8)) >> 4;
-      tempcx = myptr1[5];
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-         tempcx = myptr[6];
-      }
-      if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-         tempax >>= 1;
-	 tempbx >>= 1;
-	 tempcx >>= 1;
-      }
-      if(SiS_Pr->SiS_VBType & VB_SIS302LV) tempbx++;
-
-      tempcx += tempbx;
-      if(tempcx >= tempax) tempcx -= tempax;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1c,tempbx);
-      temp = (tempbx & 0x0f00) >> 4;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1d,0x0f,temp);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempcx);
-
-      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-         if(SiS_Pr->SiS_VGAVDE == 525) {
-	    temp = 0xc3;
-	    if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	       temp++;
-	       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-	 } else if(SiS_Pr->SiS_VGAVDE == 420) {
-	    temp = 0x4d;
-	    if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	       temp++;
-	       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	 }
-      }
-
-#endif
-
-  } else
-#endif
-         if((HwInfo->jChipType >= SIS_315H)                    &&
-            (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)            &&
-            ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) ) {
-
-#ifdef SIS315H 							/* ------------- 315/330 series ------------ */
-
-      SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &CRT2Index, &resindex, HwInfo);
-
+#ifdef SIS315H
+  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+                          			&CRT2Index, &resindex, HwInfo)) {
       switch(CRT2Index) {
-        case Panel_1024x768      : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;  break;  /* "Normal" */
-        case Panel_1280x1024     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_1; break;
-	case Panel_1400x1050     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_1; break;
-	case Panel_1600x1200     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_1; break;
-        case Panel_1024x768  + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;  break;  /* Non-Expanding */
-        case Panel_1280x1024 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_2; break;
-	case Panel_1400x1050 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_2; break;
-	case Panel_1600x1200 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_2; break;
-        case Panel_1024x768  + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;  break;  /* VESA Timing */
-        case Panel_1280x1024 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_3; break;
-	case Panel_1400x1050 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_3; break;
-	case Panel_1600x1200 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_3; break;
-	case 100:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_1; break;  /* Custom */
-	case 101:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_2; break;
-	case 102:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_3; break;
-	case 103:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_1; break;    /* Custom */
-	case 104:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_2; break;
-	case 105:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_3; break;
-	case 106:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Asus1024x768_3; break;
-	default:                   CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;  break;
+        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
+	case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
+	default:  CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;   break;
       }
 
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
@@ -7879,58 +7343,34 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
 
-      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        if(SiS_Pr->SiS_VGAVDE == 525) {
-	  temp = 0xc3;
-	  if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	     temp++;
-	     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
-	  }
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-	} else if(SiS_Pr->SiS_VGAVDE == 420) {
-	  temp = 0x4d;
-	  if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	     temp++;
-	     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
-	  }
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	}
-     }
+      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   /* See Sync above, 0x1a */
-	   temp = 1;
-	   if(ModeNo <= 0x13) temp = 3;
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
-	}
-     }
+      
+  } else {
 #endif
-
-  } else {   /* ------ 300 series and other bridges, other LCD resolutions ------ */
-
-      /* Using this on the 301B with an auto-expanding 1024 panel (CR37=1) makes
-       * the panel scale at modes < 1024 (no black bars); if the panel is non-expanding,
-       * the bridge scales all modes to 1024.
-       * !!! Malfunction at 640x480 and 640x400 when panel is auto-expanding - black screen !!!
-       */
-
-    tempcx = SiS_Pr->SiS_VT;
-    tempbx = SiS_Pr->PanelYRes;
+	  
+    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
+    /*             Clevo dual-link 1024x768 */
+    /* 		   Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
+    /*		   Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
 
     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-       tempbx = SiS_Pr->SiS_VDE - 1;
-       tempcx--;
-    }
-
-    tempax = 1;
-    if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-       if(tempbx != SiS_Pr->SiS_VDE) {
-          tempax = tempbx;
-          if(tempax < SiS_Pr->SiS_VDE) {
-             tempax = 0;
-             tempcx = 0;
+       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
+          tempbx = SiS_Pr->SiS_VDE - 1;
+          tempcx = SiS_Pr->SiS_VT - 1;
+       } else {
+          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+	  tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+       }
+    } else {
+       tempbx = SiS_Pr->PanelYRes;
+       tempcx = SiS_Pr->SiS_VT;
+       tempax = 1;
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          tempax = SiS_Pr->PanelYRes;
+	  /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
+          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
+             tempax = tempcx = 0;
           } else {
              tempax -= SiS_Pr->SiS_VDE;
           }
@@ -7946,23 +7386,46 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
 #endif
 
-    temp = tempcx & 0x00FF;   				/* RVEQ1EQ=lcdvdes */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,temp);
-    temp = tempbx & 0x00FF;   				/* RVEQ2EQ=lcdvdee */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);	/* lcdvdes  */
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);	/* lcdvdee  */
 
     temp = ((tempbx & 0xFF00) >> 8) << 3;
     temp |= ((tempcx & 0xFF00) >> 8);
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
-    tempbx = SiS_Pr->SiS_VT;    /* push2; */
-    tempax = SiS_Pr->SiS_VDE;   /* push1; */
-    tempcx = (tempbx - tempax) >> 4;
-    tempbx += tempax;
-    tempbx >>= 1;
-    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx -= 10;
+    tempax = SiS_Pr->SiS_VDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       tempax = SiS_Pr->PanelYRes;
+    }
+    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+	  tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
+       }
+    }
+
+    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
+    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
+             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
+	     if(tempax % 4) { tempax >>= 2; tempax++; }
+	     else           { tempax >>= 2;           }
+             tempbx -= (tempax - 1);
+	  } else tempbx -= 10;
+       }
+    }
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+       tempbx++;
+       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
+          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+	     tempbx = 770;
+	     tempcx = 3;
+	  }
+       }
+    }
 
-    /* non-expanding: lcdvrs = tempbx = ((VT + VDE) / 2) - 10 */
+    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
 
     if(SiS_Pr->UseCustomMode) {
        tempbx = SiS_Pr->CVSyncStart;
@@ -7972,8 +7435,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
     xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;   				/* RTVACTEE = lcdvrs */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
 
     temp = ((tempbx & 0xFF00) >> 8) << 4;
     tempbx += (tempcx + 1);
@@ -7990,149 +7452,106 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
 
-    /* Code from 630/301B (I+II) BIOS */
-
 #ifdef SIS300
-    if(!SiS_Pr->UseCustomMode) {
-       if( ( ( (HwInfo->jChipType == SIS_630) ||
-               (HwInfo->jChipType == SIS_730) ) &&
-             (HwInfo->jChipRevision > 2) )  &&
-           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) &&
-           (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
-           (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-          if(ModeNo == 0x13) {
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
-          } else {
-             if((crt2crtc & 0x3F) == 4) {
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
-             }
-          }
-       }
-
-       if(HwInfo->jChipType < SIS_315H) {
-          if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
-             crt2crtc &= 0x1f;
-             tempcx = 0;
-             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                   tempcx += 7;
-                }
-             }
-             tempcx += crt2crtc;
-             if(crt2crtc >= 4) {
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
-             }
+    SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
+#endif
 
-             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                   if(crt2crtc == 4) {
-                      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
-                   }
-                }
-             }
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
-          }
+    bridgeoffset = 7;
+    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)          bridgeoffset += 2;
+    if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
+    if(SiS_IsDualLink(SiS_Pr, HwInfo))        		 bridgeoffset++;
+
+    temp = 0;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+	  if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
        }
     }
-#endif
-
-    tempcx = (SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE) >> 2;     /* (HT - HDE) >> 2 */
-    tempbx = SiS_Pr->SiS_HDE + 7;            		  /* lcdhdee         */
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-       tempbx += 2;
+    temp += bridgeoffset;
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	    /* lcdhdes[7:0] */
+    temp = (temp >> 4) & 0xf0;
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,temp);  /* lcdhdes [11:8] */
+
+    tempcx = SiS_Pr->SiS_HT;
+    tempax = tempbx = SiS_Pr->SiS_HDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          tempax = SiS_Pr->PanelXRes;
+          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+       }
+    }
+    if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
+       tempcx >>= 1;
+       tempbx >>= 1;
+       tempax >>= 1;		
     }
-    push1 = tempbx;
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;    			          /* RHEQPLE = lcdhdee */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,temp);
-    temp = (tempbx & 0xFF00) >> 8;
+    tempbx += bridgeoffset;
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
+    temp = (tempbx >> 8) & 0x0f;
     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp);
 
-    temp = 7;
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-       temp += 2;
-    }
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	  /* RHBLKE = lcdhdes[7:0] */
-    SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x20,0x0F);	  /* lcdhdes [11:8] */
+    tempcx = (tempcx - tempax) >> 2;
 
     tempbx += tempcx;
     push2 = tempbx;
 
-    if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncStart + 7;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          tempbx += 2;
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
+	  }
        }
     }
 
+    if(SiS_Pr->UseCustomMode) {
+       tempbx = SiS_Pr->CHSyncStart;
+       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       tempbx += bridgeoffset;
+    }
+
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;            		          /* RHBURSTS = lcdhrs */
-    if(!SiS_Pr->UseCustomMode) {
-       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-          if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-             if(SiS_Pr->SiS_HDE == 1280) temp = 0x47;
-          }
-       }
-    }
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
     temp = (tempbx & 0x0F00) >> 4;
     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp);
 
     tempbx = push2;
+
     tempcx <<= 1;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
+    }
     tempbx += tempcx;
 
     if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncEnd + 7;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          tempbx += 2;
-       }
+       tempbx = SiS_Pr->CHSyncEnd;
+       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       tempbx += bridgeoffset;
     }
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;            		          /* RHSYEXP2S = lcdhre */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);	    /* lcdhre */
 
-    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-       if(SiS_Pr->SiS_VGAVDE == 525) {
-          if(SiS_Pr->SiS_ModeType <= ModeVGA)
-    	     temp=0xC6;
-          else
-       	     temp=0xC3;
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xB3);
-       } else if(SiS_Pr->SiS_VGAVDE == 420) {
-          if(SiS_Pr->SiS_ModeType <= ModeVGA)
-	     temp=0x4F;
-          else
-       	     temp=0x4D;
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-       }
-    }
+    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
 #ifdef SIS300
-    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex,
-                        RefreshRateTableIndex, ModeNo);
+    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
 #endif
-
-  } /* HwInfo */
+#ifdef SIS315H
+  } /* CRT2-LCD from table */
+#endif  
 }
 
 /*********************************************/
@@ -8143,26 +7562,14 @@ static void
 SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo)
 {
-  USHORT modeflag, i;
-  const UCHAR  *tempdi;
+  USHORT 	i;
+  const UCHAR  	*tempdi;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 
-  if(ModeNo<=0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
-  }
-
 #ifndef SIS_CP
   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
-#endif
-
-#ifdef SIS_CP
+#else
   SIS_CP_INIT301_CP
 #endif
 
@@ -8185,9 +7592,6 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHOR
      tempdi = SiS_Pr->SiS_HiTVGroup3Data;
      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
         tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
-        if(!(modeflag & Charx8Dot)) {
-           tempdi = SiS_Pr->SiS_HiTVGroup3Text;
-        }
      }
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
@@ -8196,7 +7600,7 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHOR
      }
   }
   if(tempdi) {
-     for(i=0; i<=0x3E; i++){
+     for(i=0; i<=0x3E; i++) {
         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
      }
      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
@@ -8206,17 +7610,92 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHOR
      }
   }
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) {
 #ifdef SIS_CP
-     SIS_CP_INIT301_CP2
+  SIS_CP_INIT301_CP2
 #endif
-  }
 }
 
 /*********************************************/
 /*         SET PART 4 REGISTER GROUP         */
 /*********************************************/
 
+#ifdef SIS315H
+static void
+SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
+{
+   USHORT temp, temp1, temp2;
+
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
+   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
+   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
+   temp = (USHORT)((int)(temp) + shift);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
+   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
+}
+
+static void
+SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                    USHORT ModeNo, USHORT ModeIdIndex)
+{
+   USHORT temp, temp1, resinfo = 0;
+
+   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+
+   if(ModeNo > 0x13) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
+
+   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
+   if(!(temp & 0x01)) {
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
+      if(HwInfo->jChipType < SIS_661) {
+         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
+      }
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
+      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
+      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
+      else					   temp = 0x0402;
+      if(HwInfo->jChipType >= SIS_661) {
+         temp1 = 0;
+	 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
+	 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
+      } else {
+         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
+	 if(temp1 == 0x01) temp |= 0x01;
+	 if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+
+      if(HwInfo->jChipType >= SIS_661) { 		/* ? */
+         if(SiS_Pr->SiS_TVMode & TVAspect43) {
+            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	       if(resinfo == SIS_RI_1024x768) {
+	          SiS_ShiftXPos(SiS_Pr, 97);
+	       } else {
+	          SiS_ShiftXPos(SiS_Pr, 111);
+	       }
+	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+	       SiS_ShiftXPos(SiS_Pr, 136);
+	    }
+         }
+      }
+   }
+}
+#endif
+
 static void
 SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                  USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
@@ -8254,7 +7733,6 @@ SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USH
   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
 }
 
-/* Set 301 VGA2 registers */
 static void
 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   	      USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
@@ -8265,14 +7743,12 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
   if(HwInfo->jChipType >= SIS_315H) {
@@ -8298,7 +7774,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
 #ifdef SET_EMI
 	   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	   }
 #endif
@@ -8311,29 +7787,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,temp);
 
   tempbx = SiS_Pr->SiS_RVBHCMAX;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
 
-  temp2 = (((tempbx & 0xFF00) >> 8) << 7) & 0x00ff;
+  temp2 = (tempbx >> 1) & 0x0080;
 
   tempcx = SiS_Pr->SiS_VGAHT - 1;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
 
-  temp = (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
-  temp2 |= temp;
+  temp2 |= (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
 
   tempcx = SiS_Pr->SiS_VGAVT - 1;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV))  tempcx -= 5;
-
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,temp);
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
 
-  temp = temp2 | ((tempcx & 0xFF00) >> 8);
+  temp = temp2 | (tempcx >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
 
   tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK)  tempbx >>= 1;
+  if(modeflag & HalfDCLK) tempbx >>= 1;
   if(HwInfo->jChipType >= SIS_661) {
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   }
@@ -8370,7 +7841,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
   }
 
   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
         temp |= 0x0A;
   }
 
@@ -8420,14 +7891,11 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	if(tempax > 800) tempax -= 800;
-     } else {
+     } else /* if(SiS_Pr->SiS_VBInfo & TvNoHiviNoYPbPr) */ {    /* 651+301C */
         if(tempax > 800) {
 	   tempbx = 8;
-           if(tempax == 1024)
-	      tempax *= 25;
-           else
-	      tempax *= 20;
-
+           if(tempax == 1024) tempax *= 25;
+           else	              tempax *= 20;
 	   temp = tempax % 32;
 	   tempax /= 32;
 	   tempax--;
@@ -8436,9 +7904,10 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
      }
      tempax--;
      temp = ((tempax & 0xFF00) >> 8) & 0x03;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* From 1.10.7w */
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) {	/* From 1.10.7w */
 	if(ModeNo > 0x13) {					/* From 1.10.7w */
 	   if(resinfo == SIS_RI_1024x768) tempax = 0x1f;	/* From 1.10.7w */
+	   /* ax normally 0x1e */				/* From 1.10.7w */
 	}							/* From 1.10.7w */
      }								/* From 1.10.7w */
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax & 0x00FF);
@@ -8489,7 +7958,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
 #ifdef SET_EMI
 	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	}
 #endif
@@ -8504,7 +7973,6 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
 /*         SET PART 5 REGISTER GROUP         */
 /*********************************************/
 
-/* Set 301 Palette address port registers */
 static void
 SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo)
@@ -8514,7 +7982,7 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHOR
 
   if(SiS_Pr->SiS_ModeType == ModeVGA) {
      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
-        SiS_EnableCRT2(SiS_Pr);
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
         SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
      }
   }
@@ -8532,11 +8000,8 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USH
   USHORT ResIndex,DisplayType;
   const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
+  if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
@@ -8544,7 +8009,9 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USH
      return;
 
   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &ResIndex, &DisplayType))) return;
+                          &ResIndex, &DisplayType))) {
+     return;
+  }
 
   if(HwInfo->jChipType < SIS_315H) {
      if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
@@ -8552,16 +8019,16 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USH
 
   switch(DisplayType) {
     case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1;           break;
-    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
-    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
-    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
-    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
-    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
-    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
-    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
-    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
-    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
-    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
+    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
+    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
+    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
+    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
+    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
+    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
+    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
+    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
+    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
+    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
     case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H;       break;
     case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1;           break;
     case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H;         break;
@@ -8600,7 +8067,7 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USH
     default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
   }
 
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);                        /*unlock cr0-7  */
+  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
 
   tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
@@ -8635,12 +8102,6 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USH
   tempah <<= 5;
   if(modeflag & DoubleScanMode)  tempah |= 0x080;
   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
-
-  /* 650/LVDS BIOS - doesn't make sense */
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(modeflag & HalfDCLK)
-        SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-  }
 }
 
 /*********************************************/
@@ -8655,7 +8116,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USH
   USHORT clkbase, vclkindex=0;
   UCHAR  sr2b, sr2c;
 
-  if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) || (SiS_Pr->SiS_IF_DEF_TRUMPION == 1)) {
+  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
         if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
 	   RefreshRateTableIndex--;
@@ -8672,7 +8133,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USH
   sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     if(SiS_Pr->SiS_UseROM) {
 	if(ROMAddr[0x220] & 0x01) {
            sr2b = ROMAddr[0x227];
 	   sr2c = ROMAddr[0x228];
@@ -8687,7 +8148,6 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USH
      }
   }
 
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
@@ -8712,9 +8172,9 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHO
   const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
 
   if(ModeNo <= 0x13)
-    	tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   else
-    	tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
   TVType = 0;
   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
@@ -8732,16 +8192,16 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHO
 	}
   }
   switch(TVType) {
-    	case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
-    	case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
-    	case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
-    	case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-	case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
-    	case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
-    	case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
-    	case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
-	case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
-	default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+     case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+     case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+     case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
+     case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+     case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+     case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+     case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+     case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+     case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+     default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
   }
   resindex = tempcl & 0x3F;
 
@@ -9013,21 +8473,21 @@ SiS_ChrontelPowerSequencing(SiS_Private 
   /* Set up Power up/down timing */
 
   if(HwInfo->jChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
         else    			          tableptr = table1024_740;
-     } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
 	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
         else					  tableptr = table1400_740;
      } else return;
   } else {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         tableptr = table1024_650;
-     } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
         tableptr = table1400_650;
      } else return;
   }
@@ -9063,45 +8523,35 @@ SiS_SetCH701xForLCD(SiS_Private *SiS_Pr,
   int i;
 
   if(HwInfo->jChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        tableptr = table1024_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tableptr = table1280_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-        tableptr = table1400_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-        tableptr = table1600_740;
-     } else return;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        tableptr = table1024_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tableptr = table1280_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-        tableptr = table1400_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-        tableptr = table1600_650;
-     } else return;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
+     else return;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
+     else return;
   }
 
   tempbh = SiS_GetCH701x(SiS_Pr,0x74);
   if((tempbh == 0xf6) || (tempbh == 0xc7)) {
      tempbh = SiS_GetCH701x(SiS_Pr,0x73);
      if(tempbh == 0xc8) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
      } else if(tempbh == 0xdb) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) return;
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
      } else if(tempbh == 0xde) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
      }
   }
 
-  if(HwInfo->jChipType == SIS_740) {
-     tempbh = 0x0d;
-  } else {
-     tempbh = 0x0c;
-  }
+  if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
+  else     			   tempbh = 0x0c;
+
   for(i = 0; i < tempbh; i++) {
      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
   }
@@ -9488,13 +8938,12 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PS
 
    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 
-   /* Set up Panel Link for LVDS, 301BDH and 30xLV(for LCDA) */
+   /* Set up Panel Link for LVDS and LCDA */
+   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
        ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-   } else {
-      SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    }
 
 #ifdef LINUX_XF86
@@ -9521,11 +8970,16 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PS
 #endif
       	   SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
       	   SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+#ifdef SIS315H
+	   SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+#endif
       	   SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
 
+	   SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+
 	   /* For 301BDH (Panel link initialization): */
 	   if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+	      if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
 		 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
 		    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 		       SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
@@ -9540,28 +8994,25 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PS
 
    } else {
 
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-    	      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
-	                      RefreshRateTableIndex,HwInfo);
-	   }
+        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+
+        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+    	   SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
 	}
 
-        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
-	                RefreshRateTableIndex,HwInfo);
+        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
 
 	if(SiS_Pr->SiS_SetFlag & LowModeTests) {
      	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-#ifdef SIS315H		 
+#ifdef SIS315H
 		    SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
-#endif		    
+#endif
 		 }
 	      }
 	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-       		 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,
-		               RefreshRateTableIndex);
+       		 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
 	      }
      	   }
 	}
@@ -9572,7 +9023,7 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PS
    if(HwInfo->jChipType < SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 	 if(SiS_Pr->SiS_UseOEM) {
-	    if((SiS_Pr->SiS_UseROM) && ROMAddr && (SiS_Pr->SiS_UseOEM == -1)) {
+	    if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
 	       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	          SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
 	       			    RefreshRateTableIndex);
@@ -9605,13 +9056,11 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PS
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 	 if(HwInfo->jChipType < SIS_661) {
 	    SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-            if(SiS_Pr->SiS_UseOEM) {
-               SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
-            }
+            SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
 	 } else {
 	    SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 	 }
-         SiS_CRT2AutoThreshold(SiS_Pr);
+         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
       }
    }
 #endif
@@ -9625,7 +9074,7 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PS
    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 	 /* Disable LCD panel when using TV */
-	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x11,0x0C);
+	 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
       } else {
 	 /* Disable TV when using LCD */
 	 SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
@@ -9648,6 +9097,7 @@ void
 SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   /* Switch on LCD backlight on SiS30xLV */
+  SiS_DDC2Delay(SiS_Pr,0xff00);
   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
      SiS_WaitVBRetrace(SiS_Pr,HwInfo);
@@ -9663,12 +9113,81 @@ SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSI
   /* Switch off LCD backlight on SiS30xLV */
   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+  SiS_DDC2Delay(SiS_Pr,0xe000);
 }
 
 /*********************************************/
 /*          DDC RELATED FUNCTIONS            */
 /*********************************************/
 
+static void
+SiS_SetupDDCN(SiS_Private *SiS_Pr)
+{
+  SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
+  SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
+  if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
+     SiS_Pr->SiS_DDC_NData &= 0x0f;
+     SiS_Pr->SiS_DDC_NClk  &= 0x0f;
+  }
+}
+
+#ifdef SIS300
+static UCHAR *
+SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
+{
+  int i, j, num;
+  USHORT tempah,temp;
+  UCHAR *mydataptr;
+
+  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
+     mydataptr = dataptr;
+     num = *mydataptr++;
+     if(!num) return mydataptr;
+     if(i) {
+        SiS_SetStop(SiS_Pr);
+	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;		/* Set start condition */
+     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write DAB (S0=0=write) */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     tempah = *mydataptr++;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write register number */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     for(j=0; j<num; j++) {
+        tempah = *mydataptr++;
+        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
+	if(temp) break;
+     }
+     if(temp) continue;
+     if(SiS_SetStop(SiS_Pr)) continue;
+     return mydataptr;
+  }
+  return NULL;
+}
+
+static BOOLEAN
+SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;              	/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;              	/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+
+  SiS_SetSwitchDDC2(SiS_Pr);
+
+  while(*dataptr) {
+     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
+     if(!dataptr) return FALSE;
+  }
+#ifdef TWDEBUG
+  xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
+#endif
+  return TRUE;
+}
+#endif
+
 /* The Chrontel 700x is connected to the 630/730 via
  * the 630/730's DDC/I2C port.
  *
@@ -9704,18 +9223,32 @@ SiS_SetChReg(SiS_Private *SiS_Pr, USHORT
   return FALSE;
 }
 
+#ifdef SIS300
+/* Write Trumpion register */
+void
+SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;              	/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;              	/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_SetChReg(SiS_Pr, tempbx, 0);
+}
+#endif
+
 /* Write to Chrontel 700x */
 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
 void
 SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
 
   if(!(SiS_Pr->SiS_ChrontelInit)) {
      SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
   }
 
   if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
@@ -9723,6 +9256,7 @@ SiS_SetCH700x(SiS_Private *SiS_Pr, USHOR
      SiS_Pr->SiS_DDC_Index = 0x0a;		/* Bit 7 = SC;  Bit 6 = SD */
      SiS_Pr->SiS_DDC_Data  = 0x80;              /* Bitmask in IndexReg for Data */
      SiS_Pr->SiS_DDC_Clk   = 0x40;              /* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
 
      SiS_SetChReg(SiS_Pr, tempbx, 0x80);
   }
@@ -9736,19 +9270,18 @@ SiS_SetCH701x(SiS_Private *SiS_Pr, USHOR
   SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
+  SiS_SetupDDCN(SiS_Pr);
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
-
   SiS_SetChReg(SiS_Pr, tempbx, 0);
 }
 
 void
 SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-      SiS_SetCH700x(SiS_Pr,tempbx);
-   else
-      SiS_SetCH701x(SiS_Pr,tempbx);
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     SiS_SetCH700x(SiS_Pr,tempbx);
+  else
+     SiS_SetCH701x(SiS_Pr,tempbx);
 }
 
 static USHORT
@@ -9780,6 +9313,21 @@ SiS_GetChReg(SiS_Private *SiS_Pr, USHORT
   return 0xFFFF;
 }
 
+#ifdef SIS300
+/* Read from Trumpion */
+USHORT
+SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;	/* DAB */
+  SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;         /* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;         /* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+  return(SiS_GetChReg(SiS_Pr,0));
+}
+#endif
+
 /* Read from Chrontel 700x */
 /* Parameter is [Register no (S7-S0)] */
 USHORT
@@ -9787,13 +9335,13 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHOR
 {
   USHORT result;
 
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
 
   if(!(SiS_Pr->SiS_ChrontelInit)) {
      SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
   }
 
   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
@@ -9804,6 +9352,7 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHOR
      SiS_Pr->SiS_DDC_Index = 0x0a;
      SiS_Pr->SiS_DDC_Data  = 0x80;
      SiS_Pr->SiS_DDC_Clk   = 0x40;
+     SiS_SetupDDCN(SiS_Pr);
 
      result = SiS_GetChReg(SiS_Pr,0x80);
   }
@@ -9818,7 +9367,7 @@ SiS_GetCH701x(SiS_Private *SiS_Pr, USHOR
   SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
+  SiS_SetupDDCN(SiS_Pr);
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
 
   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
@@ -9831,10 +9380,10 @@ SiS_GetCH701x(SiS_Private *SiS_Pr, USHOR
 USHORT
 SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-      return(SiS_GetCH700x(SiS_Pr, tempbx));
-   else
-      return(SiS_GetCH701x(SiS_Pr, tempbx));
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     return(SiS_GetCH700x(SiS_Pr, tempbx));
+  else
+     return(SiS_GetCH701x(SiS_Pr, tempbx));
 }
 
 /* Our own DDC functions */
@@ -9942,6 +9491,8 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, uns
     SiS_Pr->SiS_DDC_Data = 0x02 << temp;
     SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
 
+    SiS_SetupDDCN(SiS_Pr);
+
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
     		SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
@@ -9986,11 +9537,15 @@ SiS_SendACK(SiS_Private *SiS_Pr, USHORT 
 {
    SiS_SetSCLKLow(SiS_Pr);
    if(yesno) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data, SiS_Pr->SiS_DDC_Data);
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      SiS_Pr->SiS_DDC_Data);
    } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data, 0);
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      0);
    }
    SiS_SetSCLKHigh(SiS_Pr);
 }
@@ -10215,6 +9770,8 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
    for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
    SiS_Pr->CP_HaveCustomData = FALSE;
    SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
+   SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
+   SiS_Pr->CP_PreferredIndex = -1;
 
    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
    if(pSiS->VBFlags & VB_30xBDH) return 0;
@@ -10309,12 +9866,14 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
 	 SiS_Pr->CP_PreferredY = yres;
 
          switch(xres) {
+#if 0	    /* Treat as custom */
             case 800:
 	        if(yres == 600) {
 	     	   paneltype = Panel_800x600;
 	     	   checkexpand = TRUE;
 	        }
 	        break;
+#endif
             case 1024:
 	        if(yres == 768) {
 	     	   paneltype = Panel_1024x768;
@@ -10352,9 +9911,11 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
 #if 0	    /* Treat this as custom, as we have no valid timing data yet */
 	    case 1600:
 	        if(pSiS->VGAEngine == SIS_315_VGA) {
-	           if(yres == 1200) {
-	              paneltype = Panel310_1600x1200;
-		      checkexpand = TRUE;
+		   if(pSiS->VBFlags & VB_301C) {
+	              if(yres == 1200) {
+	                 paneltype = Panel310_1600x1200;
+		         checkexpand = TRUE;
+		      }
 	           }
 	        }
       	        break;
@@ -10480,6 +10041,10 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
 	          if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
 		  if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
 
+		  if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
+	             SiS_Pr->CP_PreferredIndex = i;
+	          }
+
 		  SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
 		  SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
 
@@ -10560,28 +10125,20 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
       SiS_Pr->CP_MaxX = xres = buffer[0x76] | (buffer[0x77] << 8);
       SiS_Pr->CP_MaxY = yres = buffer[0x78] | (buffer[0x79] << 8);
       switch(xres) {
+#if 0
          case 800:
 	     if(yres == 600) {
 	     	paneltype = Panel_800x600;
 	     	checkexpand = TRUE;
 	     }
 	     break;
+#endif
          case 1024:
 	     if(yres == 768) {
 	     	paneltype = Panel_1024x768;
 	     	checkexpand = TRUE;
 	     }
 	     break;
-	 case 1152:
-	     if(yres == 768) {
-	        if(pSiS->VGAEngine == SIS_300_VGA) {
-		   paneltype = Panel300_1152x768;
-		} else {
-		   paneltype = Panel310_1152x768;
-		}
-	     	checkexpand = TRUE;
-	     }
-	     break;
 	 case 1280:
 	     if(yres == 960) {
 	        if(pSiS->VGAEngine == SIS_315_VGA) {
@@ -10606,9 +10163,11 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
 #if 0    /* Treat this one as custom since we have no timing data yet */
 	 case 1600:
 	     if(pSiS->VGAEngine == SIS_315_VGA) {
-	        if(yres == 1200) {
-	           paneltype = Panel310_1600x1200;
-		   checkexpand = TRUE;
+	        if(pSiS->VBFlags & VB_301C) {
+	           if(yres == 1200) {
+	              paneltype = Panel310_1600x1200;
+		      checkexpand = TRUE;
+		   }
 	        }
 	     }
       	     break;
@@ -10710,6 +10269,10 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
 
 	       if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
 
+	       if((SiS_Pr->CP_MaxX == xres) && (SiS_Pr->CP_MaxY == yres)) {
+	          SiS_Pr->CP_PreferredIndex = i;
+	       }
+
 	       SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
 	       SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
 	       SiS_Pr->CP_SyncValid[i] = TRUE;
@@ -10764,10 +10327,11 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
    if(paneltype) {
        if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
        if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
-       cr37 &= 0xf1;
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf1,cr37);
        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
+       cr37 &= 0xf1;
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf3,cr37);
+       SiS_Pr->PanelSelfDetected = TRUE;
 #ifdef TWDEBUG
        xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
        	"CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
@@ -10861,7 +10425,7 @@ SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SI
    }
 
    if(foundcrt) {
-       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
+      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
    }
    return(0);
 }
@@ -10903,11 +10467,15 @@ USHORT
 SiS_SetStart(SiS_Private *SiS_Pr)
 {
   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			           /* (SC->low)  */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);             /* SD->high */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+    		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);             			   /* SD->high */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* SC->high */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,0x00);                             /* SD->low = start condition */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  0x00);                             			   /* SD->low = start condition */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* (SC->low) */
   return 0;
 }
@@ -10918,11 +10486,15 @@ USHORT
 SiS_SetStop(SiS_Private *SiS_Pr)
 {
   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			           /* (SC->low) */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,0x00);          		   /* SD->low   */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  	          SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  0x00);          		   			   /* SD->low   */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* SC->high  */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);  	   /* SD->high = stop condition */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);  	   			   /* SD->high = stop condition */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* (SC->high) */
   return 0;
 }
@@ -10937,11 +10509,15 @@ SiS_WriteDDC2Data(SiS_Private *SiS_Pr, U
   for(i=0; i<8; i++) {
     SiS_SetSCLKLow(SiS_Pr);				                      /* SC->low */
     if(tempax & flag) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);            /* Write bit (1) to SD */
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      SiS_Pr->SiS_DDC_Data);            		      /* Write bit (1) to SD */
     } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data,0x00);                            /* Write bit (0) to SD */
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      0x00);                            		      /* Write bit (0) to SD */
     }
     SiS_SetSCLKHigh(SiS_Pr);				                      /* SC->high */
     flag >>= 1;
@@ -10959,8 +10535,10 @@ SiS_ReadDDC2Data(SiS_Private *SiS_Pr, US
   for(i=0; i<8; i++) {
     getdata <<= 1;
     SiS_SetSCLKLow(SiS_Pr);
-    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                    ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);
+    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+    		    SiS_Pr->SiS_DDC_Index,
+                    SiS_Pr->SiS_DDC_NData,
+		    SiS_Pr->SiS_DDC_Data);
     SiS_SetSCLKHigh(SiS_Pr);
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
     if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
@@ -10971,8 +10549,10 @@ SiS_ReadDDC2Data(SiS_Private *SiS_Pr, US
 USHORT
 SiS_SetSCLKLow(SiS_Private *SiS_Pr)
 {
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Clk,0x00);      		/* SetSCLKLow()  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NClk,
+		  0x00);      					/* SetSCLKLow()  */
   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
   return 0;
 }
@@ -10982,8 +10562,10 @@ SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
 {
   USHORT temp, watchdog=1000;
 
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Clk,SiS_Pr->SiS_DDC_Clk);  	/* SetSCLKHigh()  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NClk,
+		  SiS_Pr->SiS_DDC_Clk);  			/* SetSCLKHigh()  */
   do {
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
@@ -11005,10 +10587,12 @@ SiS_CheckACK(SiS_Private *SiS_Pr)
   USHORT tempah;
 
   SiS_SetSCLKLow(SiS_Pr);				           /* (SC->low) */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);     /* (SD->high) */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);     			   /* (SD->high) */
   SiS_SetSCLKHigh(SiS_Pr);				           /* SC->high = clock impulse for ack */
-  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);/* Read SD */
+  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
   SiS_SetSCLKLow(SiS_Pr);				           /* SC->low = end of clock impulse */
   if(tempah & SiS_Pr->SiS_DDC_Data) return(1);			   /* Ack OK if bit = 0 */
   else return(0);
@@ -11028,13 +10612,13 @@ GetRAMDACromptr(SiS_Private *SiS_Pr, PSI
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x128] | (ROMAddr[0x129] << 8);
+     romptr = SISGETROMW(0x128);
      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
-        romptr = ROMAddr[0x12a] | (ROMAddr[0x12b] << 8);
+        romptr = SISGETROMW(0x12a);
   } else {
-     romptr = ROMAddr[0x1a8] | (ROMAddr[0x1a9] << 8);
+     romptr = SISGETROMW(0x1a8);
      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
-        romptr = ROMAddr[0x1aa] | (ROMAddr[0x1ab] << 8);
+        romptr = SISGETROMW(0x1aa);
   }
   return(romptr);
 }
@@ -11046,13 +10630,13 @@ GetLCDromptr(SiS_Private *SiS_Pr, PSIS_H
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
+     romptr = SISGETROMW(0x120);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+        romptr = SISGETROMW(0x122);
   } else {
-     romptr = ROMAddr[0x1a0] | (ROMAddr[0x1a1] << 8);
+     romptr = SISGETROMW(0x1a0);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x1a2] | (ROMAddr[0x1a3] << 8);
+        romptr = SISGETROMW(0x1a2);
   }
   return(romptr);
 }
@@ -11064,13 +10648,13 @@ GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8);
+     romptr = SISGETROMW(0x114);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8);
+        romptr = SISGETROMW(0x11a);
   } else {
-     romptr = ROMAddr[0x194] | (ROMAddr[0x195] << 8);
+     romptr = SISGETROMW(0x194);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x19a] | (ROMAddr[0x19b] << 8);
+        romptr = SISGETROMW(0x19a);
   }
   return(romptr);
 }
@@ -11092,9 +10676,9 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, 
      }
   }
 
-  index = SiS_Pr->SiS_LCDResInfo & 0x0F;
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)      index -= 5;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) index -= 6;
+  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
+  else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
   index--;
   index *= 3;
   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -11107,12 +10691,9 @@ GetLCDPtrIndex(SiS_Private *SiS_Pr)
 {
   USHORT index;
 
-  index = SiS_Pr->SiS_LCDResInfo & 0x0F;
-  index--;
-  index *= 3;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
+  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
+  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
-
   return index;
 }
 
@@ -11122,8 +10703,10 @@ GetTVPtrIndex(SiS_Private *SiS_Pr)
   USHORT index;
 
   index = 0;
-  if(SiS_Pr->SiS_TVMode & TVSetPAL) index++;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index++;  /* HiVision uses PAL */
+  if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
 
   index <<= 1;
 
@@ -11136,7 +10719,7 @@ GetTVPtrIndex(SiS_Private *SiS_Pr)
 }
 
 static ULONG
-GetOEMTVPtr661_2(SiS_Private *SiS_Pr)
+GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
 {
    USHORT index = 0, temp = 0;
 
@@ -11153,7 +10736,7 @@ GetOEMTVPtr661_2(SiS_Private *SiS_Pr)
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-	 index += 8;
+	 index += addme;
 	 temp++;
       }
       temp += 0x0100;
@@ -11161,16 +10744,37 @@ GetOEMTVPtr661_2(SiS_Private *SiS_Pr)
    return(ULONG)(index | (temp << 16));
 }
 
+static ULONG
+GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
+{
+   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+}
+
+#if 0
+static ULONG
+GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
+{
+   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+}
+#endif
+
 static int
 GetOEMTVPtr661(SiS_Private *SiS_Pr)
 {
    int index = 0;
 
-   if(SiS_Pr->SiS_TVMode & TVSetPAL)       index = 2;
-   if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
+   if(SiS_Pr->SiS_ROMNew) {
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
+   } else {
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   }
 
    if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
 
@@ -11184,15 +10788,21 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
   USHORT delay=0,index,myindex,temp,romptr=0;
   BOOLEAN dochiptest = TRUE;
 
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
+  } else {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
+  }
+
   /* Find delay (from ROM, internal tables, PCI subsystem) */
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {			/* ------------ VGA */
      
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
         romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
-	if(!romptr) return;
-	delay = ROMAddr[romptr];
-     } else {
+     }
+     if(romptr) delay = ROMAddr[romptr];
+     else {
         delay = 0x04;
         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
 	   if(IS_SIS650) {
@@ -11204,8 +10814,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 	   } else {
 	      delay = 0x0c;
 	   }
-	}
-        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
            delay = 0x00;
 	}
      }
@@ -11214,13 +10823,39 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 
      BOOLEAN gotitfrompci = FALSE;
 
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	if(SiS_Pr->PDC != -1) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
+	   return;
+	}
+     } else {
+	if(SiS_Pr->PDCA != -1) {
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
+	   return;
+	}
+     }
 
-     /* Could we detect a PDC for LCD? If yes, use it */
+     /* Custom Panel? */
 
-     if(SiS_Pr->PDC) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDC & 0x0f) << 4));
+	   delay = 0x00;
+	   if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	      delay = 0x20;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
+	} else {
+	   delay = 0x0c;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
+	   else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = 0x03;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
 	}
         return;
      }
@@ -11233,7 +10868,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
      switch(SiS_Pr->SiS_CustomT) {
      case CUT_COMPAQ1280:
      case CUT_COMPAQ12802:
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
 	   gotitfrompci = TRUE;
 	   dochiptest = FALSE;
 	   delay = 0x03;
@@ -11241,15 +10876,13 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 	break;
      case CUT_CLEVO1400:
      case CUT_CLEVO14002:
-	/* if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { */
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
-	   delay = 0x02;
-	/* } */
+	gotitfrompci = TRUE;
+	dochiptest = FALSE;
+	delay = 0x02;
 	break;
      case CUT_CLEVO1024:
      case CUT_CLEVO10242:
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   gotitfrompci = TRUE;
 	   dochiptest = FALSE;
 	   delay = 0x33;
@@ -11270,21 +10903,16 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 
            if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
 
-              if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-#if 0	         /* Always use the second pointer on 650; some BIOSes */
+              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+	         /* Always use the second pointer on 650; some BIOSes */
                  /* still carry old 301 data at the first location    */
-	         romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
-	         if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-#endif
-	            romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+	         /* romptr = SISGETROMW(0x120);                       */
+	         /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	         romptr = SISGETROMW(0x122);
 	         if(!romptr) return;
 	         delay = ROMAddr[(romptr + index)];
 	      } else {
-                 delay = SiS310_LCDDelayCompensation_650301B[myindex];
-#if 0
-	         if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-	            delay = SiS310_LCDDelayCompensation_650301B[myindex];
-#endif
+                 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
 	      }
 
           } else {
@@ -11295,34 +10923,34 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 
           }
 
-        } else if((ROMAddr) && SiS_Pr->SiS_UseROM &&
-	          (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)) {
+        } else if(SiS_Pr->SiS_UseROM 			      &&
+		  (!(SiS_Pr->SiS_ROMNew))		      &&
+	          (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
 
+	   /* Data for 1280x1024 wrong in 301B BIOS */
            romptr = GetLCDromptr(SiS_Pr, HwInfo);
 	   if(!romptr) return;
 	   delay = ROMAddr[(romptr + index)];
 
         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 
-	   if(IS_SIS650) {
-              delay = SiS310_LCDDelayCompensation_LVDS650[myindex];
-	   } else {
-	      delay = SiS310_LCDDelayCompensation_LVDS740[myindex];
-	   }
+	   if(IS_SIS740) delay = 0x03;
+	   else          delay = 0x00;
 
 	} else {
 
            delay = SiS310_LCDDelayCompensation_301[myindex];
-           if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-#if 0 	      /* This data is (like the one in the BIOS) wrong. */
-	      if(IS_SIS550650740660) {
-	         delay = SiS310_LCDDelayCompensation_650301B[myindex];
-	      } else {
-#endif
-                 delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
-#if 0
-	      }
-#endif
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if(IS_SIS740) delay = 0x01;  /* ? */
+	      else          delay = 0x03;
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
 	   }
 
         }
@@ -11342,23 +10970,19 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 
         if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
 
-           if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-#if 0	      /* Always use the second pointer on 650; some BIOSes */
+           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+	      /* Always use the second pointer on 650; some BIOSes */
               /* still carry old 301 data at the first location    */
-              romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8);
-	      if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-#endif
-	         romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8);
+              /* romptr = SISGETROMW(0x114);			   */
+	      /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	      romptr = SISGETROMW(0x11a);
 	      if(!romptr) return;
 	      delay = ROMAddr[romptr + index];
 
 	   } else {
 
 	      delay = SiS310_TVDelayCompensation_301B[index];
-#if 0
-	      if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-	         delay = SiS310_TVDelayCompensation_301B[index];
-#endif		
+
 	   }
 
         } else {
@@ -11384,7 +11008,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
 	   }
         }
 
-     } else if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 
         romptr = GetTVromptr(SiS_Pr, HwInfo);
 	if(!romptr) return;
@@ -11400,14 +11024,16 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 	   if(IS_SIS740) {
 	      delay = SiS310_TVDelayCompensation_740301B[index];
+	      /* LV: use 301 data? BIOS bug? */
 	   } else {
               delay = SiS310_TVDelayCompensation_301B[index];
+	      if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
 	   }
 	}
 
      }
 
-     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {  /* LCDA */
+     if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
 	delay &= 0x0f;
 	dochiptest = FALSE;
      }
@@ -11470,18 +11096,21 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS
      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
 
   temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;  	  /* 0: NTSC, 1: PAL, 2: HiTV */
+  temp >>= 1;  	  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
   temp1 = temp;
 
-  if(ROMAddr && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
      if(HwInfo->jChipType >= SIS_661) {
-	romptr = ROMAddr[0x260] | (ROMAddr[0x261] << 8);
-	temp1 = GetOEMTVPtr661(SiS_Pr);
+        temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
+        romptr = SISGETROMW(0x260);
+        if(HwInfo->jChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x360);
+	}
      } else if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x192] | (ROMAddr[0x193] << 8);
+        romptr = SISGETROMW(0x192);
      } else {
-        romptr = ROMAddr[0x112] | (ROMAddr[0x113] << 8);
+        romptr = SISGETROMW(0x112);
      }
   }
 
@@ -11503,24 +11132,25 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,temp1,romptr=0;
 
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;              	/* 0: NTSC, 1: PAL, 2: HiTV */
-  temp1 = temp;
+  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; 	/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
-  if(ModeNo<=0x13)
+  if(ModeNo <= 0x13)
      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
   else
      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
 
-  if(ROMAddr && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
      if(HwInfo->jChipType >= SIS_661) {
-	romptr = ROMAddr[0x26c] | (ROMAddr[0x26d] << 8);
+        romptr = SISGETROMW(0x26c);
+        if(HwInfo->jChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x36c);
+	}
 	temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
      } else if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x1a4] | (ROMAddr[0x1a5] << 8);
+        romptr = SISGETROMW(0x1a4);
      } else {
-        romptr = ROMAddr[0x124] | (ROMAddr[0x125] << 8);
+        romptr = SISGETROMW(0x124);
      }
   }
 
@@ -11538,62 +11168,15 @@ static void
 SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
            USHORT ModeNo,USHORT ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index, myindex, oldindex,temp, i, j, flag1 = 0, flag2 = 0, romptr = 0;
-  ULONG  lindex;
+  USHORT index, temp, i, j;
 
-  if(ModeNo<=0x13) {
-    index =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
+  if(ModeNo <= 0x13) {
+     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
   } else {
-    index =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
-  }
-
-  oldindex = index;
-
-  if((HwInfo->jChipType >= SIS_661) && ROMAddr && SiS_Pr->SiS_UseROM) {
-     if(ModeNo > 0x13) {
-        index =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndexROM661;
-     }
-     lindex = GetOEMTVPtr661_2(SiS_Pr);
-     if(lindex & 0x00ff0000) flag1 = 1;
-     if(lindex & 0xff000000) flag2 = 1;
-     lindex &= 0xffff;
-
-     /* NTSC-J: Use PAL filters */
-     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) lindex = 1;
-
-     romptr = ROMAddr[0x268] | (ROMAddr[0x269] << 8);
-     if(flag1) myindex = index * 7;
-     else      myindex = index << 2;
-
-     if(romptr) {
-        romptr += (lindex << 1);
-        romptr = (ROMAddr[romptr] | (ROMAddr[romptr+1] << 8)) + myindex;
-	if(romptr) {
-           if((!flag1) && (flag2)) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,ROMAddr[romptr++]);
-           } else {
-	      for(i=0x35; i<=0x38; i++) {
-                 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr++]);
-              }
-           }
-           if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      for(j=0, i=0x48; i<=0x4a; i++, j++) {
-                 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr++]);
-              }
-           }
-           return;
-	}
-     }
+     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
   }
 
-  index = oldindex;
-
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;  			/* 0: NTSC, 1: PAL, 2: HiTV */
+  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)	     temp = 1;  /* NTSC-J uses PAL */
   else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
@@ -11627,21 +11210,11 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_H
   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
 
-  if(HwInfo->jChipType >= SIS_661) {
-     lindex = GetOEMTVPtr661_2(SiS_Pr) & 0xffff;
+  if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
      lindex <<= 2;
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-        romptr = ROMAddr[0x264] | (ROMAddr[0x265] << 8);
-     }
-     if(romptr) {
-	romptr += lindex;
-	for(j=0, i=0x31; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
-        }
-     } else {
-        for(j=0, i=0x31; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
-        }
+     for(j=0, i=0x31; i<=0x34; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
      }
      return;
   }
@@ -11659,20 +11232,20 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_H
   /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
    * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
    */
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-     romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+  if(SiS_Pr->SiS_UseROM) {
+     romptr = SISGETROMW(0x116);
      if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+        romptr = SISGETROMW(0x196);
      }
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-        romptr = ROMAddr[0x11c] | (ROMAddr[0x11d] << 8);
+        romptr = SISGETROMW(0x11c);
 	if(HwInfo->jChipType >= SIS_330) {
-	   romptr = ROMAddr[0x19c] | (ROMAddr[0x19d] << 8);
+	   romptr = SISGETROMW(0x19c);
 	}
 	if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
-	   romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+	   romptr = SISGETROMW(0x116);
 	   if(HwInfo->jChipType >= SIS_330) {
-              romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+              romptr = SISGETROMW(0x196);
            }
 	}
      }
@@ -11695,19 +11268,19 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_H
      }
   }
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-     if((!(SiS_Pr->SiS_TVMode & TVSetPAL)) && (ModeNo > 0x13)) {
+  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
+     if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
         if((resinfo == SIS_RI_640x480) ||
 	   (resinfo == SIS_RI_800x600)) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
-	} else if (resinfo == SIS_RI_1024x768) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
+	} else if(resinfo == SIS_RI_1024x768) {
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
 	}
      }
   }
@@ -11722,12 +11295,12 @@ SiS_OEM310Setting(SiS_Private *SiS_Pr, P
    if(SiS_Pr->UseCustomMode) return;
 
    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-       SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
-          SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       }
+      SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      if(SiS_Pr->SiS_VBType & VB_SIS301) {
+         SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      }
    }
 }
 
@@ -11735,65 +11308,104 @@ static void
 SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
                 USHORT ModeIdIndex, USHORT RTI)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
    USHORT delay = 0, romptr = 0, index;
-   UCHAR  *myptr = NULL;
-   UCHAR  temp;
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
 
    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
       return;
 
-   delay = SiS_Pr->SiS_RefIndex[RTI].Ext_PDC;
+   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
+
+   if(SiS_Pr->SiS_ROMNew) {
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) 			||
+         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+	  (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+         index = 25;
+         if(SiS_Pr->UseCustomMode) {
+	    index = SiS_Pr->CSRClock;
+         } else if(ModeNo > 0x13) {
+            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
+            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
+         }
+	 if(index < 25) index = 25;
+         index = ((index / 25) - 1) << 1;
+         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) index++;
+	 romptr = SISGETROMW(0x104);  /* 0x4ae */
+         delay = ROMAddr[romptr + index];
+         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
+         } else {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+         }
+         return;
+      }
+   }
+
+   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
 
-   delay &= 0xf0;
-   delay >>= 4;
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) delay <<= 12;  /* BIOS: 8, wrong */
+   if(SiS_Pr->UseCustomMode) delay = 0x04;
+   else if(ModeNo <= 0x13)   delay = 0x04;
+   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
+   delay |= (delay << 8);
 
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+      /* 3. TV */
+
       index = GetOEMTVPtr661(SiS_Pr);
-      if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-         romptr = ROMAddr[0x25c] | (ROMAddr[0x25d] << 8);
-         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-            romptr = ROMAddr[0x25e] | (ROMAddr[0x25f] << 8);
-         }
-      }
-      if(romptr) myptr = &ROMAddr[romptr];
-      if(!myptr) {
-         myptr = (UCHAR *)SiS_TVDelay661_301;
-	 if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	    myptr = (UCHAR *)SiS_TVDelay661_301B;
-	 }
+      if(SiS_Pr->SiS_ROMNew) {
+         romptr = SISGETROMW(0x106);  /* 0x4ba */
+         delay = ROMAddr[romptr + index];
+      } else {
+         delay = 0x04;
       }
-      delay = myptr[index];
-      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) delay >>= 4;  /* Should test dual edge */
+
    } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-      if(SiS_Pr->PDC) {
-         delay = SiS_Pr->PDC & 0x0f;
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            delay |= (delay << 12);
-         }
-      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
-         delay = 0x4444;  /* TEST THIS */
-      } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-         myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-         if(myptr) delay = myptr[4];
-         else delay = 0x44;
-         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            delay |= (delay << 8);
+
+      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
+
+      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
+          ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
+
+	 /* For LV, the BIOS must know about the correct value */
+	 delay = ROMAddr[romptr + 0x0d];		/* LCD  */
+	 delay |= (ROMAddr[romptr + 0x0c] << 8);	/* LCDA */
+
+      } else {
+
+         /* TMDS: Set our own, since BIOS has no idea - TODO: Find out about values */
+         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+            if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
+	       delay = 0x0404;
+            } else if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	       delay = 0x0404;
+            } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
+	       delay = 0x1004;
+            } else
+	       delay = 0x0000;
          }
+
       }
-   }
 
-   temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2d);
-   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToRAMDAC)) {
-      temp &= 0xf0;
-      temp |= (delay & 0x000f);
+      /* Override by detected or user-set values */
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
+         delay = SiS_Pr->PDC & 0x1f;
+      }
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
+         delay = (SiS_Pr->PDCA & 0x1f) << 8;
+      }
    }
+
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      temp &= 0x0f;
-      temp |= ((delay & 0xf000) >> 8);
+      delay >>= 8;
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+   } else {
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
    }
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,temp);
 }
 
 static void
@@ -11802,38 +11414,50 @@ SetCRT2SyncDither661(SiS_Private *SiS_Pr
    USHORT infoflag;
    UCHAR temp;
 
-   infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
-   if(ModeNo <= 0x13) {
-      infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
-   }
-   infoflag &= 0xc0;
    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+
+      if(ModeNo <= 0x13) {
+         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
+      } else if(SiS_Pr->UseCustomMode) {
+         infoflag = SiS_Pr->CInfoFlag;
+      } else {
+         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
+      }
+      infoflag &= 0xc0;
+
       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-      if(temp & 0x20) infoflag = temp;
+      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+         temp &= 0x3f;
+	 temp |= infoflag;
+      } else {
+         if(temp & 0x20) infoflag = temp;
+      }
       if(temp & 0x01) infoflag |= 0x01;
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-      temp = 0x0c;
-      if(infoflag & 0x01) temp ^= 0x14;  /* BIOS: 18, wrong */
-      temp |= (infoflag >> 6);
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      temp = 0;
-      if(infoflag & 0x01) temp |= 0x80;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
-      temp = 0x30;
-      if(infoflag & 0x01) temp = 0x20;
-      infoflag &= 0xc0;
-      temp |= infoflag;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+         temp = 0x0c;
+         if(infoflag & 0x01) temp ^= 0x14;  /* BIOS: 18, wrong */
+         temp |= (infoflag >> 6);
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
+      } else {
+         temp = 0;
+         if(infoflag & 0x01) temp |= 0x80;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
+         temp = 0x30;
+         if(infoflag & 0x01) temp = 0x20;
+         infoflag &= 0xc0;
+         temp |= infoflag;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+      }
+
    }
 }
 
 static void
 SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-   UCHAR *myptr;
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   USHORT romptr, temp1, temp2;
 
    if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
       if(SiS_Pr->LVDSHL != -1) {
@@ -11841,16 +11465,22 @@ SetPanelParms661(SiS_Private *SiS_Pr, PS
       }
    }
 
-   myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-   if(myptr) {
-      if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
-         if(SiS_Pr->LVDSHL == -1) {
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xE0,myptr[1] & 0x1f);
-	 } else {
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xE3,myptr[1] & 0x1c);
-	 }
+   if(SiS_Pr->SiS_ROMNew) {
+
+      if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
+         if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
+	    temp2 = 0xfc;
+	    if(SiS_Pr->LVDSHL != -1) {
+	      temp1 &= 0xfc;
+	      temp2 = 0xf3;
+	    }
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
+         }
+         temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
       }
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0x3f,myptr[2] & 0xc0);
+
    }
 }
 
@@ -11871,7 +11501,7 @@ SiS_OEM661Setting(SiS_Private *SiS_Pr, P
          SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-         if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+         if(SiS_Pr->SiS_VBType & VB_SIS301) {
             SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          }
       }
@@ -11900,7 +11530,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
      }
   }
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
   if(SiS_Pr->UseCustomMode) return;
 
   switch(SiS_Pr->SiS_CustomT) {
@@ -11930,7 +11560,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
   }
 
   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         /* Maybe all panels? */
         if(SiS_Pr->LVDSHL == -1) {
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -11941,7 +11571,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
 
   if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if(SiS_Pr->LVDSHL == -1) {
 	      /* Maybe all panels? */
               SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -11961,15 +11591,15 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
   }
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 #ifdef SET_EMI
 	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	}
 #endif
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
         if(SiS_Pr->LVDSHL == -1) {
            /* Maybe ACER only? */
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -11977,9 +11607,9 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
      }
      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
 	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if(tempch == 0x03) {
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
@@ -12060,7 +11690,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
 	tempbh >>= 4;
 	tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
 	tempbx = (tempbh << 8) | tempbl;
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
 	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
 	      	 tempbx = 770;
@@ -12151,19 +11781,16 @@ GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_H
 
     tempbx = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f) - 2;
     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
-    if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
     }
-    if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+    if(SiS_Pr->SiS_UseROM) {
        if(ROMAddr[0x235] & 0x80) {
           tempbx = SiS_Pr->SiS_LCDTypeInfo;
           if(Flag) {
-	     romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8);
-	     if(romptr) {
-	        tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	     } else {
-	        tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
-	     }
+	     romptr = SISGETROMW(0x255);
+	     if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	     else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
              if(tempbx == 0xFF) return 0xFFFF;
           }
 	  tempbx <<= 1;
@@ -12174,13 +11801,10 @@ GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_H
   } else {
 
     if(Flag) {
-       if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-          romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8);
-	  if(romptr) {
-	     tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	  } else {
-	     tempbx = 0xff;
-	  }
+       if(SiS_Pr->SiS_UseROM) {
+          romptr = SISGETROMW(0x255);
+	  if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	  else 	     tempbx = 0xff;
        } else {
           tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
        }
@@ -12204,12 +11828,12 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
      if(!(ROMAddr[0x237] & 0x02)) return;
-     romptr = ROMAddr[0x24b] | (ROMAddr[0x24c] << 8);
+     romptr = SISGETROMW(0x24b);
   }
 
   /* The Panel Compensation Delay should be set according to tables
@@ -12219,7 +11843,7 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS
    * Thus we don't set this if the user select a custom pdc or if
    * we otherwise detected a valid pdc.
    */
-  if(SiS_Pr->PDC) return;
+  if(SiS_Pr->PDC != -1) return;
 
   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
 
@@ -12231,7 +11855,7 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS
   if(HwInfo->jChipType != SIS_300) {
      if(romptr) {
 	romptr += (temp * 2);
-	romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	romptr = SISGETROMW(romptr);
 	romptr += index;
 	temp = ROMAddr[romptr];
      } else {
@@ -12242,21 +11866,21 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS
         }
      }
   } else {
-     if((ROMAddr) && SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
+     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
 	if(romptr) {
 	   romptr += (temp * 2);
-	   romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	   romptr = SISGETROMW(romptr);
 	   romptr += index;
 	   temp = ROMAddr[romptr];
 	} else {
 	   temp = SiS300_OEMLCDDelay5[temp][index];
 	}
      } else {
-        if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+        if(SiS_Pr->SiS_UseROM) {
 	   romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
 	   if(romptr) {
 	      romptr += (temp * 2);
-	      romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	      romptr = SISGETROMW(romptr);
 	      romptr += index;
 	      temp = ROMAddr[romptr];
 	   } else {
@@ -12279,7 +11903,7 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if((SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
      if(!(ROMAddr[0x237] & 0x04)) return;
      /* No rom pointer in BIOS header! */
@@ -12329,10 +11953,10 @@ SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x02)) return;
-     romptr = ROMAddr[0x241] | (ROMAddr[0x242] << 8);
+     romptr = SISGETROMW(0x241);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12341,7 +11965,7 @@ SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_
 
   if(romptr) {
      romptr += (temp * 2);
-     romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+     romptr = SISGETROMW(romptr);
      romptr += index;
      temp = ROMAddr[romptr];
   } else {
@@ -12352,7 +11976,7 @@ SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_
      }
   }
   temp &= 0x3c;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
 }
 
 static void
@@ -12362,10 +11986,10 @@ SetOEMAntiFlicker(SiS_Private *SiS_Pr, P
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x04)) return;
-     romptr = ROMAddr[0x243] | (ROMAddr[0x244] << 8);
+     romptr = SISGETROMW(0x243);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12374,14 +11998,14 @@ SetOEMAntiFlicker(SiS_Private *SiS_Pr, P
 
   if(romptr) {
      romptr += (temp * 2);
-     romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+     romptr = SISGETROMW(romptr);
      romptr += index;
      temp = ROMAddr[romptr];
   } else {
      temp = SiS300_OEMTVFlicker[temp][index];
   }
   temp &= 0x70;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);  /* index 0A D[6:4] */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
 }
 
 static void
@@ -12395,10 +12019,10 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSI
 
   if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x08)) return;
-     romptr = ROMAddr[0x245] | (ROMAddr[0x246] << 8);
+     romptr = SISGETROMW(0x245);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12412,7 +12036,7 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSI
   } else {
      if(romptr) {
         romptr += (temp * 2);
-	romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	romptr = SISGETROMW(romptr);
 	romptr += (index * 4);
         for(i=0x31, j=0; i<=0x34; i++, j++) {
 	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
@@ -12434,10 +12058,10 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x10)) return;
-     romptr = ROMAddr[0x247] | (ROMAddr[0x248] << 8);
+     romptr = SISGETROMW(0x247);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12458,7 +12082,7 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_
   } else {
       if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
          romptr += (temp * 2);
-	 romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	 romptr = SISGETROMW(romptr);
 	 romptr += (index * 4);
 	 for(i=0x35, j=0; i<=0x38; i++, j++) {
        	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/init301.h linux-2.4.26-pre6/drivers/video/sis/init301.h
--- linux-2.4.25/drivers/video/sis/init301.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/init301.h	2004-03-25 00:19:54.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -91,29 +88,41 @@ const UCHAR SiS_YPbPrTable[3][64] = {
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
     0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
     0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
-    0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53,
+    0x03,0x0a,0x65,0x8d /*0x9d*/,0x08,0x92,0x8f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50 /*0x53*/,
     0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
   },
   {
     0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
     0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13,
     0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
-    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+    0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40,
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b,
     0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
   },
   {
+#if 1
     0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
     0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0xed,0x50,0x70,0x9f,0x16,0x59,0x2b,0x13,
+    0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
     0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
-    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+    0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
     0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+#if 0
+    0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c,  /* TEST (0.93) - BAD */
+    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+    0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13,
+    0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0,
+    0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f,
+    0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00
+#endif
   }
 };
 
@@ -139,7 +148,7 @@ const UCHAR SiS_HiTVGroup3_2[] = {
     0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
 };
 
-/* 301C / 302ELV (?) extended Part2 TV registers */
+/* 301C / 302ELV extended Part2 TV registers */
 
 static const UCHAR SiS_Part2CLVX_1[] = {
     0x00,0x00,
@@ -208,7 +217,7 @@ static const UCHAR SiS_Part2CLVX_6[] = {
     0x00,0x04,
     0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
     0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x1D,0x7C,0x0D,0x18,0x7F,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x1D /* 0x7D? */ ,0x7C,0x0D,0x18,0x7F,
     0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
     0xFF,0xFF,
 };
@@ -217,19 +226,80 @@ static const UCHAR SiS_Part2CLVX_6[] = {
 #ifdef SIS315H
 /* 661 et al LCD data structure */
 static const UCHAR SiS_LCDStruct661[] = {
-    /* 1600x1200 */
-    0x0B,0xEA,0x81,0x10,0x00,0xC0,0x03,0x21,0x5A,0x23,0x5A,0x23,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
-    /* 1400x1050 */
-    0x09,0xEA,0x81,0x80,0xA3,0x70,0x03,0x19,0xD2,0x2A,0xF8,0x2F,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
-    /* 1280x1024 */
-    0x03,0xEA,0x81,0x40,0xA1,0x70,0x03,0x19,0xD2,0x2A,0xF8,0x2F,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
     /* 1024x768 */
-    0x02,0xEA,0x80,0x00,0x11,0x88,0x06,0x0B,0xF5,0x6C,0x35,0x62,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x28,0x10,
-    0xFF,
+/*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
+    0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
+    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x37,0x6E,0x05,0x6E,0x04,
+    /*  | vss      |   vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
+    /*					      VESA    non-VESA  noscale */
+    /* 1280x1024 */
+    0x03,0xE0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x5F,0x6F,0xDB,0x6F,0x08,
+    /* 1400x1050 */
+    0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x35,0x70,0x00,0x00,0x09,
+    /* 1600x1200 */
+    0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
+    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x07,0x71,0x00,0x00,0x0B,
+    /* 1280x768 */
+    0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x05,0x26,0x03,0x10,0x00,0x40,
+    0x00,0x03,0x00,0x06,0x00,0x44,0x63,0x46,0xEB,0x6E,0xA5,0x6E,0x06,
+    /* 1280x720 */
+    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x40,0x05,0x26,0x03,0x10,0x00,0x02,
+    0x00,0x01,0x00,0x06,0x00,0x41,0x5A,0x64,0x69,0x6E,0x00,0x00,0x05,
+#if 0 /* 0.92: */
+    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x72,0x06,0xEE,0x02,0x2A,0x00,0x3F,
+    0x00,0x01,0x00,0x06,0x00,0x41,0x00,0x00,0xA7,0x6A,0x00,0x00,0x05,
+#endif
+    /* 1280x800 */
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0x80,0x05,0x30,0x03,0x15,0x00,0x18,
+    0x00,0x04,0x00,0x03,0x00,0x45,0x9C,0x62,0x31,0x6F,0x00,0x00,0x07,
+    /* 1680x1050 */
+    0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
+    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x99,0x70,0x00,0x00,0x0A, /* 0.93: 0x0A=0x06 - WRONG? */
+    /* 1280x768 (not in 0.93) */
+    0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x06,0x1E,0x03,0x40,0x00,0x80,
+    0x00,0x03,0x00,0x07,0x00,0x4F,0x00,0x00,0x6F,0x6B,0x00,0x00,0x06
+};
+#endif
+
+#ifdef SIS300
+static UCHAR SiS300_TrumpionData[7][80] = {
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
+    0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
+    0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
+    0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }
 };
 #endif
 
@@ -271,6 +341,12 @@ void   	SiS_ChrontelDoSomething1(SiS_Pri
 void   	SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void   	SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
 #endif /* 315 */
+#ifdef SIS300
+void    SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
+USHORT  SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
+static  BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
+#endif
+
 
 USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
 void     SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
@@ -338,5 +414,6 @@ extern USHORT   SiS_GetOffset(SiS_Privat
 extern void     SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO,USHORT ModeNo,
                             USHORT ModeIdIndex);
 
+extern void	SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/initdef.h linux-2.4.26-pre6/drivers/video/sis/initdef.h
--- linux-2.4.25/drivers/video/sis/initdef.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/initdef.h	2004-03-25 00:20:32.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -72,6 +69,8 @@
 #define IS_SIS650740660         (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
 #define IS_SIS550650740660      (IS_SIS550 || IS_SIS650740660)
 
+#define SISGETROMW(x)		(ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
+
 /* SiS_VBType */
 #define VB_SIS301	      	0x0001
 #define VB_SIS301B        	0x0002
@@ -102,7 +101,7 @@
 #define SetNotSimuMode          0x0400
 #define SetNotSimuTVMode        SetNotSimuMode
 #define SetDispDevSwitch        0x0800
-#define SetCRT2ToYPbPr525750    0x0800   /* 661 */
+#define SetCRT2ToYPbPr525750    0x0800   
 #define LoadDACFlag             0x1000
 #define DisableCRT2Display      0x2000
 #define DriverMode              0x4000
@@ -145,7 +144,7 @@
 #define SupportCHTV 		0x0800
 #define Support64048060Hz       0x0800  /* Special for 640x480 LCD */
 #define SupportHiVision         0x0010
-#define SupportYPbPr            0x1000  /* TODO */
+#define SupportYPbPr750p        0x1000  
 #define SupportLCD              0x0020
 #define SupportRAMDAC2          0x0040	/* All           (<= 100Mhz) */
 #define SupportRAMDAC2_135      0x0100  /* All except DH (<= 135Mhz) */
@@ -174,20 +173,23 @@
 #define TVSetPALM		0x0004
 #define TVSetPALN		0x0008
 #define TVSetCHOverScan		0x0010
-#define TVSetYPbPr525i		0x0020
-#define TVSetYPbPr525p		0x0040
-#define TVSetYPbPr750p		0x0080
-#define TVSetHiVision		0x0100
-#define TVSetTVSimuMode		0x0800
-#define TVRPLLDIV2XO		0x1000
-#define TVSetNTSC1024		0x2000
-
-/* YPbPr flag (>=315, <661; YPbPr not supported yet) */
-#define YPbPr750                0x0001	/* 750p (must be a single bit, checked logially) */
-#define YPbPr525                0x0002	/* 525p (must be a single bit, checked logially) */
-#define YPbPrHiVision           0x0003	/* HiVision */
-#define YPbPrModeMask           (YPbPr750 | YPbPr525 | YPbPrHiVision)
-#define YPbPrSetSVideo     	0x0004	/* (sets SVIDEO flag) */
+#define TVSetYPbPr525i		0x0020 /* new 0x10 */
+#define TVSetYPbPr525p		0x0040 /* new 0x20 */
+#define TVSetYPbPr750p		0x0080 /* new 0x40 */
+#define TVSetHiVision		0x0100 /* new 0x80; = 1080i, software-wise identical */
+#define TVSetTVSimuMode		0x0200 /* new 0x200, prev. 0x800 */
+#define TVRPLLDIV2XO		0x0400 /* prev 0x1000 */
+#define TVSetNTSC1024		0x0800 /* new 0x100, prev. 0x2000 */
+#define TVAspect43		0x2000
+#define TVAspect169		0x4000
+#define TVAspect43LB		0x8000
+
+/* YPbPr flag (>=315, <661; converted to TVMode) */
+#define YPbPr525p               0x0001
+#define YPbPr750p               0x0002
+#define YPbPr525i               0x0004
+#define YPbPrHiVision           0x0008
+#define YPbPrModeMask           (YPbPr750p | YPbPr525p | YPbPr525i | YPbPrHiVision)
 
 /* SysFlags (to identify special versions) */
 #define SF_Is651                0x0001
@@ -198,6 +200,7 @@
 #define SF_IsM661		0x0020
 #define SF_IsM741		0x0040
 #define SF_IsM760		0x0080
+#define SF_760UMA		0x8000
 
 /* CR32 (Newer 630, and 315 series)
 
@@ -223,11 +226,11 @@
    [2]    1 = PALM (if D0 = 1)
    [3]    1 = PALN (if D0 = 1)
    [4]    1 = Overscan (Chrontel only)
-   [7:5]  (only if D2 in CR38 is set; not supported yet)
+   [7:5]  (only if D2 in CR38 is set)
           000  525i
  	  001  525p
 	  010  750p
-	  011  HiVision (Should be 1080i, but...)
+	  011  1080i (or HiVision on 301, 301B)
 
    These bits are being translated to TVMode flag.
 
@@ -269,7 +272,7 @@
 #define LCDRGB18Bit           0x0001
 #define LCDNonExpanding       0x0010
 #define LCDSync               0x0020
-#define LCDPass11             0x0100
+#define LCDPass11             0x0100   /* 0: center screen, 1: Pass 1:1 data */
 #define LCDDualLink	      0x0200
 
 #define DontExpandLCD	      LCDNonExpanding
@@ -281,13 +284,13 @@
 /* CR38 (315 series) */
 #define EnableDualEdge 		0x01
 #define SetToLCDA		0x02   /* LCD channel A (301C/302B/30x(E)LV and 650+LVDS only) */
-#define EnableSiSYPbPr          0x04   /* YPbPr on SiS bridge (not used; also on 661) */
 #define EnableCHScart           0x04   /* Scart on Ch7019 (unofficial definition - TW) */
 #define EnableCHYPbPr           0x08   /* YPbPr on Ch7019 (480i HDTV); only on 650/Ch7019 systems */
-#define EnableYPbPr750          0x08   /* Enable 750P YPbPr mode (30xLV/301C only) (not supported) */
-#define EnableYPbPr525          0x10   /* Enable 525P YPbPr mode (30xLV/301C only) (not supported) */
-#define EnableYPbPrHiVision     0x18   /* Enable HiVision (not supported) */
-#define EnableYPbPrsetSVideo    0x20   /* Enable YPbPr and set SVideo */
+#define EnableSiSYPbPr          0x08   /* Enable YPbPr mode (30xLV/301C only) */
+#define EnableYPbPr525i         0x00   /* Enable 525i YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr525p         0x10   /* Enable 525p YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr750p         0x20   /* Enable 750p YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr1080i        0x30   /* Enable 1080i YPbPr mode (30xLV/301C only) (mask 0x30) */
 #define EnablePALM              0x40   /* 1 = Set PALM */
 #define EnablePALN              0x80   /* 1 = Set PALN */
 #define EnableNTSCJ             EnablePALM  /* Not BIOS */
@@ -305,10 +308,10 @@
 #define EnablePALMN             0x40   /* Romflag: 1 = Allow PALM/PALN */
 
 /* CR39 (650 only) */
-#define LCDPass1_1		0x01   /* LVDS only; set by driver to pass 1:1 data to LVDS output  */
+#define LCDPass1_1		0x01   /* 0: center screen, 1: pass 1:1 data output  */
 #define Enable302LV_DualLink    0x04   /* 302LV only; enable dual link */
 
-/* CR39 (661 and later; not yet implemented)
+/* CR39 (661 and later)
    D[1:0] YPbPr Aspect Ratio
           00 4:3 letterbox
 	  01 4:3
@@ -316,6 +319,11 @@
 	  11 4:3
 */
 
+/* CR3B (651+301C)
+   D[1:0] YPbPr Aspect Ratio
+          ?
+*/
+
 /* CR79 (315/330 series only; not 661 and later)
    [3-0] Notify driver
          0001 Mode Switch event (set by BIOS)
@@ -343,7 +351,7 @@
 #define Panel300_1024x600       0x06
 #define Panel300_1152x768       0x07
 #define Panel300_1280x768       0x0a
-#define Panel300_320x480        0x0e 	/* fstn - TW: This is fake, can be any */
+#define Panel300_320x480        0x0e 	/* fstn - This is fake, can be any */
 #define Panel300_Custom		0x0f
 #define Panel300_Barco1366      0x10
 
@@ -363,8 +371,24 @@
 #define Panel310_320x480        0x0e    /* fstn - TW: This is fake, can be any */
 #define Panel310_Custom		0x0f
 
+#define Panel661_800x600        0x01
+#define Panel661_1024x768       0x02
+#define Panel661_1280x1024      0x03
+#define Panel661_640x480        0x04
+#define Panel661_1024x600       0x05
+#define Panel661_1152x864       0x06
+#define Panel661_1280x960       0x07
+#define Panel661_1152x768       0x08
+#define Panel661_1400x1050      0x09
+#define Panel661_1280x768       0x0a
+#define Panel661_1600x1200      0x0b
+#define Panel661_1280x800       0x0c
+#define Panel661_1680x1050      0x0d
+#define Panel661_1280x720       0x0e
+#define Panel661_Custom		0x0f
+
 #define Panel_800x600           0x01	/* Unified values */
-#define Panel_1024x768          0x02
+#define Panel_1024x768          0x02    /* MUST match BIOS values from 0-e */
 #define Panel_1280x1024         0x03
 #define Panel_640x480           0x04
 #define Panel_1024x600          0x05
@@ -372,16 +396,19 @@
 #define Panel_1280x960          0x07
 #define Panel_1152x768          0x08	/* LVDS only */
 #define Panel_1400x1050         0x09
-#define Panel_1280x768          0x0a    /* LVDS only */
+#define Panel_1280x768          0x0a    /* 30xB/C and LVDS only (BIOS: all) */
 #define Panel_1600x1200         0x0b
-#define Panel_640x480_2		0x0c
-#define Panel_640x480_3		0x0d
-#define Panel_320x480           0x0e    /* fstn - TW: This is fake, can be any */
-#define Panel_Custom		0x0f
-#define Panel_Barco1366         0x10
-#define Panel_848x480		0x11
-#define Panel_1280x800		0x12    /* 661etc: 0x0c */
-#define Panel_1680x1050         0x13    /* 661etc: 0x0d */
+#define Panel_1280x800		0x0c    /* 661etc  */
+#define Panel_1680x1050         0x0d    /* 661etc  */
+#define Panel_1280x720		0x0e    /* 661etc  */
+#define Panel_Custom		0x0f	/* MUST BE 0x0f (for DVI DDC detection */
+#define Panel_320x480           0x10    /* SiS 550 fstn - TW: This is fake, can be any */
+#define Panel_Barco1366         0x11
+#define Panel_848x480		0x12
+#define Panel_640x480_2		0x13    /* SiS 550 */
+#define Panel_640x480_3		0x14    /* SiS 550 */
+#define Panel_1280x768_2        0x15	/* 30xLV */
+#define Panel_1280x768_3        0x16    /* 30xLV */
 
 /* Index in ModeResInfo table */
 #define SIS_RI_320x200    0
@@ -413,6 +440,8 @@
 #define SIS_RI_1152x768  26
 #define SIS_RI_768x576   27
 #define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800  30
 
 /* CR5F */
 #define IsM650                  0x80
@@ -440,14 +469,22 @@
 #define VCLK108_3_300           0x42   /* Index in VCLKData table (300) */
 #define VCLK100_300             0x43   /* Index in VCLKData table (300) */
 #define VCLK34_300              0x3d   /* Index in VCLKData table (300) */
+#define VCLK_CUSTOM_300		0x46
 #define VCLK65_315              0x0b   /* Index in (VB)VCLKData table (315) */
 #define VCLK108_2_315           0x19   /* Index in (VB)VCLKData table (315) */
 #define VCLK81_315		0x5b   /* Index in (VB)VCLKData table (315) */
-#define VCLK162_315             0x21   /* Index in (VB)VCLKData table (315) */
+#define VCLK162_315             0x5e   /* Index in (VB)VCLKData table (315) */
 #define VCLK108_3_315           0x45   /* Index in VBVCLKData table (315) */
 #define VCLK100_315             0x46   /* Index in VBVCLKData table (315) */
-#define VCLK34_315              0x55   /* Index in VBVCLKData table (315) */
+#define VCLK34_315              0x55
 #define VCLK68_315		0x0d
+#define VCLK69_315		0x5c   /* Index in VBVCLKData table (315) */
+#define VCLK121_315		0x5d   /* Index in VBVCLKData table (315) */
+#define VCLK_1280x720		0x5f
+#define VCLK_1280x768_2		0x60
+#define VCLK_1280x768_3		0x61
+#define VCLK_CUSTOM_315		0x62
+#define VCLK_1280x720_2		0x63
 
 #define TVCLKBASE_300		0x21   /* Indices on TV clocks in VCLKData table (300) */
 #define TVCLKBASE_315	        0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
@@ -457,7 +494,7 @@
 #define HiTVVCLK                0x03   /* Index relative to TVCLKBASE */
 #define HiTVSimuVCLK            0x04   /* Index relative to TVCLKBASE */
 #define HiTVTextVCLK            0x05   /* Index relative to TVCLKBASE */
-#define YPbPr750pVCLK		0x0f   /* NOT relative to TVCLKBASE ! */
+#define YPbPr750pVCLK		0x25   /* Index relative to TVCLKBASE; was 0x0f NOT relative */
 
 /* ------------------------------ */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/oem300.h linux-2.4.26-pre6/drivers/video/sis/oem300.h
--- linux-2.4.25/drivers/video/sis/oem300.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/oem300.h	2004-03-25 00:18:37.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/oem310.h linux-2.4.26-pre6/drivers/video/sis/oem310.h
--- linux-2.4.25/drivers/video/sis/oem310.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/oem310.h	2004-03-25 00:16:51.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -72,7 +69,7 @@ static const UCHAR SiS310_LCDDelayCompen
 };
 
 /* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
-static const UCHAR SiS310_LCDDelayCompensation_650301B[] =	   	/* 30xB,LV */
+static const UCHAR SiS310_LCDDelayCompensation_650301LV[] =	   	/* 650 + 30xLV */
 {
 		 0x01,0x01,0x01,    /*   800x600 */
 		 0x01,0x01,0x01,    /*  1024x768 */
@@ -91,65 +88,7 @@ static const UCHAR SiS310_LCDDelayCompen
 		 0x02,0x02,0x02
 };
 
-/* This data is correct, so we use it instead of the table above */
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
-{
-		 0x01,0x01,0x01,    /*   800x600 */
-		 0x0C,0x0C,0x0C,    /*  1024x768 */
-		 0x0C,0x0C,0x0C,    /* 1280x1024 */
-                 0x08,0x08,0x08,    /*   640x480 */
-		 0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
-		 0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
-		 0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
-		 0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
-		 0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
-		 0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
-		 0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
-		 0x02,0x02,0x02,
-		 0x02,0x02,0x02,
-		 0x02,0x02,0x02,
-		 0x02,0x02,0x02
-};
-
-static const UCHAR SiS310_LCDDelayCompensation_LVDS650[] =   	/* LVDS */
-{
-                 0x00,0x00,0x00,    /*   800x600 */
-		 0x00,0x00,0x00,    /*  1024x768 */
-		 0x00,0x00,0x00,    /* 1280x1024 */
-		 0x00,0x00,0x00,    /*   640x480 (unknown) */
-		 0x00,0x00,0x00,    /*  1024x600 (unknown) */
-		 0x00,0x00,0x00,    /*  1152x864 (unknown) */
-		 0x00,0x00,0x00,    /*  1280x960 (guessed) */
-		 0x00,0x00,0x00,    /*  1152x768 (unknown) */
-		 0x00,0x00,0x00,    /* 1400x1050 */
-		 0x00,0x00,0x00,    /*  1280x768  (guessed) */
-		 0x00,0x00,0x00,    /* 1600x1200 */
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00
-};
-
-static const UCHAR SiS310_LCDDelayCompensation_LVDS740[] =   	/* LVDS */
-{
-                 0x03,0x03,0x03,    /*   800x600 */
-		 0x03,0x03,0x03,    /*  1024x768 */
-		 0x03,0x03,0x03,    /* 1280x1024 */
-		 0x03,0x03,0x03,    /*   640x480 (unknown) */
-		 0x03,0x03,0x03,    /*  1024x600 (unknown) */
-		 0x03,0x03,0x03,    /*  1152x864 (unknown) */
-		 0x03,0x03,0x03,    /*  1280x960 (guessed) */
-		 0x03,0x03,0x03,    /*  1152x768 (unknown) */
-		 0x03,0x03,0x03,    /* 1400x1050 */
-		 0x03,0x03,0x03,    /*  1280x768  (guessed) */
-		 0x03,0x03,0x03,    /* 1600x1200 */
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00
-};
-
-static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =	  /* M650/651 301LV */
+static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =	  	/* M650/651 301LV */
 {
                  0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
 		 0x33,0x33,0x33,    /*  1024x768 */
@@ -168,7 +107,7 @@ static const UCHAR SiS310_LCDDelayCompen
 		 0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =	   /* M650/651 302LV */
+static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =	   	/* M650/651 302LV */
 {
                  0x33,0x33,0x33,    /*   800x600 (guessed) */
 		 0x33,0x33,0x33,    /*  1024x768 */
@@ -187,6 +126,25 @@ static const UCHAR SiS310_LCDDelayCompen
 		 0x33,0x33,0x33
 };
 
+static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
+{
+		 0x01,0x01,0x01,    /*   800x600 */
+		 0x0C,0x0C,0x0C,    /*  1024x768 */
+		 0x0C,0x0C,0x0C,    /* 1280x1024 */
+                 0x08,0x08,0x08,    /*   640x480 */
+		 0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02
+};
+
 static const UCHAR SiS310_TVDelayCompensation_301[] = 		/* 301 */
 {
 		 0x02,0x02,    /* NTSC Enhanced, Standard */
@@ -208,13 +166,6 @@ static const UCHAR SiS310_TVDelayCompens
 		 0x05,0x05
 };
 
-static const UCHAR SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
-{
-		 0x0a,0x0a,
-		 0x0a,0x0a,
-		 0x0a,0x0a
-};
-
 static const UCHAR SiS310_TVDelayCompensation_651301LV[] =	/* M650, 651, 301LV */
 {
 		 0x33,0x33,
@@ -249,6 +200,13 @@ static const UCHAR SiS_TVDelay661_301B[]
 		 0x44,0x44
 };
 
+static const UCHAR SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
+{
+		 0x0a,0x0a,
+		 0x0a,0x0a,
+		 0x0a,0x0a
+};
+
 static const UCHAR SiS310_TVAntiFlick1[6][2] =
 {
             {0x4,0x0},
@@ -451,141 +409,6 @@ static const SiS_LCDDataStruct  SiS310_E
 	{    1,   1,1696,1066,1696,1066}
 };
 
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_1[] =
-{
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x35,0x1B,0xA0,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x45,0x1C,0x20,0x3F,0xFF,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x49,0x1C,0x40,0x7F,0xFF,0xAD,0x23,0x0A,0x07,0xF3,0x8A,0x12}},
- {{0x4C,0x1C,0x18,0x2F,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_2[] =
-{
- {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x33,0x13,0x01,0x0D,0xFD,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x3F,0x1B,0x3D,0x49,0x39,0x54,0x23,0xC0,0x27,0x66,0x30,0x42}},
- {{0x33,0x1B,0x91,0x9D,0x8D,0x8C,0x23,0xF8,0x27,0x9E,0x68,0x42}},
- {{0x43,0x24,0x11,0x1D,0x0D,0xCC,0x23,0x38,0x37,0xDE,0xA8,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xEA,0x23,0x0A,0x07,0x32,0xC6,0x42}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_3[] =
-{
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}}
-};
-
-/* LCDA CRT2 data is std */
-
-static const SiS_LVDSDesStruct Compaq1280x1024Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Compaq1280x1024Des_2[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-/* Clevo L285/287 (dual-link 1024x768) */
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_1[] =
-{
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x2C,0x12,0x9A,0xAE,0x88,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x16,0x0C,0xE6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_2[] =
-{
- {{0x25,0x12,0x51,0x6E,0x48,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xE0,0x12,0xB1,0x47,0x30,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xF4,0x12,0xD9,0x47,0x44,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
-#if 0
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-#endif
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_3[] =
-{
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}}, /* Corrected */
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xC9,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-};
-
-/* CRT2 data is std */
-
-static const SiS_LVDSDesStruct Clevo1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Clevo1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 622 },
-  { 1232, 722 },
-  {    0,   0 }
-};
-
 /* Asus A2xxxH _2 */
 
 static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] =
@@ -601,52 +424,6 @@ static const SiS_Part2PortTblStruct SiS3
  {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-static const SiS_LVDSDesStruct Asus1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Asus1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 622 },
-  { 1232, 722 },
-  {    0,   0 }
-};
-
-/* CRT2 data is std */
-
-/* Uniwill N243S9, ECS A928 */
 
-static const SiS_LVDSDesStruct Uniwill1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 805 }
-};
-
-static const SiS_LVDSDesStruct Uniwill1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 650 },
-  { 1232, 722 },
-  {    0, 805 },
-};
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/osdef.h linux-2.4.26-pre6/drivers/video/sis/osdef.h
--- linux-2.4.25/drivers/video/sis/osdef.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/osdef.h	2004-03-25 00:16:52.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -54,95 +51,77 @@
  */
 
 /* The choices are: */
-
 #define LINUX_KERNEL	   /* Kernel framebuffer */
 /* #define LINUX_XF86 */   /* XFree86 */
 
-/**********************************************************************/
-#ifdef LINUX_KERNEL  /* -------------------------- */
-#include <linux/config.h>
-#include <linux/version.h>
-
-#ifdef CONFIG_FB_SIS_300
-#define SIS300
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#define SIS315H
-#endif
-
-#if 1
-#define SISFBACCEL	/* Include 2D acceleration */
-#endif
-
-#endif
-
-#ifdef LINUX_XF86 /* ----------------------------- */
-#define SIS300
-#define SIS315H
-#endif
-
-/**********************************************************************/
-#ifdef LINUX_XF86
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
-#endif
-
-#ifdef LINUX_KERNEL
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
-#endif
-
-/**********************************************************************/
-
 #ifdef OutPortByte
 #undef OutPortByte
-#endif /* OutPortByte */
+#endif
 
 #ifdef OutPortWord
 #undef OutPortWord
-#endif /* OutPortWord */
+#endif
 
 #ifdef OutPortLong
 #undef OutPortLong
-#endif /* OutPortLong */
+#endif
 
 #ifdef InPortByte
 #undef InPortByte
-#endif /* InPortByte */
+#endif
 
 #ifdef InPortWord
 #undef InPortWord
-#endif /* InPortWord */
+#endif
 
 #ifdef InPortLong
 #undef InPortLong
-#endif /* InPortLong */
+#endif
 
 /**********************************************************************/
-/*  LINUX XF86                                                        */
+/*  LINUX KERNEL                                                      */
 /**********************************************************************/
 
-#ifdef LINUX_XF86
-#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
-#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
-#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
-#define InPortByte(p)    inb((CARD16)(p))
-#define InPortWord(p)    inw((CARD16)(p))
-#define InPortLong(p)    inl((CARD16)(p))
+#ifdef LINUX_KERNEL
+#include <linux/config.h>
+#include <linux/version.h>
+
+#ifdef CONFIG_FB_SIS_300
+#define SIS300
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#define SIS315H
+#endif
+
+#if 1
+#define SISFBACCEL	/* Include 2D acceleration */
+#endif
+
+#define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
+#define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
+#define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
+#define InPortByte(p)    inb((SISIOADDRESS)(p))
+#define InPortWord(p)    inw((SISIOADDRESS)(p))
+#define InPortLong(p)    inl((SISIOADDRESS)(p))
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
 #endif
 
 /**********************************************************************/
-/*  LINUX KERNEL                                                      */
+/*  XFree86                                                           */
 /**********************************************************************/
 
-#ifdef LINUX_KERNEL
-#define OutPortByte(p,v) outb((u8)(v),(u16)(p))
-#define OutPortWord(p,v) outw((u16)(v),(u16)(p))
-#define OutPortLong(p,v) outl((u32)(v),(u16)(p))
-#define InPortByte(p)    inb((u16)(p))
-#define InPortWord(p)    inw((u16)(p))
-#define InPortLong(p)    inl((u16)(p))
+#ifdef LINUX_XF86
+#define SIS300
+#define SIS315H
+
+#define OutPortByte(p,v) outb((IOADDRESS)(p),(CARD8)(v))
+#define OutPortWord(p,v) outw((IOADDRESS)(p),(CARD16)(v))
+#define OutPortLong(p,v) outl((IOADDRESS)(p),(CARD32)(v))
+#define InPortByte(p)    inb((IOADDRESS)(p))
+#define InPortWord(p)    inw((IOADDRESS)(p))
+#define InPortLong(p)    inl((IOADDRESS)(p))
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
 #endif
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/sis_accel.c linux-2.4.26-pre6/drivers/video/sis/sis_accel.c
--- linux-2.4.25/drivers/video/sis/sis_accel.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/sis_accel.c	2004-03-25 00:20:11.000000000 +0000
@@ -77,9 +77,8 @@
 #include "sis_accel.h"
 #include "sis.h"
 
-extern struct     video_info ivideo;
-extern VGA_ENGINE sisvga_engine;
-extern int sisfb_accel;
+extern struct   video_info ivideo;
+extern int 	sisfb_accel;
 
 static const int sisALUConv[] =
 {
@@ -337,7 +336,7 @@ int sisfb_initaccel(void)
 
 void sisfb_syncaccel(void)
 {
-    if(sisvga_engine == SIS_300_VGA) {
+    if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
     	SiS300Sync();
 #endif
@@ -357,7 +356,7 @@ int fbcon_sis_sync(struct fb_info *info)
    if(!ivideo.accel)
    	return 0;
    
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       SiS300Sync();
 #endif
@@ -393,7 +392,7 @@ void fbcon_sis_fillrect(struct fb_info *
 		 break;
    }
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
       SiS300SetupForSolidFill(col, myrops[rect->rop], 0);
@@ -432,7 +431,7 @@ void fbcon_sis_copyarea(struct fb_info *
    if(area->sy < area->dy) ydir = 0;
    else                    ydir = 1;
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
       SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
@@ -494,7 +493,7 @@ void fbcon_sis_bmove(struct display *p, 
 	if(srcy < dsty) ydir = 0;
 	else            ydir = 1;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
 	   SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
@@ -509,10 +508,6 @@ void fbcon_sis_bmove(struct display *p, 
 	   SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
 	   SiS310Sync();
-#if 0
-	   printk(KERN_INFO "sis_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
-		srcx, srcy, dstx, dsty, width, height);
-#endif
 #endif
 	}
 }
@@ -527,7 +522,7 @@ static void fbcon_sis_clear(struct vc_da
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
 	   SiS300SetupForSolidFill(color, 3, 0);
@@ -616,7 +611,7 @@ void fbcon_sis_revc(struct display *p, i
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
 	   SiS300SetupForSolidFill(0, 0x0a, 0);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/sis_accel.h linux-2.4.26-pre6/drivers/video/sis/sis_accel.h
--- linux-2.4.25/drivers/video/sis/sis_accel.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/sis_accel.h	2004-03-25 00:16:55.000000000 +0000
@@ -158,7 +158,15 @@
 #define Q_READ_PTR		0x85C8  /* Current read pointer (?) */
 #define Q_STATUS		0x85CC  /* queue status */
 
+#define MMIO_IN8(base, offset)  readb((base+offset))
+#define MMIO_IN16(base, offset) readw((base+offset))
+#define MMIO_IN32(base, offset) readl((base+offset))
+
+#define MMIO_OUT8(base, offset, val)  writeb((val), (base+offset))
+#define MMIO_OUT16(base, offset, val) writew((val), (base+offset))
+#define MMIO_OUT32(base, offset, val) writel((val), (base+offset))
 
+#if 0
 #define MMIO_IN8(base, offset) \
 	*(volatile u8 *)(((u8*)(base)) + (offset))
 #define MMIO_IN16(base, offset) \
@@ -171,6 +179,7 @@
 	*(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
 #define MMIO_OUT32(base, offset, val) \
 	*(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
+#endif
 
 /* ------------- SiS 300 series -------------- */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/sis_main.c linux-2.4.26-pre6/drivers/video/sis/sis_main.c
--- linux-2.4.25/drivers/video/sis/sis_main.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/sis_main.c	2004-03-25 00:20:52.000000000 +0000
@@ -47,9 +47,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <linux/vmalloc.h>
-#endif
 #include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
@@ -87,14 +85,18 @@
 #include "sis.h"
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#error "This version of sisfb requires at least 2.6.0"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
+#error "This version of sisfb requires at least 2.6.3"
+#else
+#if 0
+#define NEWFBDEV		/* Define this as soon as sysfs support has returned */
+#endif
 #endif
 #endif
 
 /* -------------------- Macro definitions ---------------------------- */
 
-#undef SISFBDEBUG 	/* TW: no debugging */
+#undef SISFBDEBUG 	/* no debugging */
 
 #ifdef SISFBDEBUG
 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -118,170 +120,23 @@ extern struct display_switch fbcon_sis32
 
 /* --------------- Hardware Access Routines -------------------------- */
 
-void sisfb_set_reg4(u16 port, unsigned long data)
-{
-	outl((u32) (data & 0xffffffff), port);
-}
-
-u32 sisfb_get_reg3(u16 port)
-{
-	u32 data;
-
-	data = inl(port);
-	return (data);
-}
-
-/* ------------ Interface for init & mode switching code ------------- */
-
-BOOLEAN
-sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
-	unsigned long offset, unsigned long set, unsigned long *value)
+/* These are used on x86 hardware during probe only */
+static void __devinit
+sisfb_set_reg4(u16 port, u32 data)
 {
-	static struct pci_dev *pdev = NULL;
-	static unsigned char init = 0, valid_pdev = 0;
-
-	if (!set)
-		DPRINTK("sisfb: Get VGA offset 0x%lx\n", offset);
-	else
-		DPRINTK("sisfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
-
-	if (!init) {
-		init = TRUE;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			DPRINTK("sisfb: Current: 0x%x, target: 0x%x\n",
-			         pdev->device, ivideo.chip_id);
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-			           && (pdev->device == ivideo.chip_id)) {
-				valid_pdev = TRUE;
-				break;
-			}
-		}
-	}
-
-	if (!valid_pdev) {
-		printk(KERN_DEBUG "sisfb: Can't find SiS %d VGA device.\n",
-				ivideo.chip_id);
-		return FALSE;
-	}
-
-	if (set == 0)
-		pci_read_config_dword(pdev, offset, (u32 *)value);
-	else
-		pci_write_config_dword(pdev, offset, (u32)(*value));
-
-	return TRUE;
+	outl((u32)(data & 0xffffffff), port);
 }
 
-BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
-	unsigned long offset, unsigned long set, unsigned long *value)
+static u32 __devinit
+sisfb_get_reg3(u16 port)
 {
-	static struct pci_dev *pdev = NULL;
-	static unsigned char init = 0, valid_pdev = 0;
-	u16 nbridge_id = 0;
-
-	if (!init) {
-		init = TRUE;
-		switch (ivideo.chip) {
-#ifdef CONFIG_FB_SIS_300
-		case SIS_540:
-			nbridge_id = PCI_DEVICE_ID_SI_540;
-			break;
-		case SIS_630:
-			nbridge_id = PCI_DEVICE_ID_SI_630;
-			break;
-		case SIS_730:
-			nbridge_id = PCI_DEVICE_ID_SI_730;
-			break;
-#endif
-#ifdef CONFIG_FB_SIS_315
-		case SIS_550:
-			nbridge_id = PCI_DEVICE_ID_SI_550;
-			break;
-		case SIS_650:
-			nbridge_id = PCI_DEVICE_ID_SI_650;
-			break;
-		case SIS_740:
-			nbridge_id = PCI_DEVICE_ID_SI_740;
-			break;
-		case SIS_661:
-			nbridge_id = PCI_DEVICE_ID_SI_660;
-			break;
-		case SIS_741:
-			nbridge_id = PCI_DEVICE_ID_SI_741;
-			break;
-		case SIS_660:
-			nbridge_id = PCI_DEVICE_ID_SI_660;
-			break;
-		case SIS_760:
-			nbridge_id = PCI_DEVICE_ID_SI_760;
-			break;
-#endif
-		default:
-			nbridge_id = 0;
-			break;
-		}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			DPRINTK("Current: 0x%x, target: 0x%x\n",
-					pdev->device, ivideo.chip_id);
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-					&& (pdev->device == nbridge_id)) {
-				valid_pdev = TRUE;
-				break;
-			}
-		}
-	}
-
-	if (!valid_pdev) {
-		printk(KERN_DEBUG "sisfb: Can't find SiS %d North Bridge device.\n",
-				nbridge_id);
-		return FALSE;
-	}
-
-	if (set == 0)
-		pci_read_config_dword(pdev, offset, (u32 *)value);
-	else
-		pci_write_config_dword(pdev, offset, (u32)(*value));
-
-	return TRUE;
+	return((u32)inl(port));
 }
 
 /* ------------------ Internal helper routines ----------------- */
 
-static BOOLEAN sisfb_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
-{
-	int htotal, vtotal;
-	unsigned int dclock, hsync;
-
-	if(!monitor->datavalid) return TRUE;
-
-	if(mode_idx < 0) return FALSE;
-
-	if(rate < (monitor->vmin - 1)) return FALSE;
-	if(rate > (monitor->vmax + 1)) return FALSE;
-
-	if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
-	                          &htotal, &vtotal, rate_idx)) {
-		dclock = (htotal * vtotal * rate) / 1000;
-		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
-		hsync = dclock / htotal;
-		if(hsync < (monitor->hmin - 1)) return FALSE;
-		if(hsync > (monitor->hmax + 1)) return FALSE;
-        } else {
-	  	return FALSE;
-	}
-	return TRUE;
-};
-
-static BOOLEAN sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
+static BOOLEAN __devinit
+sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 {
 	int i, j, xres, yres, refresh, index;
 	u32 emodes;
@@ -381,7 +236,8 @@ static BOOLEAN sisfb_interpret_edid(stru
  	return(monitor->datavalid);
 }
 
-static void sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
+static void __devinit
+sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
 {
 	USHORT  temp, i, realcrtno = crtno;
    	u8      buffer[256];
@@ -396,7 +252,7 @@ static void sisfb_handle_ddc(struct sisf
 
 	if((sisfb_crt1off) && (!crtno)) return;
 
-    	temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, realcrtno, 0, &buffer[0]);
+    	temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, realcrtno, 0, &buffer[0]);
    	if((!temp) || (temp == 0xffff)) {
       	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
 	   return;
@@ -411,7 +267,7 @@ static void sisfb_handle_ddc(struct sisf
       	   if(temp & 0x02) {
 	      i = 3;  /* Number of retrys */
 	      do {
-	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine,
+	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine,
 				     realcrtno, 1, &buffer[0]);
 	      } while((temp) && i--);
               if(!temp) {
@@ -431,7 +287,8 @@ static void sisfb_handle_ddc(struct sisf
 	}
 }
 
-static void sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+static void __init
+sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
 {
 	int i = 0, j = 0;
 
@@ -467,7 +324,8 @@ static void sisfb_search_vesamode(unsign
 	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
 }
 
-static void sisfb_search_mode(char *name, BOOLEAN quiet)
+static void __init
+sisfb_search_mode(char *name, BOOLEAN quiet)
 {
 	int i = 0;
 	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
@@ -538,17 +396,145 @@ static void sisfb_search_mode(char *name
 
 }
 
-static int sisfb_validate_mode(int myindex, unsigned long vbflags)
+static void __init
+sisfb_search_crt2type(const char *name)
+{
+	int i = 0;
+
+	if(name == NULL)
+		return;
+
+	while(sis_crt2type[i].type_no != -1) {
+		if (!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+			sisfb_crt2type = sis_crt2type[i].type_no;
+			sisfb_tvplug = sis_crt2type[i].tvplug_no;
+			sisfb_dstn = (sis_crt2type[i].flags & FL_550_DSTN) ? 1 : 0;
+			sisfb_fstn = (sis_crt2type[i].flags & FL_550_FSTN) ? 1 : 0;
+			break;
+		}
+		i++;
+	}
+	if(sisfb_crt2type < 0)
+		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
+        if(ivideo.chip != SIS_550) {
+	   sisfb_dstn = sisfb_fstn = 0;
+	}
+}
+
+static void __init
+sisfb_search_queuemode(const char *name)
+{
+	int i = 0;
+
+	if(name == NULL)
+		return;
+
+	while (sis_queuemode[i].type_no != -1) {
+		if (!strnicmp(name, sis_queuemode[i].name, strlen(sis_queuemode[i].name))) {
+			sisfb_queuemode = sis_queuemode[i].type_no;
+			break;
+		}
+		i++;
+	}
+	if (sisfb_queuemode < 0)
+		printk(KERN_ERR "sisfb: Invalid queuemode type: %s\n", name);
+}
+
+static void __init
+sisfb_search_tvstd(const char *name)
+{
+	int i = 0;
+
+	if(name == NULL)
+		return;
+
+	while (sis_tvtype[i].type_no != -1) {
+		if (!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+		        ivideo.vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN);
+			ivideo.vbflags |= sis_tvtype[i].type_no;
+			break;
+		}
+		i++;
+	}
+}
+
+static void __init
+sisfb_search_specialtiming(const char *name)
+{
+	int i = 0;
+	BOOLEAN found = FALSE;
+
+	if(name == NULL)
+		return;
+
+	if(!strnicmp(name, "none", 4)) {
+	        SiS_Pr.SiS_CustomT = CUT_FORCENONE;
+		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
+	} else {
+	   while(mycustomttable[i].chipID != 0) {
+	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
+		 SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+		 found = TRUE;
+		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
+		 	mycustomttable[i].optionName);
+		 break;
+	      }
+	      i++;
+	   }
+	   if(!found) {
+	      printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+	      printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+	      i = 0;
+	      while(mycustomttable[i].chipID != 0) {
+		 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+		     mycustomttable[i].optionName,
+		     mycustomttable[i].vendorName,
+		     mycustomttable[i].cardName);
+		 i++;
+	      }
+           }
+ 	}
+}
+
+static BOOLEAN
+sisfb_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
+{
+	int htotal, vtotal;
+	unsigned int dclock, hsync;
+
+	if(!monitor->datavalid) return TRUE;
+
+	if(mode_idx < 0) return FALSE;
+
+	if(rate < (monitor->vmin - 1)) return FALSE;
+	if(rate > (monitor->vmax + 1)) return FALSE;
+
+	if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
+	                          &htotal, &vtotal, rate_idx)) {
+		dclock = (htotal * vtotal * rate) / 1000;
+		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
+		hsync = dclock / htotal;
+		if(hsync < (monitor->hmin - 1)) return FALSE;
+		if(hsync > (monitor->hmax + 1)) return FALSE;
+        } else {
+	  	return FALSE;
+	}
+	return TRUE;
+}
+
+static int
+sisfb_validate_mode(int myindex, unsigned long vbflags)
 {
-   u16 xres, yres, myres;
+   u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
    }
 #endif
 #ifdef CONFIG_FB_SIS_315
-   if(sisvga_engine == SIS_315_VGA) {
+   if(ivideo.sisvga_engine == SIS_315_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
    }
 #endif
@@ -557,7 +543,7 @@ static int sisfb_validate_mode(int myind
 
    switch (vbflags & VB_DISPTYPE_DISP2) {
      case CRT2_LCD:
-	switch (sishw_ext.ulCRT2LCDType) {
+	switch(sishw_ext.ulCRT2LCDType) {
 	case LCD_640x480:  xres =  640; yres =  480;  break;
 	case LCD_800x600:  xres =  800; yres =  600;  break;
         case LCD_1024x600: xres = 1024; yres =  600;  break;
@@ -571,6 +557,9 @@ static int sisfb_validate_mode(int myind
 	case LCD_320x480:  xres =  320; yres =  480;  break; /* FSTN (old) */
 	case LCD_640x480_2:
 	case LCD_640x480_3:xres =  640; yres =  480;  break; /* FSTN (new) */
+	case LCD_1680x1050:xres = 1680; yres = 1050;  break;
+	case LCD_1280x800: xres = 1280; yres =  800;  break;
+	case LCD_1280x720: yres = 1280; yres =  720;  break;
 	default:           xres =    0; yres =    0;  break;
 	}
 
@@ -602,21 +591,21 @@ static int sisfb_validate_mode(int myind
 	   }
 	}
 
-	if(SiS_GetModeID_LCD(sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
+	if(SiS_GetModeID_LCD(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
 	                     0, sisfb_fstn, SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
 	   return(-1);
 	}
 	break;
 
-     case CRT2_TV:  
-	if(SiS_GetModeID_TV(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+     case CRT2_TV:
+	if(SiS_GetModeID_TV(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
 	   return(-1);
 	}
 	break;
 
      case CRT2_VGA:
-        if(SiS_GetModeID_VGA2(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+        if(SiS_GetModeID_VGA2(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
 	   return(-1);
 	}
@@ -626,49 +615,9 @@ static int sisfb_validate_mode(int myind
      return(myindex);
 }
 
-static void sisfb_search_crt2type(const char *name)
-{
-	int i = 0;
 
-	if(name == NULL)
-		return;
-
-	while(sis_crt2type[i].type_no != -1) {
-		if (!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
-			sisfb_crt2type = sis_crt2type[i].type_no;
-			sisfb_tvplug = sis_crt2type[i].tvplug_no;
-			sisfb_dstn = (sis_crt2type[i].flags & FL_550_DSTN) ? 1 : 0;
-			sisfb_fstn = (sis_crt2type[i].flags & FL_550_FSTN) ? 1 : 0;
-			break;
-		}
-		i++;
-	}
-	if(sisfb_crt2type < 0)
-		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
-        if(ivideo.chip != SIS_550) {
-	   sisfb_dstn = sisfb_fstn = 0;
-	}
-}
-
-static void sisfb_search_queuemode(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_queuemode[i].type_no != -1) {
-		if (!strnicmp(name, sis_queuemode[i].name, strlen(sis_queuemode[i].name))) {
-			sisfb_queuemode = sis_queuemode[i].type_no;
-			break;
-		}
-		i++;
-	}
-	if (sisfb_queuemode < 0)
-		printk(KERN_ERR "sisfb: Invalid queuemode type: %s\n", name);
-}
-
-static u8 sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
+static u8
+sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
 {
 	u16 xres, yres;
 	int i = 0;
@@ -676,37 +625,37 @@ static u8 sisfb_search_refresh_rate(unsi
 	xres = sisbios_mode[mode_idx].xres;
 	yres = sisbios_mode[mode_idx].yres;
 
-	sisfb_rate_idx = 0;
+	ivideo.rate_idx = 0;
 	while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
 		if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
 			if (sisfb_vrate[i].refresh == rate) {
-				sisfb_rate_idx = sisfb_vrate[i].idx;
+				ivideo.rate_idx = sisfb_vrate[i].idx;
 				break;
 			} else if (sisfb_vrate[i].refresh > rate) {
 				if ((sisfb_vrate[i].refresh - rate) <= 3) {
 					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
 						rate, sisfb_vrate[i].refresh);
-					sisfb_rate_idx = sisfb_vrate[i].idx;
+					ivideo.rate_idx = sisfb_vrate[i].idx;
 					ivideo.refresh_rate = sisfb_vrate[i].refresh;
 				} else if (((rate - sisfb_vrate[i-1].refresh) <= 2)
 						&& (sisfb_vrate[i].idx != 1)) {
 					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i-1].refresh);
-					sisfb_rate_idx = sisfb_vrate[i-1].idx;
+					ivideo.rate_idx = sisfb_vrate[i-1].idx;
 					ivideo.refresh_rate = sisfb_vrate[i-1].refresh;
 				} 
 				break;
 			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
 				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i].refresh);
-	           		sisfb_rate_idx = sisfb_vrate[i].idx;
+	           		ivideo.rate_idx = sisfb_vrate[i].idx;
 		   		break;
 	       		}
 		}
 		i++;
 	}
-	if (sisfb_rate_idx > 0) {
-		return sisfb_rate_idx;
+	if(ivideo.rate_idx > 0) {
+		return ivideo.rate_idx;
 	} else {
 		printk(KERN_INFO
 			"sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
@@ -714,78 +663,27 @@ static u8 sisfb_search_refresh_rate(unsi
 	}
 }
 
-static void sisfb_search_tvstd(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_tvtype[i].type_no != -1) {
-		if (!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
-			ivideo.vbflags |= sis_tvtype[i].type_no;
-			break;
-		}
-		i++;
-	}
-}
-
-static void sisfb_search_specialtiming(const char *name)
-{
-	int i = 0;
-	BOOLEAN found = FALSE;
-
-	if(name == NULL)
-		return;
-
-	if(!strnicmp(name, "none", 4)) {
-	        SiS_Pr.SiS_CustomT = CUT_FORCENONE;
-		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
-	} else {
-	   while(mycustomttable[i].chipID != 0) {
-	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
-		 SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
-		 found = TRUE;
-		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
-		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
-		 	mycustomttable[i].optionName);
-		 break;
-	      }
-	      i++;
-	   }
-	   if(!found) {
-	      printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
-	      printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
-	      i = 0;
-	      while(mycustomttable[i].chipID != 0) {
-		 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
-		     mycustomttable[i].optionName,
-		     mycustomttable[i].vendorName,
-		     mycustomttable[i].cardName);
-		 i++;
-	      }
-           }
- 	}
-}
 
-static BOOLEAN sisfb_bridgeisslave(void)
+static BOOLEAN
+sisfb_bridgeisslave(void)
 {
    unsigned char P1_00;
 
    if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;
 
    inSISIDXREG(SISPART1,0x00,P1_00);
-   if( ((sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-       ((sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+   if( ((ivideo.sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+       ((ivideo.sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
 	   return TRUE;
    } else {
            return FALSE;
    }
 }
 
-static BOOLEAN sisfballowretracecrt1(void)
+static BOOLEAN
+sisfballowretracecrt1(void)
 {
-   unsigned char temp;
+   u8 temp;
 
    inSISIDXREG(SISCR,0x17,temp);
    if(!(temp & 0x80)) return FALSE;
@@ -796,16 +694,17 @@ static BOOLEAN sisfballowretracecrt1(voi
    return TRUE;
 }
 
-static BOOLEAN sisfbcheckvretracecrt1(void)
+static BOOLEAN
+sisfbcheckvretracecrt1(void)
 {
-
    if(!sisfballowretracecrt1()) return FALSE;
 
    if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
    else 			   return FALSE;
 }
 
-static void sisfbwaitretracecrt1(void)
+static void
+sisfbwaitretracecrt1(void)
 {
    int watchdog;
 
@@ -817,11 +716,12 @@ static void sisfbwaitretracecrt1(void)
    while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
 }
 
-static BOOLEAN sisfbcheckvretracecrt2(void)
+static BOOLEAN
+sisfbcheckvretracecrt2(void)
 {
    unsigned char temp, reg;
 
-   switch(sisvga_engine) {
+   switch(ivideo.sisvga_engine) {
    case SIS_300_VGA:
    	reg = 0x25;
 	break;
@@ -837,7 +737,8 @@ static BOOLEAN sisfbcheckvretracecrt2(vo
    else 	   return TRUE;
 }
 
-static BOOLEAN sisfb_CheckVBRetrace(void)
+static BOOLEAN
+sisfb_CheckVBRetrace(void)
 {
    if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
       if(sisfb_bridgeisslave()) {
@@ -849,7 +750,8 @@ static BOOLEAN sisfb_CheckVBRetrace(void
    return(sisfbcheckvretracecrt1());
 }
 
-static int sisfb_myblank(int blank)
+static int
+sisfb_myblank(int blank)
 {
    u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
    BOOLEAN backlight = TRUE;
@@ -912,8 +814,8 @@ static int sisfb_myblank(int blank)
           ((sisfb_thismonitor.datavalid) &&
            (sisfb_thismonitor.feature & 0xe0))) {
 
-	 if(sisvga_engine == SIS_315_VGA) {
-	    setSISIDXREG(SISCR, 0x63, 0xbf, cr63);
+	 if(ivideo.sisvga_engine == SIS_315_VGA) {
+	    setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 	 }
 
 	 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
@@ -929,7 +831,7 @@ static int sisfb_myblank(int blank)
 	 } else {
 	    SiS_SiS30xBLOff(&SiS_Pr, &sishw_ext);
 	 }
-      } else if(sisvga_engine == SIS_315_VGA) {
+      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
 	 if(ivideo.vbflags & VB_CHRONTEL) {
 	    if(backlight) {
 	       SiS_Chrontel701xBLOn(&SiS_Pr,&sishw_ext);
@@ -939,19 +841,19 @@ static int sisfb_myblank(int blank)
 	 }
       }
 
-      if(((sisvga_engine == SIS_300_VGA) &&
+      if(((ivideo.sisvga_engine == SIS_300_VGA) &&
           (ivideo.vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
-         ((sisvga_engine == SIS_315_VGA) &&
+         ((ivideo.sisvga_engine == SIS_315_VGA) &&
           ((ivideo.vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
           setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
       }
 
-      if(sisvga_engine == SIS_300_VGA) {
+      if(ivideo.sisvga_engine == SIS_300_VGA) {
          if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
             (!(ivideo.vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
 	 }
-      } else if(sisvga_engine == SIS_315_VGA) {
+      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
          if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
             (!(ivideo.vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
@@ -971,7 +873,8 @@ static int sisfb_myblank(int blank)
 
 /* ----------- FBDev related routines for all series ----------- */
 
-static void sisfb_set_vparms(void)
+static void
+sisfb_set_vparms(void)
 {
    switch(ivideo.video_bpp) {
    case 8:
@@ -997,7 +900,8 @@ static void sisfb_set_vparms(void)
    }
 }
 
-static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+static int
+sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      struct fb_info *info)
 {
 	unsigned int htotal = 0, vtotal = 0; 
@@ -1034,11 +938,6 @@ static int sisfb_do_set_var(struct fb_va
 	   ivideo.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
 	} else ivideo.refresh_rate = 60;
 
-#if 0
-	printk(KERN_DEBUG "sisfb: Change mode to %dx%dx%d-%dHz\n",
-		var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);
-#endif		
-
 	old_mode = sisfb_mode_idx;
 	sisfb_mode_idx = 0;
 
@@ -1047,7 +946,7 @@ static int sisfb_do_set_var(struct fb_va
 		if( (sisbios_mode[sisfb_mode_idx].xres == var->xres) &&
 		    (sisbios_mode[sisfb_mode_idx].yres == var->yres) &&
 		    (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) {
-			sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+			ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
 			found_mode = 1;
 			break;
 		}
@@ -1067,14 +966,14 @@ static int sisfb_do_set_var(struct fb_va
 	}
 
 	if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {
-		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+		ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
 		ivideo.refresh_rate = 60;
 	}
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	if(sisfb_thismonitor.datavalid) {
 	   if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-	                         sisfb_rate_idx, ivideo.refresh_rate)) {
+	                         ivideo.rate_idx, ivideo.refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
@@ -1087,8 +986,8 @@ static int sisfb_do_set_var(struct fb_va
 #endif
 		sisfb_pre_setmode();
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
-			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", sisfb_mode_no);
+		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
+			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo.mode_no);
 			return -EINVAL;
 		}
 
@@ -1114,7 +1013,7 @@ static int sisfb_do_set_var(struct fb_va
 		ivideo.current_pixclock = var->pixclock;
 		ivideo.current_refresh_rate = ivideo.refresh_rate;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                sisfb_lastrates[sisfb_mode_no] = ivideo.refresh_rate;
+                sisfb_lastrates[ivideo.mode_no] = ivideo.refresh_rate;
 #endif
 		
 		sisfb_post_setmode();
@@ -1123,7 +1022,8 @@ static int sisfb_do_set_var(struct fb_va
 	return 0;
 }
 
-static int sisfb_pan_var(struct fb_var_screeninfo *var)
+static int
+sisfb_pan_var(struct fb_var_screeninfo *var)
 {
 	unsigned int base;
 
@@ -1154,22 +1054,23 @@ static int sisfb_pan_var(struct fb_var_s
         outSISIDXREG(SISCR, 0x0D, base & 0xFF);
 	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
 	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
-	if(sisvga_engine == SIS_315_VGA) {
+	if(ivideo.sisvga_engine == SIS_315_VGA) {
 		setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
 	}
         if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-		orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
         	outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
         	outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
         	outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
-		if(sisvga_engine == SIS_315_VGA) {
+		if(ivideo.sisvga_engine == SIS_315_VGA) {
 			setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
 		}
         }
 	return 0;
 }
 
-static void sisfb_bpp_to_var(struct fb_var_screeninfo *var)
+static void
+sisfb_bpp_to_var(struct fb_var_screeninfo *var)
 {
 	switch(var->bits_per_pixel) {
 	   case 8:
@@ -1202,7 +1103,8 @@ static void sisfb_bpp_to_var(struct fb_v
 	}
 }
 
-void sis_dispinfo(struct ap_data *rec)
+void
+sis_dispinfo(struct ap_data *rec)
 {
 	rec->minfo.bpp      = ivideo.video_bpp;
 	rec->minfo.xres     = ivideo.video_width;
@@ -1228,7 +1130,8 @@ void sis_dispinfo(struct ap_data *rec)
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
 
-static void sisfb_crtc_to_var(struct fb_var_screeninfo *var)
+static void
+sisfb_crtc_to_var(struct fb_var_screeninfo *var)
 {
 	u16 VRE, VBE, VRS, VBS, VDE, VT;
 	u16 HRE, HBE, HRS, HBS, HDE, HT;
@@ -1417,10 +1320,11 @@ static void sisfb_crtc_to_var(struct fb_
 
 }
 
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+static int
+sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
 			 unsigned *transp, struct fb_info *fb_info)
 {
-	if (regno >= ivideo.video_cmap_len)
+	if(regno >= ivideo.video_cmap_len)
 		return 1;
 
 	*red = sis_palette[regno].red;
@@ -1430,24 +1334,25 @@ static int sis_getcolreg(unsigned regno,
 	return 0;
 }
 
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+static int
+sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
                            unsigned transp, struct fb_info *fb_info)
 {
-	if (regno >= ivideo.video_cmap_len)
+	if(regno >= ivideo.video_cmap_len)
 		return 1;
 
 	sis_palette[regno].red = red;
 	sis_palette[regno].green = green;
 	sis_palette[regno].blue = blue;
 
-	switch (ivideo.video_bpp) {
+	switch(ivideo.video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
 	        outSISREG(SISDACA, regno);
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1473,7 +1378,8 @@ static int sisfb_setcolreg(unsigned regn
 	return 0;
 }
 
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var,
+static void
+sisfb_set_disp(int con, struct fb_var_screeninfo *var,
                            struct fb_info *info)
 {
 	struct fb_fix_screeninfo fix;
@@ -1502,7 +1408,7 @@ static void sisfb_set_disp(int con, stru
 
 	save_flags(flags);
 
-	switch (ivideo.video_bpp) {
+	switch(ivideo.video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	   case 8:
 #ifdef SISFBACCEL
@@ -1548,12 +1454,13 @@ static void sisfb_set_disp(int con, stru
 	}
 }
 
-static void sisfb_do_install_cmap(int con, struct fb_info *info)
+static void
+sisfb_do_install_cmap(int con, struct fb_info *info)
 {
-        if (con != currcon)
+        if(con != currcon)
 		return;
 
-        if (fb_display[con].cmap.len)
+        if(fb_display[con].cmap.len)
 		fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
         else
 		fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1,
@@ -1561,7 +1468,8 @@ static void sisfb_do_install_cmap(int co
 }
 
 
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
+static int
+sisfb_get_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
 	if(con == -1)
@@ -1577,7 +1485,8 @@ static int sisfb_get_var(struct fb_var_s
 	return 0;
 }
 
-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
+static int
+sisfb_set_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
 	int err;
@@ -1611,10 +1520,11 @@ static int sisfb_set_var(struct fb_var_s
 	return 0;
 }
 
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+static int
+sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			  struct fb_info *info)
 {
-        if (con == currcon)
+        if(con == currcon)
 		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
 
 	else if (fb_display[con].cmap.len)
@@ -1625,18 +1535,19 @@ static int sisfb_get_cmap(struct fb_cmap
 	return 0;
 }
 
-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+static int
+sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 			  struct fb_info *info)
 {
 	int err;
 
-	if (!fb_display[con].cmap.len) {
+	if(!fb_display[con].cmap.len) {
 		err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
 		if (err)
 			return err;
 	}
         
-	if (con == currcon)
+	if(con == currcon)
 		return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
 
 	else
@@ -1645,17 +1556,18 @@ static int sisfb_set_cmap(struct fb_cmap
 	return 0;
 }
 
-static int sisfb_pan_display(struct fb_var_screeninfo *var, int con,
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var, int con,
 			     struct fb_info* info)
 {
 	int err;
 
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
+	if(var->vmode & FB_VMODE_YWRAP) {
+		if(var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
 			return -EINVAL;
 	} else {
-		if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
-		    var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+		if(var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
+		   var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
 			return -EINVAL;
 	}
 
@@ -1665,7 +1577,7 @@ static int sisfb_pan_display(struct fb_v
 
 	fb_display[con].var.xoffset = var->xoffset;
 	fb_display[con].var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
+	if(var->vmode & FB_VMODE_YWRAP)
 		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
 	else
 		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
@@ -1673,15 +1585,16 @@ static int sisfb_pan_display(struct fb_v
 	return 0;
 }
 
-static int sisfb_mmap(struct fb_info *info, struct file *file,
+static int
+sisfb_mmap(struct fb_info *info, struct file *file,
 		      struct vm_area_struct *vma)
 {
 	struct fb_var_screeninfo var;
 	unsigned long start;
 	unsigned long off;
-	u32 len, mmio_off;
+	unsigned long len, mmio_off;
 
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
+	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
 
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
@@ -1701,7 +1614,7 @@ static int sisfb_mmap(struct fb_info *in
 		if(var.accel_flags) return -EINVAL;
 
 		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
 	}
 
 	start &= PAGE_MASK;
@@ -1712,18 +1625,19 @@ static int sisfb_mmap(struct fb_info *in
 	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
 
 #if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
+	if(boot_cpu_data.x86 > 3)
 		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
 #endif
         /* RedHat requires vma as the first paramater to the following call */
-	if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
-				vma->vm_page_prot))
+	if(io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot))
 		return -EAGAIN;
 
 	return 0;
 }
 
-static void sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
+static void
+sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
 {
 	struct display *p = &fb_display[currcon];
 	u16 c;
@@ -1737,7 +1651,7 @@ static void sis_get_glyph(struct fb_info
 	widthb = (fontwidth(p) + 7) / 8;
 
 	c = gly->ch & p->charmask;
-	if (fontwidth(p) <= 8)
+	if(fontwidth(p) <= 8)
 		cdat = p->fontdata + c * fontheight(p);
 	else
 		cdat = p->fontdata + (c * fontheight(p) << 1);
@@ -1747,12 +1661,14 @@ static void sis_get_glyph(struct fb_info
 	gly->ngmask = size;
 }
 
-static int sisfb_update_var(int con, struct fb_info *info)
+static int
+sisfb_update_var(int con, struct fb_info *info)
 {
         return(sisfb_pan_var(&fb_display[con].var));
 }
 
-static int sisfb_switch(int con, struct fb_info *info)
+static int
+sisfb_switch(int con, struct fb_info *info)
 {
 	int cols, rows;
 
@@ -1784,7 +1700,8 @@ static int sisfb_switch(int con, struct 
 	return 1;
 }
 
-static void sisfb_blank(int blank, struct fb_info *info)
+static void
+sisfb_blank(int blank, struct fb_info *info)
 {
 	sisfb_myblank(blank);
 }
@@ -1794,17 +1711,20 @@ static void sisfb_blank(int blank, struc
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
-static int sisfb_open(struct fb_info *info, int user)
+static int
+sisfb_open(struct fb_info *info, int user)
 {
     return 0;
 }
 
-static int sisfb_release(struct fb_info *info, int user)
+static int
+sisfb_release(struct fb_info *info, int user)
 {
     return 0;
 }
 
-static int sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
+static int
+sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
 {
 	int rc = 16;		
 
@@ -1820,19 +1740,20 @@ static int sisfb_get_cmap_len(const stru
 	return rc;
 }
 
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *info)
+static int
+sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+		unsigned transp, struct fb_info *info)
 {
-	if (regno >= sisfb_get_cmap_len(&info->var))
+	if(regno >= sisfb_get_cmap_len(&info->var))
 		return 1;
 
-	switch (info->var.bits_per_pixel) {
+	switch(info->var.bits_per_pixel) {
 	case 8:
 	        outSISREG(SISDACA, regno);
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1854,7 +1775,8 @@ static int sisfb_setcolreg(unsigned regn
 	return 0;
 }
 
-static int sisfb_set_par(struct fb_info *info)
+static int
+sisfb_set_par(struct fb_info *info)
 {
 	int err;
 
@@ -1866,8 +1788,9 @@ static int sisfb_set_par(struct fb_info 
 	return 0;
 }
 
-static int sisfb_check_var(struct fb_var_screeninfo *var,
-                           struct fb_info *info)
+static int
+sisfb_check_var(struct fb_var_screeninfo *var,
+                   struct fb_info *info)
 {
 	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
 	unsigned int drate = 0, hrate = 0, maxyres;
@@ -1912,7 +1835,6 @@ static int sisfb_check_var(struct fb_var
 	}
 
 	if(!found_mode) {
-
                 search_idx = 0;
 		while(sisbios_mode[search_idx].mode_no != 0) {
 		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
@@ -2051,32 +1973,33 @@ static int sisfb_check_var(struct fb_var
 	return 0;
 }
 
-static int sisfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info* info)
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var,
+		     struct fb_info* info)
 {
 	int err;
 
-	if (var->xoffset > (var->xres_virtual - var->xres))
+	if(var->xoffset > (var->xres_virtual - var->xres))
 		return -EINVAL;
-	if (var->yoffset > (var->yres_virtual - var->yres))
+	if(var->yoffset > (var->yres_virtual - var->yres))
 		return -EINVAL;
 
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 ||
-		    var->yoffset >= info->var.yres_virtual ||
-		    var->xoffset)
+	if(var->vmode & FB_VMODE_YWRAP) {
+		if(var->yoffset < 0 ||
+		   var->yoffset >= info->var.yres_virtual ||
+		   var->xoffset)
 		    	return -EINVAL;
 	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
+		if(var->xoffset + info->var.xres > info->var.xres_virtual ||
+		   var->yoffset + info->var.yres > info->var.yres_virtual)
 			return -EINVAL;
 	}
-    
+
 	if((err = sisfb_pan_var(var)) < 0) return err;
 
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
+	if(var->vmode & FB_VMODE_YWRAP)
 		info->var.vmode |= FB_VMODE_YWRAP;
 	else
 		info->var.vmode &= ~FB_VMODE_YWRAP;
@@ -2084,12 +2007,13 @@ static int sisfb_pan_display(struct fb_v
 	return 0;
 }
 
-static int sisfb_mmap(struct fb_info *info, struct file *file,
+static int
+sisfb_mmap(struct fb_info *info, struct file *file,
 		      struct vm_area_struct *vma)
 {
 	unsigned long start;
 	unsigned long off;
-	u32 len, mmio_off;
+	unsigned long len, mmio_off;
 
 	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
 
@@ -2110,7 +2034,7 @@ static int sisfb_mmap(struct fb_info *in
 		if(info->var.accel_flags) return -EINVAL;
 
 		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
 	}
 
 	start &= PAGE_MASK;
@@ -2131,7 +2055,8 @@ static int sisfb_mmap(struct fb_info *in
 	return 0;
 }
 
-static int sisfb_blank(int blank, struct fb_info *info)
+static int
+sisfb_blank(int blank, struct fb_info *info)
 {
 	return(sisfb_myblank(blank));
 }
@@ -2207,8 +2132,8 @@ static int sisfb_ioctl(struct inode *ino
 		{
 			unsigned long myhwcoffset = 0;
 
-			if(sisfb_caps & HW_CURSOR_CAP)
-				myhwcoffset = sisfb_hwcursor_vbase -
+			if(ivideo.caps & HW_CURSOR_CAP)
+				myhwcoffset = ivideo.hwcursor_vbase -
 				    (unsigned long) ivideo.video_vbase;
 
 			return put_user(myhwcoffset, (unsigned long *)arg);
@@ -2231,14 +2156,19 @@ static int sisfb_ioctl(struct inode *ino
 			x.chip_id = ivideo.chip_id;
 			x.memory = ivideo.video_size / 1024;
 			x.heapstart = ivideo.heapstart / 1024;
-			x.fbvidmode = sisfb_mode_no;
-			x.sisfb_caps = sisfb_caps;
+			if(ivideo.modechanged) {
+			   x.fbvidmode = ivideo.mode_no;
+			} else {
+			   x.fbvidmode = ivideo.modeprechange;
+			}
+			x.sisfb_caps = ivideo.caps;
 			x.sisfb_tqlen = 512; /* yet fixed */
 			x.sisfb_pcibus = ivideo.pcibus;
 			x.sisfb_pcislot = ivideo.pcislot;
 			x.sisfb_pcifunc = ivideo.pcifunc;
-			x.sisfb_lcdpdc = sisfb_detectedpdc;
-			x.sisfb_lcda = sisfb_detectedlcda;
+			x.sisfb_lcdpdc = ivideo.detectedpdc;
+			x.sisfb_lcdpdca = ivideo.detectedpdca;
+			x.sisfb_lcda = ivideo.detectedlcda;
 			x.sisfb_vbflags = ivideo.vbflags;
 			x.sisfb_currentvbflags = ivideo.currentvbflags;
 			x.sisfb_scalelcd = SiS_Pr.UsePanelScaler;
@@ -2287,8 +2217,9 @@ static int sisfb_ioctl(struct inode *ino
 }
 
 
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
+static int
+sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+	      struct fb_info *info)
 {
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
@@ -2301,7 +2232,7 @@ static int sisfb_get_fix(struct fb_fix_s
 	fix->smem_start = ivideo.video_base;
 
         if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-	    if(sisvga_engine == SIS_300_VGA) {
+	    if(ivideo.sisvga_engine == SIS_300_VGA) {
 	       if(ivideo.video_size > 0x1000000) {
 	          	fix->smem_len = 0xc00000;
 	       } else if(ivideo.video_size > 0x800000)
@@ -2327,8 +2258,8 @@ static int sisfb_get_fix(struct fb_fix_s
 	fix->ywrapstep   = 0;
 	fix->line_length = ivideo.video_linelength;
 	fix->mmio_start  = ivideo.mmio_base;
-	fix->mmio_len    = sisfb_mmio_size;
-	if(sisvga_engine == SIS_300_VGA) 
+	fix->mmio_len    = ivideo.mmio_size;
+	if(ivideo.sisvga_engine == SIS_300_VGA) 
 	   fix->accel    = FB_ACCEL_SIS_GLAMOUR;
 	else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_760))
 	   fix->accel    = FB_ACCEL_SIS_XABRE;
@@ -2338,7 +2269,7 @@ static int sisfb_get_fix(struct fb_fix_s
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	fix->reserved[0] = ivideo.video_size & 0xFFFF;
 	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
-	fix->reserved[2] = sisfb_caps;
+	fix->reserved[2] = ivideo.caps;
 #endif
 
 	return 0;
@@ -2386,14 +2317,14 @@ static struct fb_ops sisfb_ops = {
 
 #ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
 
-static int sisfb_get_dram_size_300(void)
+static int __devinit sisfb_get_dram_size_300(void)
 {
 	struct pci_dev *pdev = NULL;
 	int pdev_valid = 0;
 	u8  pci_data, reg;
 	u16 nbridge_id;
 
-	switch (ivideo.chip) {
+	switch(ivideo.chip) {
 	   case SIS_540:
 		nbridge_id = PCI_DEVICE_ID_SI_540;
 		break;
@@ -2408,7 +2339,7 @@ static int sisfb_get_dram_size_300(void)
 		break;
 	}
 
-	if (nbridge_id == 0) {  /* 300 */
+	if(nbridge_id == 0) {   /* 300 */
 
 	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg);
 		ivideo.video_size =
@@ -2427,7 +2358,7 @@ static int sisfb_get_dram_size_300(void)
 				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
 				ivideo.video_size = (unsigned int)(1 << (pci_data+21));
 				pdev_valid = 1;
-	
+
 				reg = SIS_DATA_BUS_64 << 6;
 				switch (pci_data) {
 				   case BRI_DRAM_SIZE_2MB:
@@ -2464,7 +2395,7 @@ static int sisfb_get_dram_size_300(void)
 
 #ifdef CONFIG_FB_SIS_315    /* for SiS 315/550/650/740/330/661/741/760 */
 
-static int sisfb_get_dram_size_315(void)
+static int __devinit sisfb_get_dram_size_315(void)
 {
 	u8  reg = 0;
 
@@ -2480,9 +2411,7 @@ static int sisfb_get_dram_size_315(void)
 		return 0;
 
 	} else if(ivideo.chip == SIS_661 ||
-	          ivideo.chip == SIS_741 ||
-		  ivideo.chip == SIS_660 ||
-		  ivideo.chip == SIS_760) {
+	          ivideo.chip == SIS_741) {
 
 		inSISIDXREG(SISCR, 0x79, reg);
 		reg &= 0xf0;
@@ -2490,6 +2419,22 @@ static int sisfb_get_dram_size_315(void)
 		ivideo.video_size = (1 << reg) << 20;
 		return 0;
 
+	} else if(ivideo.chip == SIS_660 ||
+		  ivideo.chip == SIS_760) {
+
+		ivideo.video_size = 0;
+		inSISIDXREG(SISCR, 0x79, reg);
+		reg &= 0xf0;
+		reg >>= 4;
+		if(reg)	ivideo.video_size = (1 << reg) << 20;
+		inSISIDXREG(SISCR, 0x78, reg);
+		reg &= 0x30;
+		if(reg) {
+		   if(reg == 0x10) ivideo.video_size += (32 << 20);
+		   else		   ivideo.video_size += (64 << 20);
+		}
+		return 0;
+
 	} else {	/* 315, 330 */
 
 	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
@@ -2529,38 +2474,18 @@ static int sisfb_get_dram_size_315(void)
 
 /* -------------- video bridge detection --------------- */
 
-static void sisfb_detect_VB_connect()
+static void __devinit sisfb_detect_VB_connect()
 {
 	u8 sr16, sr17, cr32, temp;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 	
 		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
 	      
 		if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
-	
-			/* Old BIOSes store the detected CRT2 type in SR17
-		 	 * instead of CR32. However, since our detection
-			 * routines store their results to CR32, we now copy
-			 * the remaining bits (for LCD and VGA) to CR32 for
-			 * unified usage.
-			 * SR17[0] CRT1    [1] LCD     [2] TV    [3] VGA2
-			 *     [4] AVIDEO  [5] SVIDEO
-			 */
-
-#if 0
-			if (sr17 & 0x01) orSISIDXREG(SISCR, 0x32, SIS_CRT1);
-			else		 andSISIDXREG(SISCR, 0x32, ~SIS_CRT1);
-
-			if (sr17 & 0x02) orSISIDXREG(SISCR, 0x32, SIS_VB_LCD);
-			else		 andSISIDXREG(SISCR, 0x32, ~SIS_VB_LCD);
 
-			/* no HiVision and no DVI connector here */
-			andSISIDXREG(SISCR, 0x32, ~0xc0);
-#endif
-		
 			/* PAL/NTSC is stored on SR16 on such machines */
-			if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
+			if (!(ivideo.vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
 		   		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
 				if (sr16 & 0x20)
 					ivideo.vbflags |= TV_PAL;
@@ -2574,69 +2499,54 @@ static void sisfb_detect_VB_connect()
 	
 	inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
 
-	if (cr32 & SIS_CRT1)
+	if(cr32 & SIS_CRT1) {
 		sisfb_crt1off = 0;
-	else {
-		if (cr32 & 0x5F)
-			sisfb_crt1off = 1;
-		else
-			sisfb_crt1off = 0;
+	} else {
+		if (cr32 & 0x5F) sisfb_crt1off = 1;
+		else		 sisfb_crt1off = 0;
 	}
 
 	ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
 
-	if (cr32 & SIS_VB_TV)
-		ivideo.vbflags |= CRT2_TV;
-	if (cr32 & SIS_VB_LCD)
-		ivideo.vbflags |= CRT2_LCD;
-	if (cr32 & SIS_VB_CRT2)
-		ivideo.vbflags |= CRT2_VGA;
+	if(cr32 & SIS_VB_TV)   ivideo.vbflags |= CRT2_TV;
+	if(cr32 & SIS_VB_LCD)  ivideo.vbflags |= CRT2_LCD;
+	if(cr32 & SIS_VB_CRT2) ivideo.vbflags |= CRT2_VGA;
 		
-	/* TW: Detect/set TV plug & type */
-	if(sisfb_tvplug != -1)
-	        ivideo.vbflags |= sisfb_tvplug;
+	/* Detect/set TV plug & type */
+	if(sisfb_tvplug != -1) ivideo.vbflags |= sisfb_tvplug;
 
-	if (cr32 & SIS_VB_SVIDEO)
-		ivideo.vbflags |= TV_SVIDEO;
-	else if (cr32 & SIS_VB_COMPOSITE)
-		ivideo.vbflags |= TV_AVIDEO;
-	else if (cr32 & SIS_VB_SCART)
-		ivideo.vbflags |= TV_SCART;
-		
-	if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
-		if(sisvga_engine == SIS_300_VGA) {
+	if(cr32 & SIS_VB_SVIDEO)	  ivideo.vbflags |= TV_SVIDEO;
+	else if (cr32 & SIS_VB_COMPOSITE) ivideo.vbflags |= TV_AVIDEO;
+	else if (cr32 & SIS_VB_SCART) {
+		ivideo.vbflags |= (TV_SCART | TV_PAL);
+		ivideo.vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN);
+	}
+
+	if(!(ivideo.vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
+		if(ivideo.sisvga_engine == SIS_300_VGA) {
 	        	inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp);
-			if (temp & 0x01)
-				ivideo.vbflags |= TV_PAL;
-			else
-				ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x01) ivideo.vbflags |= TV_PAL;
+			else		ivideo.vbflags |= TV_NTSC;
 		} else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip >= SIS_330)) {
-
                 	inSISIDXREG(SISSR, 0x38, temp);
-			if(temp & 0x01)
-				ivideo.vbflags |= TV_PAL;
-			else
-				ivideo.vbflags |= TV_NTSC;
-		
+			if(temp & 0x01) ivideo.vbflags |= TV_PAL;
+			else		ivideo.vbflags |= TV_NTSC;
 	    	} else {
-
 	        	inSISIDXREG(SISCR, 0x79, temp);
-			if(temp & 0x20)
-				ivideo.vbflags |= TV_PAL;
-			else
-				ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x20)	ivideo.vbflags |= TV_PAL;
+			else		ivideo.vbflags |= TV_NTSC;
 	    	}
 	}
 
-	/* TW: Copy forceCRT1 option to CRT1off if option is given */
-    	if (sisfb_forcecrt1 != -1) {
+	/* Copy forceCRT1 option to CRT1off if option is given */
+    	if(sisfb_forcecrt1 != -1) {
     		if(sisfb_forcecrt1) sisfb_crt1off = 0;
 		else                sisfb_crt1off = 1;
     	}
 
 }
 
-static void sisfb_get_VB_type(void)
+static void __devinit sisfb_get_VB_type(void)
 {
 	u8 vb_chipid;
 	u8 reg;
@@ -2648,7 +2558,6 @@ static void sisfb_get_VB_type(void)
 	ivideo.hasVB = HASVB_NONE;
 	sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
 	sishw_ext.Is301BDH = FALSE;
-	sishw_ext.usExternalChip = 0;
 
 	inSISIDXREG(SISPART4, 0x00, vb_chipid);
 	switch (vb_chipid) {
@@ -2693,27 +2602,9 @@ static void sisfb_get_VB_type(void)
 		break;
 	   case 0x02:
 		ivideo.hasVB = HASVB_302;
-		inSISIDXREG(SISPART4, 0x01, reg);
-		if(reg < 0xd0) {
-			ivideo.vbflags |= VB_302B;
-			sishw_ext.ujVBChipID = VB_CHIP_302B;
-			inSISIDXREG(SISPART4,0x23,reg);
-		  	if(!(reg & 0x02)) {
-			   sishw_ext.Is301BDH = TRUE;
-			   ivideo.vbflags |= VB_30xBDH;
-			   printk(KERN_INFO "%s SiS302B-DH %s\n", stdstr, bridgestr);
-			} else {
-			   printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
-			}
-		} else if(reg < 0xe0) {
-		 	ivideo.vbflags |= VB_301LV;
-			sishw_ext.ujVBChipID = VB_CHIP_301LV;
-			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
-		} else if(reg <= 0xe1) {
-			ivideo.vbflags |= VB_302LV;
-			sishw_ext.ujVBChipID = VB_CHIP_302LV;
-			printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
-		}
+		ivideo.vbflags |= VB_302B;
+		sishw_ext.ujVBChipID = VB_CHIP_302B;
+		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
 		break;
 	}
 
@@ -2721,49 +2612,70 @@ static void sisfb_get_VB_type(void)
 		inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
 		reg &= SIS_EXTERNAL_CHIP_MASK;
 		reg >>= 1;
-		if(sisvga_engine == SIS_300_VGA) {
+		if(ivideo.sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
 			switch (reg) {
 			   case SIS_EXTERNAL_CHIP_LVDS:
 				ivideo.hasVB = HASVB_LVDS;
 				ivideo.vbflags |= VB_LVDS;
-				sishw_ext.usExternalChip = 0x01;
 				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
 				break;
 			   case SIS_EXTERNAL_CHIP_TRUMPION:
 				ivideo.hasVB = HASVB_TRUMPION;
-				sishw_ext.usExternalChip = 0x02;
+				ivideo.vbflags |= VB_TRUMPION;
 				printk(KERN_INFO "%s Trumpion LCD scaler\n", stdstr);
 				break;
 			   case SIS_EXTERNAL_CHIP_CHRONTEL:
 				ivideo.hasVB = HASVB_CHRONTEL;
 				ivideo.vbflags |= VB_CHRONTEL;
-				sishw_ext.usExternalChip = 0x04;
 				printk(KERN_INFO "%s %s\n", stdstr, chrstr);
 				break;
 			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
 				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
 				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				sishw_ext.usExternalChip = 0x05;
 				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
 				break;
 			}
+#endif
 		} else if(ivideo.chip < SIS_661) {
+#ifdef CONFIG_FB_SIS_315
 			switch (reg) {
 	 	   	   case SIS310_EXTERNAL_CHIP_LVDS:
 				ivideo.hasVB = HASVB_LVDS;
 				ivideo.vbflags |= VB_LVDS;
-				sishw_ext.usExternalChip = 0x01;
 				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
 				break;
 		   	   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
 				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
 				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				sishw_ext.usExternalChip = 0x05;
 				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
 				break;
 			}
+#endif
+		} else if(ivideo.chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+			inSISIDXREG(SISCR, 0x38, reg);
+			reg >>= 5;
+			switch(reg) {
+			   case 0x02:
+			   	ivideo.hasVB = HASVB_LVDS;
+				ivideo.vbflags |= VB_LVDS;
+				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				break;
+			   case 0x03:
+			   	ivideo.hasVB = HASVB_LVDS_CHRONTEL;
+				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
+				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				break;
+			   case 0x04:
+			        ivideo.hasVB = HASVB_NONE;
+				ivideo.vbflags |= (VB_LVDS | VB_CONEXANT);
+				printk(KERN_INFO "%s Conexant video bridge\n", stdstr);
+				break;
+			}
+#endif
 		}
-	
+
 	}
 	
 	if(ivideo.vbflags & VB_SISBRIDGE) {
@@ -2776,8 +2688,7 @@ static void sisfb_get_VB_type(void)
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN
-sisfb_test_DDC1(void)
+static BOOLEAN __devinit sisfb_test_DDC1(void)
 {
     unsigned short old;
     int count = 48;
@@ -2789,8 +2700,7 @@ sisfb_test_DDC1(void)
     return (count == -1) ? FALSE : TRUE;
 }
 
-static void
-sisfb_sense_crt1(void)
+static void __devinit sisfb_sense_crt1(void)
 {
     unsigned char SR1F, CR63=0, CR17;
     unsigned short temp = 0xffff;
@@ -2802,10 +2712,10 @@ sisfb_sense_crt1(void)
     andSISIDXREG(SISSR,0x1F,0x3F);
     if(SR1F & 0xc0) mustwait = TRUE;
 
-    if(sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,0x63,CR63);
+    if(ivideo.sisvga_engine == SIS_315_VGA) {
+       inSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,CR63);
        CR63 &= 0x40;
-       andSISIDXREG(SISCR,0x63,0xBF);
+       andSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF);
     }
 
     inSISIDXREG(SISCR,0x17,CR17);
@@ -2823,7 +2733,7 @@ sisfb_sense_crt1(void)
 
     i = 3;
     do {
-       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, 0, 0, NULL);
+       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, 0, 0, NULL);
     } while(((temp == 0) || (temp == 0xffff)) && i--);
 
     if((temp == 0) || (temp == 0xffff)) {
@@ -2834,8 +2744,8 @@ sisfb_sense_crt1(void)
        orSISIDXREG(SISCR,0x32,0x20);
     }
 
-    if(sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,0x63,0xBF,CR63);
+    if(ivideo.sisvga_engine == SIS_315_VGA) {
+       setSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF,CR63);
     }
 
     setSISIDXREG(SISCR,0x17,0x7F,CR17);
@@ -2844,8 +2754,7 @@ sisfb_sense_crt1(void)
 }
 
 /* Determine and detect attached devices on SiS30x */
-int
-SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+static int __devinit SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
 {
     int temp;
 
@@ -2860,8 +2769,7 @@ SISDoSense(int tempbl, int tempbh, int t
     return((temp == tempch));
 }
 
-void
-SiS_Sense30x(void)
+static void __devinit SiS_Sense30x(void)
 {
   u8 backupP4_0d,backupP2_00;
   u8 svhs_bl, svhs_bh;
@@ -2880,7 +2788,7 @@ SiS_Sense30x(void)
   inSISIDXREG(SISPART2,0x00,backupP2_00);
   outSISIDXREG(SISPART2,0x00,(backupP2_00 | 0x1c));
 
-  if(sisvga_engine == SIS_300_VGA) {
+  if(ivideo.sisvga_engine == SIS_300_VGA) {
 
 	if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)) {
 	   	vga2_bh = 0x01; vga2_bl = 0x90;
@@ -2890,20 +2798,21 @@ SiS_Sense30x(void)
 		vga2_bh = 0x00; vga2_bl = 0xd1;
         	svhs_bh = 0x00; svhs_bl = 0xb9;
 		cvbs_bh = 0x00; cvbs_bl = 0xb3;
+		inSISIDXREG(SISPART4,0x01,myflag);
+	        if(myflag & 0x04) {
+	           vga2_bh = 0x00; vga2_bl = 0xfd;
+	           svhs_bh = 0x00; svhs_bl = 0xdd;
+	      	   cvbs_bh = 0x00; cvbs_bl = 0xee;
+	        }
 	}
-	inSISIDXREG(SISPART4,0x01,myflag);
-	if(myflag & 0x04) {
-	   vga2_bh = 0x00; vga2_bl = 0xfd;
-	   svhs_bh = 0x00; svhs_bl = 0xdd;
-	   cvbs_bh = 0x00; cvbs_bl = 0xee;
-	}
+
 	vga2_ch = 0x0e;	vga2_cl = 0x08;
 	svhs_ch = 0x04;	svhs_cl = 0x04;
 	cvbs_ch = 0x08; cvbs_cl = 0x04;
 	if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
 	   	vga2_bh = 0x00; vga2_bl = 0x00;
 	   	vga2_ch = 0x00; vga2_cl = 0x00;
-	 }
+	}
 	if(ivideo.chip == SIS_300) {
 	   inSISIDXREG(SISSR,0x3b,myflag);
 	   if(!(myflag & 0x01)) {
@@ -2968,10 +2877,6 @@ SiS_Sense30x(void)
        }
     }
 
-    if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
-       orSISIDXREG(SISPART4,0x0d,0x04);
-    }
-
     haveresult = 0;
     for(j = 0; j < 10; j++) {
        result = 0;
@@ -3014,11 +2919,9 @@ SiS_Sense30x(void)
     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
 }
 
-/* TW: Determine and detect attached TV's on Chrontel */
-void
-SiS_SenseCh(void)
+/* Determine and detect attached TV's on Chrontel */
+static void __devinit SiS_SenseCh(void)
 {
-
    u8 temp1, temp2;
 #ifdef CONFIG_FB_SIS_300
    unsigned char test[3];
@@ -3143,16 +3046,17 @@ SiS_SenseCh(void)
 
 /* ------------------------ Heap routines -------------------------- */
 
-static int sisfb_heap_init(void)
+static int __devinit
+sisfb_heap_init(void)
 {
 	SIS_OH *poh;
 	u8 temp=0;
 #ifdef CONFIG_FB_SIS_315
 	int            agp_enabled = 1;
 	u32            agp_size;
-	unsigned long *cmdq_baseport = 0;
-	unsigned long *read_port = 0;
-	unsigned long *write_port = 0;
+	unsigned long  *cmdq_baseport = 0;
+	unsigned long  *read_port = 0;
+	unsigned long  *write_port = 0;
 	SIS_CMDTYPE    cmd_type;
 #ifndef AGPOFF
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
@@ -3162,7 +3066,7 @@ static int sisfb_heap_init(void)
 	agp_kern_info  *agp_info;
 	agp_memory     *agp;
 #endif
-	u32            agp_phys;
+	unsigned long  agp_phys;
 #endif
 #endif
 /*     The heap start is either set manually using the "mem" parameter, or
@@ -3179,8 +3083,8 @@ static int sisfb_heap_init(void)
  *     On the 315 and Xabre series, the default is a 1MB heap since DRI is not
  *     supported there.
  */
-     if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-        if(sisvga_engine == SIS_300_VGA) {
+     if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
+        if(ivideo.sisvga_engine == SIS_300_VGA) {
            if (ivideo.video_size > 0x1000000) {
 	        ivideo.heapstart = 0xc00000;
 	   } else if (ivideo.video_size > 0x800000) {
@@ -3194,8 +3098,7 @@ static int sisfb_heap_init(void)
      } else {
            ivideo.heapstart = sisfb_mem * 1024;
      }
-     sisfb_heap_start =
-	       (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
+     sisfb_heap_start = (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
      printk(KERN_INFO "sisfb: Memory heap starting at %dK\n",
      					(int)(ivideo.heapstart / 1024));
 
@@ -3203,8 +3106,8 @@ static int sisfb_heap_init(void)
      sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
 
 #ifdef CONFIG_FB_SIS_315
-     if (sisvga_engine == SIS_315_VGA) {
-        /* Now initialize the 310 series' command queue mode.
+     if(ivideo.sisvga_engine == SIS_315_VGA) {
+        /* Now initialize the 315/330 series' command queue mode.
 	 * On 315, there are three queue modes available which
 	 * are chosen by setting bits 7:5 in SR26:
 	 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
@@ -3275,12 +3178,11 @@ static int sisfb_heap_init(void)
 	agp_enabled = 0;
 #endif
 
-	/* TW: Now select the queue mode */
+	/* Now select the queue mode */
 
-	if ((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
+	if((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
 		cmd_type = AGP_CMD_QUEUE;
 		printk(KERN_INFO "sisfb: Using AGP queue mode\n");
-/*	} else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
         } else if (sisfb_queuemode == VM_CMD_QUEUE) {
 		cmd_type = VM_CMD_QUEUE;
 		printk(KERN_INFO "sisfb: Using VRAM queue mode\n");
@@ -3326,7 +3228,7 @@ static int sisfb_heap_init(void)
 
 		*cmdq_baseport = agp_phys;
 
-		sisfb_caps |= AGP_CMD_QUEUE_CAP;
+		ivideo.caps |= AGP_CMD_QUEUE_CAP;
 #endif
 		break;
 
@@ -3345,10 +3247,8 @@ static int sisfb_heap_init(void)
 
 		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
 
-		sisfb_caps |= VM_CMD_QUEUE_CAP;
+		ivideo.caps |= VM_CMD_QUEUE_CAP;
 
-		DPRINTK("sisfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
 		break;
 
 	   default:  /* MMIO */
@@ -3366,18 +3266,16 @@ static int sisfb_heap_init(void)
 
 		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
 
-		sisfb_caps |= MMIO_CMD_QUEUE_CAP;
+		ivideo.caps |= MMIO_CMD_QUEUE_CAP;
 
-		DPRINTK("sisfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
 		break;
 	}
      } /* sisvga_engine = 315 */
 #endif
 
 #ifdef CONFIG_FB_SIS_300
-     if (sisvga_engine == SIS_300_VGA) {
-  	    /* TW: Now initialize TurboQueue. TB is always located at the very
+     if(ivideo.sisvga_engine == SIS_300_VGA) {
+  	    /* Now initialize TurboQueue. TB is always located at the very
 	     * top of the video RAM. */
 	    if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
 		unsigned int  tqueue_pos;
@@ -3396,26 +3294,22 @@ static int sisfb_heap_init(void)
 
 		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, temp);
 
-		sisfb_caps |= TURBO_QUEUE_CAP;
+		ivideo.caps |= TURBO_QUEUE_CAP;
 
 		sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
 		sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
-		DPRINTK("sisfb: TurboQueue start at 0x%lx, size is %dK\n",
-			sisfb_heap_end, TURBO_QUEUE_AREA_SIZE/1024);
+
 	    }
      }
 #endif
-     /* TW: Now reserve memory for the HWCursor. It is always located at the very
-            top of the videoRAM, right below the TB memory area (if used). */
-     if (sisfb_heap_size >= sisfb_hwcursor_size) {
-		sisfb_heap_end -= sisfb_hwcursor_size;
-		sisfb_heap_size -= sisfb_hwcursor_size;
-		sisfb_hwcursor_vbase = sisfb_heap_end;
+     /* Now reserve memory for the HWCursor. It is always located at the very
+        top of the videoRAM, right below the TB memory area (if used). */
+     if(sisfb_heap_size >= ivideo.hwcursor_size) {
+		sisfb_heap_end -= ivideo.hwcursor_size;
+		sisfb_heap_size -= ivideo.hwcursor_size;
+		ivideo.hwcursor_vbase = sisfb_heap_end;
 
-		sisfb_caps |= HW_CURSOR_CAP;
-
-		DPRINTK("sisfb: Hardware Cursor start at 0x%lx, size is %dK\n",
-			sisfb_heap_end, sisfb_hwcursor_size/1024);
+		ivideo.caps |= HW_CURSOR_CAP;
      }
 
      sisfb_heap.poha_chain = NULL;
@@ -3449,14 +3343,15 @@ static int sisfb_heap_init(void)
      return 0;
 }
 
-static SIS_OH *sisfb_poh_new_node(void)
+static SIS_OH *
+sisfb_poh_new_node(void)
 {
 	int           i;
 	unsigned long cOhs;
 	SIS_OHALLOC   *poha;
 	SIS_OH        *poh;
 
-	if (sisfb_heap.poh_freelist == NULL) {
+	if(sisfb_heap.poh_freelist == NULL) {
 		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
 		if(!poha) return NULL;
 
@@ -3466,7 +3361,7 @@ static SIS_OH *sisfb_poh_new_node(void)
 		cOhs = (OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
 
 		poh = &poha->aoh[0];
-		for (i = cOhs - 1; i != 0; i--) {
+		for(i = cOhs - 1; i != 0; i--) {
 			poh->poh_next = poh + 1;
 			poh = poh + 1;
 		}
@@ -3481,13 +3376,14 @@ static SIS_OH *sisfb_poh_new_node(void)
 	return (poh);
 }
 
-static SIS_OH *sisfb_poh_allocate(unsigned long size)
+static SIS_OH *
+sisfb_poh_allocate(unsigned long size)
 {
 	SIS_OH *pohThis;
 	SIS_OH *pohRoot;
 	int     bAllocated = 0;
 
-	if (size > sisfb_heap.max_freesize) {
+	if(size > sisfb_heap.max_freesize) {
 		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
 			(unsigned int) size / 1024);
 		return (NULL);
@@ -3495,7 +3391,7 @@ static SIS_OH *sisfb_poh_allocate(unsign
 
 	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &sisfb_heap.oh_free) {
+	while(pohThis != &sisfb_heap.oh_free) {
 		if (size <= pohThis->size) {
 			bAllocated = 1;
 			break;
@@ -3503,19 +3399,19 @@ static SIS_OH *sisfb_poh_allocate(unsign
 		pohThis = pohThis->poh_next;
 	}
 
-	if (!bAllocated) {
+	if(!bAllocated) {
 		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
 
-	if (size == pohThis->size) {
+	if(size == pohThis->size) {
 		pohRoot = pohThis;
 		sisfb_delete_node(pohThis);
 	} else {
 		pohRoot = sisfb_poh_new_node();
 
-		if (pohRoot == NULL) {
+		if(pohRoot == NULL) {
 			return (NULL);
 		}
 
@@ -3534,7 +3430,8 @@ static SIS_OH *sisfb_poh_allocate(unsign
 	return (pohRoot);
 }
 
-static void sisfb_delete_node(SIS_OH *poh)
+static void
+sisfb_delete_node(SIS_OH *poh)
 {
 	SIS_OH *poh_prev;
 	SIS_OH *poh_next;
@@ -3544,10 +3441,10 @@ static void sisfb_delete_node(SIS_OH *po
 
 	poh_prev->poh_next = poh_next;
 	poh_next->poh_prev = poh_prev;
-
 }
 
-static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
+static void
+sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
 {
 	SIS_OH *pohTemp;
 
@@ -3560,7 +3457,8 @@ static void sisfb_insert_node(SIS_OH *po
 	poh->poh_next = pohTemp;
 }
 
-static SIS_OH *sisfb_poh_free(unsigned long base)
+static SIS_OH *
+sisfb_poh_free(unsigned long base)
 {
 	SIS_OH *pohThis;
 	SIS_OH *poh_freed;
@@ -3581,7 +3479,7 @@ static SIS_OH *sisfb_poh_free(unsigned l
 		poh_freed = poh_freed->poh_next;
 	}
 
-	if (!foundNode)  return (NULL);
+	if(!foundNode)  return(NULL);
 
 	sisfb_heap.max_freesize += poh_freed->size;
 
@@ -3591,12 +3489,11 @@ static SIS_OH *sisfb_poh_free(unsigned l
 
 	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &sisfb_heap.oh_free) {
-		if (pohThis->offset == ulUpper) {
+	while(pohThis != &sisfb_heap.oh_free) {
+		if(pohThis->offset == ulUpper) {
 			poh_next = pohThis;
 		}
-			else if ((pohThis->offset + pohThis->size) ==
-				 ulLower) {
+			else if((pohThis->offset + pohThis->size) == ulLower) {
 			poh_prev = pohThis;
 		}
 		pohThis = pohThis->poh_next;
@@ -3604,42 +3501,43 @@ static SIS_OH *sisfb_poh_free(unsigned l
 
 	sisfb_delete_node(poh_freed);
 
-	if (poh_prev && poh_next) {
+	if(poh_prev && poh_next) {
 		poh_prev->size += (poh_freed->size + poh_next->size);
 		sisfb_delete_node(poh_next);
 		sisfb_free_node(poh_freed);
 		sisfb_free_node(poh_next);
-		return (poh_prev);
+		return(poh_prev);
 	}
 
-	if (poh_prev) {
+	if(poh_prev) {
 		poh_prev->size += poh_freed->size;
 		sisfb_free_node(poh_freed);
-		return (poh_prev);
+		return(poh_prev);
 	}
 
-	if (poh_next) {
+	if(poh_next) {
 		poh_next->size += poh_freed->size;
 		poh_next->offset = poh_freed->offset;
 		sisfb_free_node(poh_freed);
-		return (poh_next);
+		return(poh_next);
 	}
 
 	sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
 
-	return (poh_freed);
+	return(poh_freed);
 }
 
-static void sisfb_free_node(SIS_OH *poh)
+static void
+sisfb_free_node(SIS_OH *poh)
 {
 	if(poh == NULL) return;
 
 	poh->poh_next = sisfb_heap.poh_freelist;
 	sisfb_heap.poh_freelist = poh;
-
 }
 
-void sis_malloc(struct sis_memreq *req)
+void
+sis_malloc(struct sis_memreq *req)
 {
 	SIS_OH *poh;
 
@@ -3658,7 +3556,8 @@ void sis_malloc(struct sis_memreq *req)
 	}
 }
 
-void sis_free(unsigned long base)
+void
+sis_free(unsigned long base)
 {
 	SIS_OH *poh;
 
@@ -3672,7 +3571,8 @@ void sis_free(unsigned long base)
 
 /* --------------------- SetMode routines ------------------------- */
 
-static void sisfb_pre_setmode(void)
+static void
+sisfb_pre_setmode(void)
 {
 	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0;
 	
@@ -3682,7 +3582,7 @@ static void sisfb_pre_setmode(void)
 	cr31 &= ~0x60;
 	cr31 |= 0x04;
 	
-	cr33 = sisfb_rate_idx & 0x0F;
+	cr33 = ivideo.rate_idx & 0x0F;
 
 	SiS_SetEnableDstn(&SiS_Pr, FALSE);
 	SiS_SetEnableFstn(&SiS_Pr, FALSE);
@@ -3733,7 +3633,7 @@ static void sisfb_pre_setmode(void)
 		if(sisfb_nocrt2rate) {
 			cr33 |= (sisbios_mode[sisfb_mode_idx].rate_idx << 4);
 		} else {
-			cr33 |= ((sisfb_rate_idx & 0x0F) << 4);
+			cr33 |= ((ivideo.rate_idx & 0x0F) << 4);
 		}
 		break;
 	   default:	/* disable CRT2 */
@@ -3751,7 +3651,7 @@ static void sisfb_pre_setmode(void)
 	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, cr33);
 
 #ifdef CONFIG_FB_SIS_315
-        if(sisvga_engine == SIS_315_VGA) {
+        if(ivideo.sisvga_engine == SIS_315_VGA) {
 	   /* Clear LCDA and PAL-N/M bits */
 	   andSISIDXREG(SISCR,0x38,~0x03);
 	   if(ivideo.chip < SIS_661) {
@@ -3765,29 +3665,39 @@ static void sisfb_pre_setmode(void)
 	SiS_Pr.SiS_UseOEM = sisfb_useoem;
 }
 
-static void sisfb_post_setmode(void)
+static void
+sisfb_post_setmode(void)
 {
 	u8 reg;
 	BOOLEAN crt1isoff = FALSE;
+	BOOLEAN doit = TRUE;
 #ifdef CONFIG_FB_SIS_315
 	u8 reg1;
 #endif
-#ifdef CONFIG_FB_SIS_300
-	BOOLEAN doit = TRUE;
-#endif
+
+	/* Now we actually HAVE changed the display mode */
+        ivideo.modechanged = 1;
+
 	/* We can't switch off CRT1 if bridge is in slave mode */
 	if(ivideo.vbflags & VB_VIDEOBRIDGE) {
+		inSISIDXREG(SISPART1, 0x00, reg);
 #ifdef CONFIG_FB_SIS_300
-		if(sisvga_engine == SIS_300_VGA) {
-			inSISIDXREG(SISPART1, 0x00, reg);
+		if(ivideo.sisvga_engine == SIS_300_VGA) {
 			if((reg & 0xa0) == 0x20) {
 				doit = FALSE;
 			}
 		}
 #endif
+#ifdef CONFIG_FB_SIS_315
+		if(ivideo.sisvga_engine == SIS_315_VGA) {
+			if((reg & 0x50) == 0x10) {
+				doit = FALSE;
+			}
+		}
+#endif
 	} else sisfb_crt1off = 0;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 
 #ifdef CONFIG_FB_SIS_300
 	   if((sisfb_crt1off) && (doit)) {
@@ -3803,7 +3713,7 @@ static void sisfb_post_setmode(void)
 	} else {
 
 #ifdef CONFIG_FB_SIS_315
-	   if(sisfb_crt1off) {
+	   if((sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg  = 0x40;
 		reg1 = 0xc0;
@@ -3813,7 +3723,7 @@ static void sisfb_post_setmode(void)
 		reg1 = 0x00;
 
 	   }
-	   setSISIDXREG(SISCR, 0x63, ~0x40, reg);
+	   setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, ~0x40, reg);
 	   setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
 #endif
 
@@ -3858,7 +3768,7 @@ static void sisfb_post_setmode(void)
 			break;
 		}
 
-		orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
 
 		if(ivideo.vbflags & TV_NTSC) {
 
@@ -3931,13 +3841,7 @@ static void sisfb_post_setmode(void)
 			}
 		}
 
-		if ((filter >= 0) && (filter <= 7)) {
-			DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
-				sis_TV_filter[filter_tb].filter[filter][0],
-				sis_TV_filter[filter_tb].filter[filter][1],
-				sis_TV_filter[filter_tb].filter[filter][2],
-				sis_TV_filter[filter_tb].filter[filter][3]
-			);
+		if((filter >= 0) && (filter <= 7)) {
 			outSISIDXREG(SISPART2, 0x35, (sis_TV_filter[filter_tb].filter[filter][0]));
 			outSISIDXREG(SISPART2, 0x36, (sis_TV_filter[filter_tb].filter[filter][1]));
 			outSISIDXREG(SISPART2, 0x37, (sis_TV_filter[filter_tb].filter[filter][2]));
@@ -3945,11 +3849,10 @@ static void sisfb_post_setmode(void)
 		}
 	  
 	}
-
 }
 
 #ifndef MODULE
-int sisfb_setup(char *options)
+int __init sisfb_setup(char *options)
 {
 	char *this_opt;
 	
@@ -3960,76 +3863,85 @@ int sisfb_setup(char *options)
 	ivideo.refresh_rate = 0;
 	SiS_Pr.SiS_CustomT = CUT_NONE;
 	SiS_Pr.UsePanelScaler = -1;
+	SiS_Pr.CenterScreen = -1;
 	SiS_Pr.LVDSHL = -1;
+#if !defined(__i386__) && !defined(__x86_64__)
+       	sisfb_resetcard = 0;
+	sisfb_videoram = 0;
+#endif
 
         printk(KERN_DEBUG "sisfb: Options %s\n", options);
 
-	if (!options || !*options)
+	if(!options || !(*options))
 		return 0;
 
 	while((this_opt = strsep(&options, ",")) != NULL) {
 
-		if (!*this_opt)	continue;
+		if(!(*this_opt)) continue;
 
-		if (!strnicmp(this_opt, "mode:", 5)) {
+		if(!strnicmp(this_opt, "mode:", 5)) {
 			sisfb_search_mode(this_opt + 5, FALSE);
-		} else if (!strnicmp(this_opt, "vesa:", 5)) {
+		} else if(!strnicmp(this_opt, "vesa:", 5)) {
 			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		} else if (!strnicmp(this_opt, "inverse", 7)) {
+		} else if(!strnicmp(this_opt, "inverse", 7)) {
 			sisfb_inverse = 1;
 			/* fb_invert_cmaps(); */
-		} else if (!strnicmp(this_opt, "font:", 5)) {
-			strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
-			sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
+		} else if(!strnicmp(this_opt, "font:", 5)) {
+		        if(strlen(this_opt + 5) < 40) {
+			   strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
+			   sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
+			}
 #endif
-		} else if (!strnicmp(this_opt, "vrate:", 6)) {
+		} else if(!strnicmp(this_opt, "vrate:", 6)) {
 			ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
 			sisfb_parm_rate = ivideo.refresh_rate;
-		} else if (!strnicmp(this_opt, "rate:", 5)) {
+		} else if(!strnicmp(this_opt, "rate:", 5)) {
 			ivideo.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
 			sisfb_parm_rate = ivideo.refresh_rate;
-		} else if (!strnicmp(this_opt, "off", 3)) {
+		} else if(!strnicmp(this_opt, "off", 3)) {
 			sisfb_off = 1;
-		} else if (!strnicmp(this_opt, "crt1off", 7)) {
+		} else if(!strnicmp(this_opt, "crt1off", 7)) {
 			sisfb_crt1off = 1;
-		} else if (!strnicmp(this_opt, "filter:", 7)) {
+		} else if(!strnicmp(this_opt, "filter:", 7)) {
 			filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "forcecrt2type:", 14)) {
+		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
 			sisfb_search_crt2type(this_opt + 14);
-		} else if (!strnicmp(this_opt, "forcecrt1:", 10)) {
+		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
 			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-                } else if (!strnicmp(this_opt, "tvmode:",7)) {
+                } else if(!strnicmp(this_opt, "tvmode:",7)) {
 		        sisfb_search_tvstd(this_opt + 7);
-                } else if (!strnicmp(this_opt, "tvstandard:",11)) {
+                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
 			sisfb_search_tvstd(this_opt + 7);
-                } else if (!strnicmp(this_opt, "mem:",4)) {
+                } else if(!strnicmp(this_opt, "mem:",4)) {
 		        sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if (!strnicmp(this_opt, "queuemode:", 10)) {
+		} else if(!strnicmp(this_opt, "queuemode:", 10)) {
 			sisfb_search_queuemode(this_opt + 10);
-		} else if (!strnicmp(this_opt, "pdc:", 4)) {
+		} else if(!strnicmp(this_opt, "pdc:", 4)) {
 		        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if (!strnicmp(this_opt, "noaccel", 7)) {
+		} else if(!strnicmp(this_opt, "pdc1:", 5)) {
+		        sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
+		} else if(!strnicmp(this_opt, "noaccel", 7)) {
 			sisfb_accel = 0;
-		} else if (!strnicmp(this_opt, "noypan", 6)) {
+		} else if(!strnicmp(this_opt, "noypan", 6)) {
 		        sisfb_ypan = 0;
-		} else if (!strnicmp(this_opt, "nomax", 5)) {
+		} else if(!strnicmp(this_opt, "nomax", 5)) {
 		        sisfb_max = 0;
-		} else if (!strnicmp(this_opt, "userom:", 7)) {
+		} else if(!strnicmp(this_opt, "userom:", 7)) {
 			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "useoem:", 7)) {
+		} else if(!strnicmp(this_opt, "useoem:", 7)) {
 			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "nocrt2rate", 10)) {
+		} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
 			sisfb_nocrt2rate = 1;
-	 	} else if (!strnicmp(this_opt, "scalelcd:", 9)) {
+	 	} else if(!strnicmp(this_opt, "scalelcd:", 9)) {
 		        unsigned long temp = 2;
 		        temp = simple_strtoul(this_opt + 9, NULL, 0);
 		        if((temp == 0) || (temp == 1)) {
 			   SiS_Pr.UsePanelScaler = temp ^ 1;
 		        }
-		} else if (!strnicmp(this_opt, "specialtiming:", 14)) {
+		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
 			sisfb_search_specialtiming(this_opt + 14);
-		} else if (!strnicmp(this_opt, "lvdshl:", 7)) {
+		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
 		        unsigned long temp = 4;
 		        temp = simple_strtoul(this_opt + 7, NULL, 0);
 		        if((temp >= 0) && (temp <= 3)) {
@@ -4037,11 +3949,17 @@ int sisfb_setup(char *options)
 		        }
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
 			sisfb_search_mode(this_opt, TRUE);
+#if !defined(__i386__) && !defined(__x86_64__)
+	        } else if(!strnicmp(this_opt, "resetcard", 9)) {
+		  	sisfb_resetcard = 1;
+	        } else if(!strnicmp(this_opt, "videoram:", 9)) {
+		  	sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+#endif
 		} else {
 			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
 		}
 
-		/* TW: Acceleration only with MMIO mode */
+		/* Acceleration only with MMIO mode */
 		if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
 			sisfb_accel = 0;
 		}
@@ -4051,177 +3969,448 @@ int sisfb_setup(char *options)
 }
 #endif
 
-static char *sis_find_rom(void)
+static char * __devinit sis_find_rom(struct pci_dev *pdev)
 {
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
-        unsigned char *rom_base;
-        unsigned char *rom;
-        int  stage;
-        int  i;
-        char sis_rom_sig[] = "Silicon Integrated Systems";
-        char *sis_sig_300[4] = {
-          "300", "540", "630", "730"
-        };
-        char *sis_sig_310[11] = {
-          "315", "315", "315", "5315", "6325", "6325",
-	  "Xabre", "6330", "6330", "6330", "6330"
-        };
-	ushort sis_nums_300[4] = {
-	  SIS_300, SIS_540, SIS_630, SIS_730
-	};
-	unsigned short sis_nums_310[11] = {
-	  SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, SIS_740,
-	  SIS_330, SIS_661, SIS_741, SIS_660, SIS_760
-	};
+        unsigned char *rom_base, *rom;
+        int  romptr;
+	unsigned short pciid;
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-                stage = 1;
+                rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+		if(!rom_base) continue;
 
-                rom_base = (char *)ioremap(segstart, 0x1000);
+		if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
+		   iounmap(rom_base);
+                   continue;
+		}
 
-                if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
-                   stage = 2;
+		romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+		if(romptr > (0x10000 - 8)) {
+		   iounmap(rom_base);
+		   continue;
+		}
 
-                if (stage != 2) {
-                   iounmap(rom_base);
-                   continue;
-                }
+		rom = rom_base + romptr;
 
+		if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+		   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
+		   iounmap(rom_base);
+		   continue;
+		}
 
-		rom = rom_base + (unsigned short)(*(rom_base + 0x12) | (*(rom_base + 0x13) << 8));
-                if(strncmp(sis_rom_sig, rom, strlen(sis_rom_sig)) == 0) {
-                    stage = 3;
-		}
-                if(stage != 3) {
-                    iounmap(rom_base);
-                    continue;
-                }
-
-		rom = rom_base + (unsigned short)(*(rom_base + 0x14) | (*(rom_base + 0x15) << 8));
-                for(i = 0;(i < 4) && (stage != 4); i++) {
-                    if(strncmp(sis_sig_300[i], rom, strlen(sis_sig_300[i])) == 0) {
-                        if(sis_nums_300[i] == ivideo.chip) {
-			   stage = 4;
-                           break;
-			}
-                    }
-                }
-		if(stage != 4) {
-                   for(i = 0;(i < 11) && (stage != 4); i++) {
-                      if(strncmp(sis_sig_310[i], rom, strlen(sis_sig_310[i])) == 0) {
-		          if(sis_nums_310[i] == ivideo.chip) {
-                             stage = 4;
-                             break;
-			  }
-                      }
-                   }
+		pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+		if(pciid != 0x1039) {
+		   iounmap(rom_base);
+		   continue;
 		}
 
-                if(stage != 4) {
-                        iounmap(rom_base);
-                        continue;
-                }
+		pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+		if(pciid == ivideo.chip_id) return rom_base;
 
-                return rom_base;
+		iounmap(rom_base);
         }
+#else
+	unsigned char *rom_base, *rom, *myrombase = NULL;
+        int  romptr;
+	unsigned short pciid;
+	u32 backup;
+
+	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &backup);
+	pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+			(ivideo.video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+
+	rom_base = ioremap(ivideo.video_base, 65536);
+	if(rom_base) {
+	   if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
+	      romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	      if(romptr <= (0x10000 - 8)) {
+	         rom = rom_base + romptr;
+		 if((readb(rom)     == 'P') && (readb(rom + 1) == 'C') &&
+		    (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
+		    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+		    if(pciid == 0x1039) {
+		       pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+		       if(pciid == ivideo.chip_id) {
+		          if((myrombase = vmalloc(65536))) {
+			     memcpy_fromio(myrombase, rom_base, 65536);
+			  }
+		       }
+		    }
+		 }
+	      }
+	   }
+	   iounmap(rom_base);
+	}
+        pci_write_config_dword(pdev, PCI_ROM_ADDRESS, backup);
+	if(myrombase) return myrombase;
 #endif
         return NULL;
 }
 
+#ifdef SIS300
+static int __devinit
+sisfb_chkbuswidth300(ULONG FBAddress)
+{
+	int i, j;
+	USHORT temp;
+	UCHAR reg;
+
+	andSISIDXREG(SISSR,0x15,0xFB);
+	orSISIDXREG(SISSR,0x15,0x04);
+   	outSISIDXREG(SISSR,0x13,0x00);
+   	outSISIDXREG(SISSR,0x14,0xBF);
+
+	for(i=0; i<2; i++) {
+	   temp = 0x1234;
+	   for(j=0; j<4; j++) {
+	      writew(temp, FBAddress);
+	      if(readw(FBAddress) == temp) break;
+	      orSISIDXREG(SISSR,0x3c,0x01);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      andSISIDXREG(SISSR,0x3c,0xfe);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      temp++;
+	   }
+	}
 
+	writel(0x01234567L, FBAddress);
+	writel(0x456789ABL, (FBAddress+4));
+	writel(0x89ABCDEFL, (FBAddress+8));
+	writel(0xCDEF0123L, (FBAddress+12));
+	inSISIDXREG(SISSR,0x3b,reg);
+	if(reg & 0x01) {
+	   if(readl((FBAddress+12)) == 0xCDEF0123L) return(4);  /* Channel A 128bit */
+	}
+	if(readl((FBAddress+4)) == 0x456789ABL)     return(2);  /* Channel B 64bit */
+	return(1);						/* 32bit */
+}
+
+static void __devinit
+sisfb_setramsize300(void)
+{
+  	ULONG 	FBAddr = (ULONG)sishw_ext.pjVideoMemoryAddress, Addr;
+	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
+	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
+   	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
+   	int     PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
+	const 	USHORT SiS_DRAMType[17][5] = {
+			{0x0C,0x0A,0x02,0x40,0x39},
+			{0x0D,0x0A,0x01,0x40,0x48},
+			{0x0C,0x09,0x02,0x20,0x35},
+			{0x0D,0x09,0x01,0x20,0x44},
+			{0x0C,0x08,0x02,0x10,0x31},
+			{0x0D,0x08,0x01,0x10,0x40},
+			{0x0C,0x0A,0x01,0x20,0x34},
+			{0x0C,0x09,0x01,0x08,0x32},
+			{0x0B,0x08,0x02,0x08,0x21},
+			{0x0C,0x08,0x01,0x08,0x30},
+			{0x0A,0x08,0x02,0x04,0x11},
+			{0x0B,0x0A,0x01,0x10,0x28},
+			{0x09,0x08,0x02,0x02,0x01},
+			{0x0B,0x09,0x01,0x08,0x24},
+			{0x0B,0x08,0x01,0x04,0x20},
+			{0x0A,0x08,0x01,0x02,0x10},
+			{0x09,0x08,0x01,0x01,0x00}
+		};
+
+        buswidth = sisfb_chkbuswidth300(FBAddr);
+
+   	MB2Bank = 16;
+   	Done = 0;
+   	for(i = 6; i >= 0; i--) {
+      	   if(Done) break;
+      	   PseudoRankCapacity = 1 << i;
+      	   for(j = 4; j >= 1; j--) {
+              if(Done) break;
+              PseudoTotalCapacity = PseudoRankCapacity * j;
+              PseudoAdrPinCount = 15 - j;
+              if(PseudoTotalCapacity <= 64) {
+                 for(k = 0; k <= 16; k++) {
+                    if(Done) break;
+                    RankCapacity = buswidth * SiS_DRAMType[k][3];
+                    AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
+                    if(RankCapacity == PseudoRankCapacity)
+                       if(AdrPinCount <= PseudoAdrPinCount) {
+                          if(j == 3) {             /* Rank No */
+                             BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
+                             BankNumMid  = RankCapacity * MB2Bank * 1 - 1;
+                          } else {
+                             BankNumHigh = RankCapacity * MB2Bank * j - 1;
+                             BankNumMid  = RankCapacity * MB2Bank * j / 2 - 1;
+                          }
+                          PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+                          PhysicalAdrHigh = BankNumHigh;
+                          PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+                          PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+                          /* Write data */
+                          andSISIDXREG(SISSR,0x15,0xFB); /* Test */
+                          orSISIDXREG(SISSR,0x15,0x04);  /* Test */
+                          TotalCapacity = SiS_DRAMType[k][3] * buswidth;
+                          SR13 = SiS_DRAMType[k][4];
+                          if(buswidth == 4) SR14 = (TotalCapacity - 1) | 0x80;
+                          if(buswidth == 2) SR14 = (TotalCapacity - 1) | 0x40;
+                          if(buswidth == 1) SR14 = (TotalCapacity - 1) | 0x00;
+                          outSISIDXREG(SISSR,0x13,SR13);
+                          outSISIDXREG(SISSR,0x14,SR14);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
+                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
+			  writew(((USHORT)PhysicalAdrHigh), Addr);
+                          Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
+                          /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
+			  writew(((USHORT)BankNumMid), Addr);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
+                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
+			  writew(((USHORT)PhysicalAdrHalfPage), Addr);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
+                          /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
+			  writew(((USHORT)PhysicalAdrOtherPage), Addr);
+                          /* Read data */
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
+                          data = readw(Addr); /* *((USHORT *)(Addr)); */
+                          if(data == PhysicalAdrHigh) Done = 1;
+                       }  /* if */
+                 }  /* for k */
+              }  /* if */
+      	   }  /* for j */
+   	}  /* for i */
+}
+
+static void __devinit sisfb_post_sis300(void)
+{
+	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
+	u16 index, rindex, memtype = 0;
+
+	outSISIDXREG(SISSR,0x05,SIS_PASSWORD);
+
+	if(sishw_ext.UseROM) {
+	   if(sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
+	      memtype = sishw_ext.pjVirtualRomBase[0x52];
+ 	   } else {
+	      inSISIDXREG(SISSR,0x3a,memtype);
+	   }
+	   memtype &= 0x07;
+	}
 
-int __init sisfb_init(void)
+	if(ivideo.revision_id <= 0x13) {
+	   v1 = 0x44; v2 = 0x42; v3 = 0x80;
+	   v4 = 0x44; v5 = 0x42; v6 = 0x80;
+	} else {
+	   v1 = 0x68; v2 = 0x43; v3 = 0x80;  /* Assume 125Mhz MCLK */
+	   v4 = 0x68; v5 = 0x43; v6 = 0x80;  /* Assume 125Mhz ECLK */
+	   if(sishw_ext.UseROM) {
+	      index = memtype * 5;
+	      rindex = index + 0x54;
+	      v1 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v2 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v3 = sishw_ext.pjVirtualRomBase[rindex++];
+	      rindex = index + 0x7c;
+	      v4 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v5 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v6 = sishw_ext.pjVirtualRomBase[rindex++];
+	   }
+	}
+	outSISIDXREG(SISSR,0x28,v1);
+	outSISIDXREG(SISSR,0x29,v2);
+	outSISIDXREG(SISSR,0x2a,v3);
+	outSISIDXREG(SISSR,0x2e,v4);
+	outSISIDXREG(SISSR,0x2f,v5);
+	outSISIDXREG(SISSR,0x30,v6);
+	v1 = 0x10;
+	if(sishw_ext.UseROM) v1 = sishw_ext.pjVirtualRomBase[0xa4];
+	outSISIDXREG(SISSR,0x07,v1);       /* DAC speed */
+	outSISIDXREG(SISSR,0x11,0x0f);     /* DDC, power save */
+	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
+	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
+	if(sishw_ext.UseROM) {
+	   memtype += 0xa5;
+	   v1 = sishw_ext.pjVirtualRomBase[memtype];
+	   v2 = sishw_ext.pjVirtualRomBase[memtype + 8];
+	   v3 = sishw_ext.pjVirtualRomBase[memtype + 16];
+	   v4 = sishw_ext.pjVirtualRomBase[memtype + 24];
+	   v5 = sishw_ext.pjVirtualRomBase[memtype + 32];
+	   v6 = sishw_ext.pjVirtualRomBase[memtype + 40];
+	   v7 = sishw_ext.pjVirtualRomBase[memtype + 48];
+	   v8 = sishw_ext.pjVirtualRomBase[memtype + 56];
+	}
+	if(ivideo.revision_id >= 0x80) v3 &= 0xfd;
+	outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+	outSISIDXREG(SISSR,0x16,v2);
+	outSISIDXREG(SISSR,0x17,v3);
+	outSISIDXREG(SISSR,0x18,v4);
+	outSISIDXREG(SISSR,0x19,v5);
+	outSISIDXREG(SISSR,0x1a,v6);
+	outSISIDXREG(SISSR,0x1b,v7);
+	outSISIDXREG(SISSR,0x1c,v8);	   /* ---- */
+	andSISIDXREG(SISSR,0x15,0xfb);
+	orSISIDXREG(SISSR,0x15,0x04);
+	if(sishw_ext.UseROM) {
+	   if(sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
+	      orSISIDXREG(SISSR,0x19,0x20);
+	   }
+	}
+	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
+	if(ivideo.revision_id >= 0x80) v1 |= 0x01;
+	outSISIDXREG(SISSR,0x1f,v1);
+	outSISIDXREG(SISSR,0x20,0xa0);     /* linear & relocated io */
+	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
+	if(sishw_ext.UseROM) {
+	   v1 = sishw_ext.pjVirtualRomBase[0xe8];
+	   v2 = sishw_ext.pjVirtualRomBase[0xe9];
+	   v3 = sishw_ext.pjVirtualRomBase[0xea];
+	}
+	outSISIDXREG(SISSR,0x23,v1);
+	outSISIDXREG(SISSR,0x24,v2);
+	outSISIDXREG(SISSR,0x25,v3);
+	outSISIDXREG(SISSR,0x21,0x84);
+	outSISIDXREG(SISSR,0x22,0x00);
+	outSISIDXREG(SISCR,0x37,0x00);
+	orSISIDXREG(SISPART1,0x24,0x01);   /* unlock crt2 */
+	outSISIDXREG(SISPART1,0x00,0x00);
+	v1 = 0x40; v2 = 0x11;
+	if(sishw_ext.UseROM) {
+	   v1 = sishw_ext.pjVirtualRomBase[0xec];
+	   v2 = sishw_ext.pjVirtualRomBase[0xeb];
+	}
+	outSISIDXREG(SISPART1,0x02,v1);
+	if(ivideo.revision_id >= 0x80) v2 &= ~0x01;
+	inSISIDXREG(SISPART4,0x00,reg);
+	if((reg == 1) || (reg == 2)) {
+	   outSISIDXREG(SISCR,0x37,0x02);
+	   outSISIDXREG(SISPART2,0x00,0x1c);
+	   v4 = 0x00; v5 = 0x00; v6 = 0x10;
+	   if(sishw_ext.UseROM) {
+	      v4 = sishw_ext.pjVirtualRomBase[0xf5];
+	      v5 = sishw_ext.pjVirtualRomBase[0xf6];
+	      v6 = sishw_ext.pjVirtualRomBase[0xf7];
+	   }
+	   outSISIDXREG(SISPART4,0x0d,v4);
+	   outSISIDXREG(SISPART4,0x0e,v5);
+	   outSISIDXREG(SISPART4,0x10,v6);
+	   outSISIDXREG(SISPART4,0x0f,0x3f);
+	   inSISIDXREG(SISPART4,0x01,reg);
+	   if(reg >= 0xb0) {
+	      inSISIDXREG(SISPART4,0x23,reg);
+	      reg &= 0x20;
+	      reg <<= 1;
+	      outSISIDXREG(SISPART4,0x23,reg);
+	   }
+	} else {
+	   v2 &= ~0x10;
+	}
+	outSISIDXREG(SISSR,0x32,v2);
+	andSISIDXREG(SISPART1,0x24,0xfe);  /* Lock CRT2 */
+	inSISIDXREG(SISSR,0x16,reg);
+	reg &= 0xc3;
+	outSISIDXREG(SISCR,0x35,reg);
+	outSISIDXREG(SISCR,0x83,0x00);
+#if !defined(__i386__) && !defined(__x86_64__)
+	if(sisfb_videoram) {
+	   outSISIDXREG(SISSR,0x13,0x28);  /* ? */
+	   reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+	   outSISIDXREG(SISSR,0x14,reg);
+	} else {
+#endif
+	   /* Need to map max FB size for finding out about RAM size */
+	   sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x4000000);
+	   if(sishw_ext.pjVideoMemoryAddress) {
+	      sisfb_setramsize300();
+	      iounmap(sishw_ext.pjVideoMemoryAddress);
+	   } else {
+	      printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+	      outSISIDXREG(SISSR,0x13,0x28);  /* ? */
+	      outSISIDXREG(SISSR,0x14,0x47);  /* 8MB, 64bit default */
+	   }
+#if !defined(__i386__) && !defined(__x86_64__)
+	}
+#endif
+	if(sishw_ext.UseROM) {
+	   v1 = sishw_ext.pjVirtualRomBase[0xe6];
+	   v2 = sishw_ext.pjVirtualRomBase[0xe7];
+	} else {
+	   inSISIDXREG(SISSR,0x3a,reg);
+	   if((reg & 0x30) == 0x30) {
+	      v1 = 0x04; /* PCI */
+	      v2 = 0x92;
+	   } else {
+	      v1 = 0x14; /* AGP */
+	      v2 = 0xb2;
+	   }
+	}
+	outSISIDXREG(SISSR,0x21,v1);
+	outSISIDXREG(SISSR,0x22,v2);
+}
+#endif
+
+
+int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	struct pci_dev *pdev = NULL;
-	struct board *b;
-	int pdev_valid = 0;
+	struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
 	u32 reg32;
 	u16 reg16;
 	u8  reg;
+	int sisvga_enabled = 0;
 
-#if 0
-	/* for DOC VB */
-	sisfb_set_reg4(0xcf8,0x800000e0);
-	reg32 = sisfb_get_reg3(0xcfc);
-	reg32 = reg32 | 0x00001000;
-	sisfb_set_reg4(0xcfc,reg32);
-	}
-#endif
-
-	if (sisfb_off)
-		return -ENXIO;
+	if(sisfb_off) return -ENXIO;
 
-	sisfb_registered = 0;
 	sisfb_thismonitor.datavalid = FALSE;
 
 	memset(&sishw_ext, 0, sizeof(sishw_ext));
+	
+	memset(&ivideo, 0, sizeof(ivideo));
+	ivideo.detectedpdc  = 0xff;
+	ivideo.detectedpdca = 0xff;
+	ivideo.detectedlcda = 0xff;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
         memset(&sisfb_lastrates[0], 0, 128);
 #endif
-	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	memset(&sis_disp, 0, sizeof(sis_disp));
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-	pci_for_each_dev(pdev) {
-#else
-	while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-		for (b = sisdev_list; b->vendor; b++) {
-			if ((b->vendor == pdev->vendor)
-			    && (b->device == pdev->device)) {
-				pdev_valid = 1;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-				sis_fb_info = framebuffer_alloc(0, &pdev->dev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+	sis_fb_info = framebuffer_alloc(0, &pdev->dev);
 #else
-				sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
+	sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
 #endif
-				if(!sis_fb_info) return -ENOMEM;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-				memset(sis_fb_info, 0, sizeof(*sis_fb_info));
+	if(!sis_fb_info) return -ENOMEM;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3))
+	memset(sis_fb_info, 0, sizeof(*sis_fb_info));
 #endif
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, b->name);
-#else				
-				strcpy(myid, b->name);
-#endif				
-				ivideo.chip_id = pdev->device;
-				pci_read_config_byte(pdev, PCI_REVISION_ID,
-				                     &ivideo.revision_id);
-				pci_read_config_word(pdev, PCI_COMMAND, &reg16);
-				sishw_ext.jChipRevision = ivideo.revision_id;
-				sisvga_enabled = reg16 & 0x01;
-				ivideo.pcibus = pdev->bus->number;
-				ivideo.pcislot = PCI_SLOT(pdev->devfn);
-				ivideo.pcifunc = PCI_FUNC(pdev->devfn);
-				ivideo.subsysvendor = pdev->subsystem_vendor;
-				ivideo.subsysdevice = pdev->subsystem_device;
-				break;
-			}
-		}
 
-		if (pdev_valid)
-			break;
-	}
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+	strcpy(sis_fb_info->modename, chipinfo->chip_name);
+#else
+	strcpy(myid, chipinfo->chip_name);
+#endif
 
-	if (!pdev_valid)
-		return -ENODEV;
+	ivideo.chip_id = pdev->device;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo.revision_id);
+	sishw_ext.jChipRevision = ivideo.revision_id;
+	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
+	sisvga_enabled = reg16 & 0x01;
+	ivideo.pcibus = pdev->bus->number;
+	ivideo.pcislot = PCI_SLOT(pdev->devfn);
+	ivideo.pcifunc = PCI_FUNC(pdev->devfn);
+	ivideo.subsysvendor = pdev->subsystem_vendor;
+	ivideo.subsysdevice = pdev->subsystem_device;
+
+	ivideo.chip = chipinfo->chip;
+	ivideo.sisvga_engine = chipinfo->vgaengine;
+	ivideo.hwcursor_size = chipinfo->hwcursor_size;
+	ivideo.CRT2_write_enable = chipinfo->CRT2_write_enable;
 
-	switch (ivideo.chip_id) {
+	/* Patch special cases */
+	switch(ivideo.chip_id) {
 #ifdef CONFIG_FB_SIS_300
-	   case PCI_DEVICE_ID_SI_300:
-		ivideo.chip = SIS_300;
-		sisvga_engine = SIS_300_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;  /* New X driver uses 2 buffers */
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-		break;
 	   case PCI_DEVICE_ID_SI_630_VGA:
 		{
-			ivideo.chip = SIS_630;
 			sisfb_set_reg4(0xCF8, 0x80000000);
 			reg32 = sisfb_get_reg3(0xCFC);
 			if(reg32 == 0x07301039) {
@@ -4232,46 +4421,12 @@ int __init sisfb_init(void)
 				strcpy(myid, "SIS 730");
 #endif
 			}
-			sisvga_engine = SIS_300_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
 			break;
 		}
-	   case PCI_DEVICE_ID_SI_540_VGA:
-		ivideo.chip = SIS_540;
-		sisvga_engine = SIS_300_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-		break;
 #endif
 #ifdef CONFIG_FB_SIS_315
-	   case PCI_DEVICE_ID_SI_315H:
-		ivideo.chip = SIS_315H;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_315:
-		ivideo.chip = SIS_315;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_315PRO:
-		ivideo.chip = SIS_315PRO;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_550_VGA:
-		ivideo.chip = SIS_550;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
 	   case PCI_DEVICE_ID_SI_650_VGA:
 	   	{
-			ivideo.chip = SIS_650;  
 			sisfb_set_reg4(0xCF8, 0x80000000);
 			reg32 = sisfb_get_reg3(0xCFC);
 			if(reg32 == 0x07401039) {
@@ -4282,17 +4437,8 @@ int __init sisfb_init(void)
 				strcpy(myid, "SIS 740");
 #endif
 			}
-			sisvga_engine = SIS_315_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
 			break;
 		}
-	   case PCI_DEVICE_ID_SI_330:
-		ivideo.chip = SIS_330;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
 	   case PCI_DEVICE_ID_SI_660_VGA:
 	   	{
 			sisfb_set_reg4(0xCF8, 0x80000000);
@@ -4326,19 +4472,13 @@ int __init sisfb_init(void)
 				strcpy(myid, "SIS 661");
 #endif
 			}
-			sisvga_engine = SIS_315_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
 			break;
 		}
 #endif
-           default:
-	   	kfree(sis_fb_info);
-	        return -ENODEV;
 	}
+
 	sishw_ext.jChipType = ivideo.chip;
 
-	/* for Debug */
 	if( (sishw_ext.jChipType == SIS_315PRO) ||
 	    (sishw_ext.jChipType == SIS_315) )
 		sishw_ext.jChipType = SIS_315H;
@@ -4346,16 +4486,16 @@ int __init sisfb_init(void)
 	ivideo.video_base = pci_resource_start(pdev, 0);
 	ivideo.mmio_base = pci_resource_start(pdev, 1);
 	sishw_ext.ulIOAddress = SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
-	ivideo.vga_base = (unsigned short) sishw_ext.ulIOAddress;
+	ivideo.vga_base = sishw_ext.ulIOAddress;
 
-	sisfb_mmio_size =  pci_resource_len(pdev, 1);
+	ivideo.mmio_size =  pci_resource_len(pdev, 1);
 
 	if(!sisvga_enabled) {
 	   if(pci_enable_device(pdev)) {
 	      kfree(sis_fb_info);
 	      return -EIO;
 	   }
-	}
+	} 
 
 	SiS_Pr.SiS_Backup70xx = 0xff;
         SiS_Pr.SiS_CHOverScan = -1;
@@ -4364,10 +4504,18 @@ int __init sisfb_init(void)
 	SiS_Pr.HaveEMI = FALSE;
 	SiS_Pr.HaveEMILCD = FALSE;
 	SiS_Pr.OverruleEMI = FALSE;
+	SiS_Pr.SiS_SensibleSR11 = FALSE;
+	SiS_Pr.SiS_MyCR63 = 0x63;
+	SiS_Pr.PDC = -1;
+	SiS_Pr.PDCA = -1;
+	if(ivideo.chip >= SIS_661) {
+	   SiS_Pr.SiS_SensibleSR11 = TRUE;
+	   SiS_Pr.SiS_MyCR63 = 0x53;
+	}
 	SiSRegInit(&SiS_Pr, sishw_ext.ulIOAddress);
 
 #ifdef CONFIG_FB_SIS_300
-	/* TW: Find PCI systems for Chrontel/GPIO communication setup */
+	/* Find PCI systems for Chrontel/GPIO communication setup */
 	if(ivideo.chip == SIS_630) {
 	   int i=0;
            do {
@@ -4385,9 +4533,21 @@ int __init sisfb_init(void)
 
         outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		
-#ifdef MODULE
+	if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		  	      || (sisfb_resetcard)
+#endif
+			      			   ) {
+	   int i;
+	   for(i = 0x30; i <= 0x3f; i++) {
+	       outSISIDXREG(SISCR,i,0x00);
+	   }
+	}
+
 	inSISIDXREG(SISCR,0x34,reg);
+	ivideo.modeprechange = ((reg & 0x7f)) ? (reg & 0x7f) : 0x03;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		
+#ifdef MODULE	
 	if((reg & 0x80) && (reg != 0xff)) {
 	   if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {
 	      printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
@@ -4398,41 +4558,31 @@ int __init sisfb_init(void)
 #endif	
 #endif
 
-	if (sisvga_engine == SIS_315_VGA) {
-		switch (ivideo.chip) {
-		   case SIS_315H:
-		   case SIS_315:
-		   case SIS_330:
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-			break;
-		   case SIS_550:
-		   case SIS_650:
-		   case SIS_740:
-		   case SIS_661:
-		   case SIS_741:
-		   case SIS_660:
-		   case SIS_760:
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-			break;
-		   default:
-			break;
-		}
-	} else if (sisvga_engine == SIS_300_VGA) {
-		if (ivideo.chip == SIS_300) {
+	if(ivideo.sisvga_engine == SIS_315_VGA) {
+	   	sishw_ext.bIntegratedMMEnabled = TRUE;
+	} else if(ivideo.sisvga_engine == SIS_300_VGA) {
+		if(ivideo.chip == SIS_300) {
 			sishw_ext.bIntegratedMMEnabled = TRUE;
 		} else {
 		        inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, reg);
-			if (reg & SIS_SCRATCH_REG_1A_MASK)
+			if(reg & SIS_SCRATCH_REG_1A_MASK)
 				sishw_ext.bIntegratedMMEnabled = TRUE;
 			else
 				sishw_ext.bIntegratedMMEnabled = FALSE;
 		}
 	}
 
+	ivideo.bios_vbase = ivideo.bios_abase = NULL;
 	if(sisfb_userom) {
-	    sishw_ext.pjVirtualRomBase = sis_find_rom();
+	    sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
+#if defined(__i386__) || defined(__x86_64__)
+	    ivideo.bios_vbase = sishw_ext.pjVirtualRomBase;	/* mapped */
+#else
+	    ivideo.bios_abase = sishw_ext.pjVirtualRomBase;	/* allocated */
+#endif
 	    if(sishw_ext.pjVirtualRomBase) {
-		printk(KERN_INFO "sisfb: Video ROM found and mapped to %p\n",
+		printk(KERN_INFO "sisfb: Video ROM found and %s to %p\n",
+			ivideo.bios_vbase ? "mapped" : "copied",
 		        sishw_ext.pjVirtualRomBase);
 		sishw_ext.UseROM = TRUE;
 	    } else {
@@ -4445,8 +4595,6 @@ int __init sisfb_init(void)
 	    printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
 	}
 	sishw_ext.bSkipDramSizing = 0;
-	sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
-	sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
 
         /* Find systems for special custom timing */
 	if(SiS_Pr.SiS_CustomT == CUT_NONE) {
@@ -4502,7 +4650,7 @@ int __init sisfb_init(void)
 
 #ifdef CONFIG_FB_SIS_300
 	/* Mode numbers for 1280x768 are different for 300 and 315 series */
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 		sisbios_mode[MODEINDEX_1280x768].mode_no = 0x55;
 		sisbios_mode[MODEINDEX_1280x768+1].mode_no = 0x5a;
 		sisbios_mode[MODEINDEX_1280x768+2].mode_no = 0x5b;
@@ -4511,36 +4659,38 @@ int __init sisfb_init(void)
 #endif
 
 	sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
-	if (sishw_ext.pSR == NULL) {
+	if(sishw_ext.pSR == NULL) {
 		printk(KERN_ERR "sisfb: Fatal error: Allocating SRReg space failed.\n");
+		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 	sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
 
 	sishw_ext.pCR = vmalloc(sizeof(SIS_DSReg) * CR_BUFFER_SIZE);
-	if (sishw_ext.pCR == NULL) {
-	        vfree(sishw_ext.pSR);
+	if(sishw_ext.pCR == NULL) {
 		printk(KERN_ERR "sisfb: Fatal error: Allocating CRReg space failed.\n");
+		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
+		vfree(sishw_ext.pSR);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 	sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
 
 #ifdef CONFIG_FB_SIS_300
-	if(sisvga_engine == SIS_300_VGA) {
-		if(!sisvga_enabled) {
-		        /* Mapping Max FB Size for 300 Init */
-			sishw_ext.pjVideoMemoryAddress
-				= ioremap(ivideo.video_base, 0x4000000);
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-			}
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
+		if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		    		      || (sisfb_resetcard)
+#endif
+		  					   ) {
+			if(ivideo.chip == SIS_300) sisfb_post_sis300();
 		}
 		if(sisfb_get_dram_size_300()) {
-		        vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
 			printk(KERN_ERR "sisfb: Fatal error: Unable to determine RAM size\n");
+			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
+			vfree(sishw_ext.pSR);
+			vfree(sishw_ext.pCR);
 			kfree(sis_fb_info);
 			return -ENODEV;
 		}
@@ -4548,12 +4698,16 @@ int __init sisfb_init(void)
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-	if (sisvga_engine == SIS_315_VGA) {
-		if (!sisvga_enabled) {
-			/* Mapping Max FB Size for 315 Init */
-			sishw_ext.pjVideoMemoryAddress 
-				= ioremap(ivideo.video_base, 0x8000000);
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
+	if(ivideo.sisvga_engine == SIS_315_VGA) {
+		if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		    		     || (sisfb_resetcard)
+#endif
+		  					  ) {
+			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
+				/* TODO: POSTing 315/330 not supported yet */
+				/* Mapping Max FB Size for 315 Init */
+			      	sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x8000000);
 				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 				sishw_ext.bSkipDramSizing = TRUE;
 				sishw_ext.pSR[0].jIdx = 0x13;
@@ -4562,12 +4716,14 @@ int __init sisfb_init(void)
 				inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
 				inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
 				sishw_ext.pSR[2].jVal = 0xFF;
+				iounmap(sishw_ext.pjVideoMemoryAddress);
 			}
 		}
 		if(sisfb_get_dram_size_315()) {
+			printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
+			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
 			vfree(sishw_ext.pSR);
 			vfree(sishw_ext.pCR);
-			printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
 			kfree(sis_fb_info);
 			return -ENODEV;
 		}
@@ -4575,53 +4731,73 @@ int __init sisfb_init(void)
 #endif
 
 	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
-
 	        /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
 	        orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
-
                 /* Enable 2D accelerator engine */
 	        orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
-
 	}
 
 	sishw_ext.ulVideoMemorySize = ivideo.video_size;
 
-	if(sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
-	if(sisfb_pdc) {
-	    SiS_Pr.PDC = sisfb_pdc;
-	} else {
-	    SiS_Pr.PDC = 0;
+	if(sisfb_pdc != 0xff) {
+	   if(ivideo.sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
+	   else				           sisfb_pdc &= 0x1f;
+	   SiS_Pr.PDC = sisfb_pdc;
+	}
+	if(ivideo.sisvga_engine == SIS_315_VGA) {
+	   if(sisfb_pdca != 0xff) SiS_Pr.PDCA = sisfb_pdca & 0x1f;
 	}
 
-	if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+	if(!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
 		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
+		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
 		vfree(sishw_ext.pSR);
 		vfree(sishw_ext.pCR);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	if (!request_mem_region(ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
+	if(!request_mem_region(ivideo.mmio_base, ivideo.mmio_size, "sisfb MMIO")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
 		release_mem_region(ivideo.video_base, ivideo.video_size);
+		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
 		vfree(sishw_ext.pSR);
 		vfree(sishw_ext.pCR);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = 
-		ioremap(ivideo.video_base, ivideo.video_size);
-	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, sisfb_mmio_size);
+	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, ivideo.video_size);
+	if(!ivideo.video_vbase) {
+	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
+	   	release_mem_region(ivideo.video_base, ivideo.video_size);
+	   	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
+	   	vfree(sishw_ext.pSR);
+	   	vfree(sishw_ext.pCR);
+	   	kfree(sis_fb_info);
+	   	return -ENODEV;
+	}
+
+	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, ivideo.mmio_size);
+	if(!ivideo.mmio_vbase) {
+	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
+	   	iounmap(ivideo.video_vbase);
+	   	release_mem_region(ivideo.video_base, ivideo.video_size);
+	   	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
+	   	vfree(sishw_ext.pSR);
+	   	vfree(sishw_ext.pCR);
+	   	kfree(sis_fb_info);
+	   	return -ENODEV;
+	}
 
 	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-	       ivideo.video_base, ivideo.video_vbase,
-	       ivideo.video_size / 1024);
+	       	ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
 
 	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
-	       ivideo.mmio_base, ivideo.mmio_vbase,
-	       sisfb_mmio_size / 1024);
+	       	ivideo.mmio_base, ivideo.mmio_vbase, ivideo.mmio_size / 1024);
 
 	if(sisfb_heap_init()) {
 		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
@@ -4631,11 +4807,12 @@ int __init sisfb_init(void)
 	
 	ivideo.vbflags = 0;
 
+	ivideo.newrom = SiSDetermineROMLayout661(&SiS_Pr, &sishw_ext);
+
 	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
 	
 		sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
 		sishw_ext.Is301BDH = FALSE;
-		sishw_ext.usExternalChip = 0;
 
 		sisfb_sense_crt1();
 	
@@ -4645,7 +4822,7 @@ int __init sisfb_init(void)
 			sisfb_detect_VB_connect();
 		}
 		
-		ivideo.currentvbflags = ivideo.vbflags & VB_VIDEOBRIDGE;
+		ivideo.currentvbflags = ivideo.vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
 		
 		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
 		   if(sisfb_crt2type != -1) {
@@ -4658,7 +4835,7 @@ int __init sisfb_init(void)
 		      /* Chrontel 700x TV detection often unreliable, therefore use a
 		       * different default order on such machines
 		       */
-		      if((sisvga_engine == SIS_300_VGA) && (ivideo.vbflags & VB_CHRONTEL)) {
+		      if((ivideo.sisvga_engine == SIS_300_VGA) && (ivideo.vbflags & VB_CHRONTEL)) {
 		         if(ivideo.vbflags & CRT2_LCD)      ivideo.currentvbflags |= CRT2_LCD;
 		         else if(ivideo.vbflags & CRT2_TV)  ivideo.currentvbflags |= CRT2_TV;
 		         else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
@@ -4673,67 +4850,99 @@ int __init sisfb_init(void)
 		if(ivideo.vbflags & CRT2_LCD) {
 		   inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
 		   reg &= 0x0f;
-		   if(sisvga_engine == SIS_300_VGA) {
+		   if(ivideo.sisvga_engine == SIS_300_VGA) {
 		      sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+		   } else if(ivideo.chip >= SIS_661) {
+		      sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
 		   } else {
 		      sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
 		   }
 		}
-		
-		sisfb_detectedpdc = 0;
-
+	
 #ifdef CONFIG_FB_SIS_300
                 /* Save the current PanelDelayCompensation if the LCD is currently used */
-		if(sisvga_engine == SIS_300_VGA) {
+		if(ivideo.sisvga_engine == SIS_300_VGA) {
 	           if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
 		       int tmp;
 		       inSISIDXREG(SISCR,0x30,tmp);
 		       if(tmp & 0x20) {
 		          /* Currently on LCD? If yes, read current pdc */
-		          inSISIDXREG(SISPART1,0x13,sisfb_detectedpdc);
-			  sisfb_detectedpdc &= 0x3c;
-			  if(SiS_Pr.PDC == 0) {
+		          inSISIDXREG(SISPART1,0x13,ivideo.detectedpdc);
+			  ivideo.detectedpdc &= 0x3c;
+			  if(SiS_Pr.PDC == -1) {
 			     /* Let option override detection */
-			     SiS_Pr.PDC = sisfb_detectedpdc;
+			     SiS_Pr.PDC = ivideo.detectedpdc;
 			  }
-			  printk(KERN_INFO
-			         "sisfb: Detected LCD PanelDelayCompensation %d\n",
-  			         sisfb_detectedpdc);
+			  printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+  			         ivideo.detectedpdc);
 		       }
-		       if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
-		          printk(KERN_INFO
-			         "sisfb: Using LCD PanelDelayCompensation %d\n",
+		       if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		          printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
 				 SiS_Pr.PDC);
 		       }
 	           }
 		}
 #endif
 
-	        sisfb_detectedlcda = 0xff;
-
 #ifdef CONFIG_FB_SIS_315
+		if(ivideo.sisvga_engine == SIS_315_VGA) {
+
+		   /* Try to find about LCDA */
+		   if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
+		      int tmp;
+		      inSISIDXREG(SISPART1,0x13,tmp);
+		      if(tmp & 0x04) {
+		         SiS_Pr.SiS_UseLCDA = TRUE;
+		         ivideo.detectedlcda = 0x03;
+		         printk(KERN_DEBUG
+			        "sisfb: BIOS uses LCDA for low resolution and text modes\n");
+		      }
+	           }
 
-		if(sisvga_engine == SIS_315_VGA) {
 		   /* Save PDC */
 		   if(ivideo.vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISCR,0x30,tmp);
-		      if(tmp & 0x20) {
+		      if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
 		         /* Currently on LCD? If yes, read current pdc */
-		         inSISIDXREG(SISPART1,0x2D,sisfb_detectedpdc);
-			 if(SiS_Pr.PDC == 0) {
-			    /* Let option override detection */
-			    SiS_Pr.PDC = sisfb_detectedpdc;
+			 u8 pdc;
+		         inSISIDXREG(SISPART1,0x2D,pdc);
+			 ivideo.detectedpdc  = (pdc & 0x0f) << 1;
+			 ivideo.detectedpdca = (pdc & 0xf0) >> 3;
+			 inSISIDXREG(SISPART1,0x35,pdc);
+			 ivideo.detectedpdc |= ((pdc >> 7) & 0x01);
+			 inSISIDXREG(SISPART1,0x20,pdc);
+			 ivideo.detectedpdca |= ((pdc >> 6) & 0x01);
+			 if(ivideo.newrom) {
+			    /* New ROM invalidates other PDC resp. */
+			    if(ivideo.detectedlcda != 0xff) {
+			       ivideo.detectedpdc = 0xff;
+			    } else {
+			       ivideo.detectedpdca = 0xff;
+			    }
+			 }
+			 if(SiS_Pr.PDC == -1) {
+			    if(ivideo.detectedpdc != 0xff) {
+			       SiS_Pr.PDC = ivideo.detectedpdc;
+			    }
+			 }
+			 if(SiS_Pr.PDCA == -1) {
+			    if(ivideo.detectedpdca != 0xff) {
+			       SiS_Pr.PDCA = ivideo.detectedpdca;
+			    }
+			 }
+			 if(ivideo.detectedpdc != 0xff) {
+			    printk(KERN_INFO
+			         "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+  			          ivideo.detectedpdc);
+			 }
+			 if(ivideo.detectedpdca != 0xff) {
+			    printk(KERN_INFO
+			         "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+  			          ivideo.detectedpdca);
 			 }
-			 printk(KERN_INFO
-			        "sisfb: Detected LCD PanelDelayCompensation %d\n",
-  			         sisfb_detectedpdc);
-		      }
-		      if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
-		         printk(KERN_INFO
-			         "sisfb: Using LCD PanelDelayCompensation %d\n",
-				 SiS_Pr.PDC);
 		      }
+
 		      /* Save EMI */
 		      if(ivideo.vbflags & (VB_302LV | VB_302ELV)) {
 		         inSISIDXREG(SISPART4,0x30,SiS_Pr.EMI_30);
@@ -4741,57 +4950,41 @@ int __init sisfb_init(void)
 			 inSISIDXREG(SISPART4,0x32,SiS_Pr.EMI_32);
 			 inSISIDXREG(SISPART4,0x33,SiS_Pr.EMI_33);
 			 SiS_Pr.HaveEMI = TRUE;
-			 if(tmp & 0x20) SiS_Pr.HaveEMILCD = TRUE;
+			 if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
+			  	SiS_Pr.HaveEMILCD = TRUE;
+			 }
 		      }
 		   }
 
-		   /* Try to find about LCDA */
-		   if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
-		      int tmp;
-		      inSISIDXREG(SISCR,0x34,tmp);
-		      if((tmp <= 0x13) || (tmp == 0xff)) {
-		         /* Currently on LCDA? (Some BIOSes leave CR38) */
-		         inSISIDXREG(SISCR,0x38,tmp);
-			 if((tmp & 0x03) == 0x03)  SiS_Pr.SiS_UseLCDA = TRUE;
-			 else {
-			    /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
-			    inSISIDXREG(SISCR,0x35,tmp);
-			    if(tmp & 0x01) SiS_Pr.SiS_UseLCDA = TRUE;
-			    else {
-			       /* Currently on LCD? If so, we can find out
-			        * by peeking the mode register
-				*/
-			       inSISIDXREG(SISCR,0x30,tmp);
-			       if(tmp & 0x20) {
-			          inSISIDXREG(SISPART1,0x13,tmp);
-				  if(tmp & 0x04) SiS_Pr.SiS_UseLCDA = TRUE;
-			       }
-			    }
-			 }
+		   /* Let user override detected PDCs (all bridges) */
+		   if(ivideo.vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
+		      if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		         printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+				 SiS_Pr.PDC);
 		      }
-		      if(SiS_Pr.SiS_UseLCDA) {
-		         sisfb_detectedlcda = 0x03;
-		         printk(KERN_DEBUG
-			        "sisfb: Bridge uses LCDA for low resolution and text modes\n");
+		      if((SiS_Pr.PDCA != -1) && (SiS_Pr.PDCA != ivideo.detectedpdca)) {
+		         printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+				 SiS_Pr.PDCA);
 		      }
-	          }
+		   }
+
 		}
 #endif
 
-		if (!sisfb_crt1off) {
+		if(!sisfb_crt1off) {
 		   	sisfb_handle_ddc(&sisfb_thismonitor, 0);
 		} else {
-		   	if ((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
-		      	    (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
+		   	if((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
+		      	   (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
 		      		sisfb_handle_ddc(&sisfb_thismonitor, 1);
 		   	}
 		}
 
-		if (sisfb_mode_idx >= 0)
+		if(sisfb_mode_idx >= 0)
 			sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
 
-		if (sisfb_mode_idx < 0) {
-			switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(sisfb_mode_idx < 0) {
+			switch(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
 			   case CRT2_LCD:
 				sisfb_mode_idx = DEFAULT_LCDMODE;
 				break;
@@ -4804,19 +4997,19 @@ int __init sisfb_init(void)
 			}
 		}
 
-		sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+		ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
 
-		if (ivideo.refresh_rate != 0)
+		if(ivideo.refresh_rate != 0)
 			sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx);
 
-		if (sisfb_rate_idx == 0) {
-			sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+		if(ivideo.rate_idx == 0) {
+			ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
 			ivideo.refresh_rate = 60;
 		}
 
-		if (sisfb_thismonitor.datavalid) {
+		if(sisfb_thismonitor.datavalid) {
 			if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-			                      sisfb_rate_idx, ivideo.refresh_rate)) {
+			                      ivideo.rate_idx, ivideo.refresh_rate)) {
 				printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 			}
 		}
@@ -4839,13 +5032,14 @@ int __init sisfb_init(void)
 
 		sisfb_pre_setmode();
 
-		if (SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
+		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
-				sisfb_mode_no);
+				ivideo.mode_no);
+			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
 			vfree(sishw_ext.pSR);
 			vfree(sishw_ext.pCR);
 			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
+			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
@@ -4877,7 +5071,7 @@ int __init sisfb_init(void)
 			
 		sisfb_set_disp(-1, &default_var, sis_fb_info);
 		
-#else		/* --------- For 2.5: Setup a somewhat sane default var ------------ */
+#else		/* --------- For 2.6: Setup a somewhat sane default var ------------ */
 
 		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
 	       		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
@@ -4891,10 +5085,10 @@ int __init sisfb_init(void)
 		
 		default_var.pixclock = (u32) (1000000000 /
 				sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						sisfb_mode_no, sisfb_rate_idx));
+						ivideo.mode_no, ivideo.rate_idx));
 						
 		if(sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-			 sisfb_mode_no, sisfb_rate_idx,
+			 ivideo.mode_no, ivideo.rate_idx,
 			 &default_var.left_margin, &default_var.right_margin, 
 			 &default_var.upper_margin, &default_var.lower_margin,
 			 &default_var.hsync_len, &default_var.vsync_len,
@@ -4927,23 +5121,24 @@ int __init sisfb_init(void)
 		sis_fb_info->par = &ivideo;
 		sis_fb_info->screen_base = ivideo.video_vbase;
 		sis_fb_info->fbops = &sisfb_ops;
+#ifdef NEWFBDEV
 		sis_fb_info->class_dev.dev = &pdev->dev;
+#endif
 		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
 		sis_fb_info->pseudo_palette = pseudo_palette;
 		
 		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
 #endif
 
-		printk(KERN_INFO "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
+		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
 
 #ifdef CONFIG_MTRR
 		ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
 				(unsigned int) ivideo.video_size,
 				MTRR_TYPE_WRCOMB, 1);
 		if(ivideo.mtrr) {
-			printk(KERN_INFO "sisfb: Added MTRRs\n");
+			printk(KERN_DEBUG "sisfb: Added MTRRs\n");
 		}
-
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -4951,41 +5146,110 @@ int __init sisfb_init(void)
 #endif
 
 		if(register_framebuffer(sis_fb_info) < 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
 			vfree(sishw_ext.pSR);
 			vfree(sishw_ext.pCR);
 			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
-#endif
+			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
-		sisfb_registered = 1;			
+		ivideo.registered = 1;
+
+		pci_set_drvdata(pdev, sis_fb_info);
 
 		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
 		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_VBRSTATUS ioctl (%x)\n", SISFB_GET_VBRSTATUS);
-		
+
 		printk(KERN_INFO "sisfb: 2D acceleration is %s, scrolling mode %s\n",
 		     sisfb_accel ? "enabled" : "disabled",
 		     sisfb_ypan  ? (sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
 		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename, VER_MAJOR, VER_MINOR,
-	       		VER_LEVEL);		     
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename,
 #else
-		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-	       		sis_fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+	       		sis_fb_info->node, myid,
 #endif
+			VER_MAJOR, VER_MINOR, VER_LEVEL);
 
-		printk(KERN_INFO "sisfb: (C) 2001-2003 Thomas Winischhofer.\n");
+		printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
 
 	}	/* if mode = "none" */
+
 	return 0;
 }
 
+/*****************************************************/
+/*                PCI DEVICE HANDLING                */
+/*****************************************************/
+
+static void __devexit sisfb_remove(struct pci_dev *pdev)
+{
+	/* Unmap */
+	iounmap(ivideo.video_vbase);
+	iounmap(ivideo.mmio_vbase);
+	if(ivideo.bios_vbase) iounmap(ivideo.bios_vbase);
+
+	/* Release mem regions */
+	release_mem_region(ivideo.video_base, ivideo.video_size);
+	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+
+#ifdef CONFIG_MTRR
+	/* Release MTRR region */
+	if(ivideo.mtrr) {
+		mtrr_del(ivideo.mtrr,
+		      (unsigned int)ivideo.video_base,
+	              (unsigned int)ivideo.video_size);
+	}
+#endif
+
+	/* Unregister the framebuffer */
+	if(ivideo.registered) {
+		unregister_framebuffer(sis_fb_info);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+		framebuffer_release(sis_fb_info);
+#else
+		kfree(sis_fb_info);
+#endif
+	}
+
+	if(sishw_ext.pSR) vfree(sishw_ext.pSR);
+	if(sishw_ext.pCR) vfree(sishw_ext.pCR);
+	if(ivideo.bios_abase) vfree(ivideo.bios_abase);
+
+	pci_set_drvdata(pdev, NULL);
+
+	/* TODO: Restore the initial mode
+	 * This sounds easy but is as good as impossible
+	 * on many machines with SiS chip and video bridge
+	 * since text modes are always set up differently
+	 * from machine to machine. Depends on the type
+	 * of integration between chipset and bridge.
+	 */
+	if(ivideo.registered) {
+	   printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
+	}
+};
+
+static struct pci_driver sisfb_driver = {
+	.name		= "sisfb",
+	.id_table 	= sisfb_pci_table,
+	.probe 		= sisfb_probe,
+	.remove 	= __devexit_p(sisfb_remove)
+};
+
+int __init sisfb_init(void)
+{
+	return(pci_module_init(&sisfb_driver));
+}
+
+/*****************************************************/
+/*                      MODULE                       */
+/*****************************************************/
 
 #ifdef MODULE
 
@@ -4997,7 +5261,8 @@ static unsigned int mem = 0;
 static char         *forcecrt2type = NULL;
 static int          forcecrt1 = -1;
 static char         *queuemode = NULL;
-static int          pdc = 0;
+static int          pdc = -1;
+static int          pdc1 = -1;
 static int          noaccel = -1;
 static int          noypan  = -1;
 static int	    nomax = -1;
@@ -5011,10 +5276,14 @@ static int	    nocrt2rate = 0;
 static int          scalelcd = -1;
 static char	    *specialtiming = NULL;
 static int	    lvdshl = -1;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int	    resetcard = 0;
+static int	    videoram = 0;
+#endif
 
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/651/661/740/741/330/760 framebuffer driver");
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer driver");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Various others");
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Others");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 MODULE_PARM(mode, "s");
@@ -5068,11 +5337,11 @@ MODULE_PARM_DESC(filter,
 
 MODULE_PARM(queuemode,   "s");
 MODULE_PARM_DESC(queuemode,
-	"\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP, VRAM,\n"
-  	  "MMIO. AGP is only available if the kernel has AGP support. The queue mode is\n"
-	  "important to programs using the 2D/3D accelerator of the SiS chip. The modes\n"
-	  "require a totally different way of programming the engines. If any mode than\n"
-	  "MMIO is selected, sisfb will disable its own 2D acceleration. On\n"
+	"\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP,\n"
+  	  "VRAM and MMIO. AGP is only available if the kernel has AGP support. The queue\n"
+	  "mode is important to programs using the 2D/3D accelerator of the SiS chip.\n"
+	  "The modes require a totally different way of programming the engines. If any\n"
+	  "mode than MMIO is selected, sisfb will disable its own 2D acceleration. On\n"
 	  "300/540/630/730, this option is ignored. (default: MMIO)");
 
 /* TW: "Import" the options from the X driver */
@@ -5083,16 +5352,16 @@ MODULE_PARM_DESC(mem,
 	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
 	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
 	  "otherwise at 12288KB. On 315 and Xabre series, the heap is 1MB by default. The\n"
-	  "value is to be specified without 'KB' and should match the MaxXFBMem setting for\n"
-	  "XFree 4.x (x>=2).");
+	  "value is to be specified without 'KB' and should match the MaxXFBMem setting\n"
+	  "for XFree 4.x (x>=2).");
 
 MODULE_PARM(forcecrt2type, "s");
 MODULE_PARM_DESC(forcecrt2type,
 	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
 	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
 	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
-	  "On systems with a 301(B/LV) bridge, parameters SVIDEO, COMPOSITE or SCART can be\n"
-	  "used instead of TV to override the TV detection. (default: [autodetected])");
+	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
+	  "be used instead of TV to override the TV detection. (default: [autodetected])");
 
 MODULE_PARM(forcecrt1, "i");
 MODULE_PARM_DESC(forcecrt1,
@@ -5105,9 +5374,14 @@ MODULE_PARM_DESC(pdc,
         "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
 	  "should detect this correctly in most cases; however, sometimes this is not\n"
 	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
-	  "on a 300 series chipset; 3 or 51 on a 315 series chipset. If the problem persists,\n"
+	  "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
 	  "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
-	  "and value from 0 to 255). (default: [autodetected])");
+	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)");
+
+MODULE_PARM(pdc1, "i");
+MODULE_PARM_DESC(pdc1,
+        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315 series\n"
+	  "only. (default: autodetected if LCD is in LCD-via-CRT1 mode during startup)");
 
 MODULE_PARM(noaccel, "i");
 MODULE_PARM_DESC(noaccel,
@@ -5122,9 +5396,10 @@ MODULE_PARM_DESC(noypan,
 MODULE_PARM(nomax, "i");
 MODULE_PARM_DESC(nomax,
         "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
-	  "memory for the virtual screen in order to optimize scrolling performance. If this\n"
-	  "is set to anything other than 0, sisfb will not do this and thereby enable the user\n"
-	  "to positively specify a virtual Y size of the screen using fbset. (default: 0)\n");
+	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
+	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
+	  "enable the user to positively specify a virtual Y size of the screen using\n"
+	  "fbset. (default: 0)\n");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
 MODULE_PARM(inverse, "i");
@@ -5156,20 +5431,31 @@ MODULE_PARM_DESC(nocrt2rate,
 MODULE_PARM(scalelcd, "i");
 MODULE_PARM_DESC(scalelcd,
 	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
-	  "native resolution. Setting it to 0 will disable scaling; if the panel can scale\n"
-	  "by itself, it will probably do this, otherwise you will see a black bar around\n"
-	  "the screen image. Default: [autodetect if panel can scale]");
+	  "native resolution. Setting it to 0 will disable scaling; if the panel can\n"
+	  "scale by itself, it will probably do this, otherwise you will see a black bar\n"
+	  "around the screen image. Default: [autodetect if panel can scale]");
 
 MODULE_PARM(specialtiming, "s");
 
 MODULE_PARM(lvdshl, "i");
 
+#if !defined(__i386__) && !defined(__x86_64__)
+MODULE_PARM(resetcard, "i");
+MODULE_PARM_DESC(resetcard,
+	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
+	  "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
+	  "Default: 0");
+MODULE_PARM(videoram, "i");
+MODULE_PARM_DESC(videoram,
+	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
+	  "some non-x86 architectures where the memory auto detection fails. Only\n"
+	  "relevant if resetcard is set, too. Default: [auto-detect]");
+#endif
 
-int init_module(void)
+int __init sisfb_init_module(void)
 {
-	int err;
-
 	SiS_Pr.UsePanelScaler = -1;
+	SiS_Pr.CenterScreen = -1;
 	SiS_Pr.SiS_CustomT = CUT_NONE;
 	SiS_Pr.LVDSHL = -1;
 
@@ -5230,14 +5516,15 @@ int init_module(void)
 
 	sisfb_useoem = useoem;
 
-	if (queuemode)        sisfb_search_queuemode(queuemode);
-	
+	if(queuemode)         sisfb_search_queuemode(queuemode);
+
 	/* If other queuemode than MMIO, disable 2D accel and ypan */
 	if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
 	        sisfb_accel = 0;
 	}
 
-        if(pdc) sisfb_pdc = pdc & 0x3c;
+        if(pdc != -1)  sisfb_pdc  = (pdc  & 0x7f);
+	if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
 
 	sisfb_nocrt2rate = nocrt2rate;
 
@@ -5246,55 +5533,30 @@ int init_module(void)
 
 	if((lvdshl >= 0) && (lvdshl <= 3)) SiS_Pr.LVDSHL = lvdshl;
 
-	if((err = sisfb_init()) < 0) return err;
-
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	/* Release mem regions */
-	release_mem_region(ivideo.video_base, ivideo.video_size);
-	release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
+#if !defined(__i386__) && !defined(__x86_64__)
+        if(resetcard)   sisfb_resetcard = 1;
+	else		sisfb_resetcard = 0;
 
-#ifdef CONFIG_MTRR
-	/* TW: Release MTRR region */
-	if(ivideo.mtrr) {
-		mtrr_del(ivideo.mtrr,
-		      (unsigned int)ivideo.video_base,
-	              (unsigned int)ivideo.video_size);
-	}
+	if(videoram)    sisfb_videoram = videoram;
 #endif
 
-	/* Unregister the framebuffer */
-	if(sisfb_registered) {
-		unregister_framebuffer(sis_fb_info);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-		framebuffer_release(sis_fb_info);
-#else
-		kfree(sis_fb_info);
-#endif
-	}
+        return(sisfb_init());
+}
 
-	if(sishw_ext.pSR) vfree(sishw_ext.pSR);
-	if(sishw_ext.pCR) vfree(sishw_ext.pCR);
-	
-	/* TODO: Restore the initial mode 
-	 * This sounds easy but is as good as impossible
-	 * on many machines with SiS chip and video bridge
-	 * since text modes are always set up differently
-	 * from machine to machine. Depends on the type
-	 * of integration between chipset and bridge.
-	 */
-	
-	printk(KERN_INFO "sisfb: Module unloaded\n");
+static void __exit sisfb_remove_module(void)
+{
+	pci_unregister_driver(&sisfb_driver);
+	printk(KERN_DEBUG "sisfb: Module unloaded\n");
 }
 
-#endif
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+#endif 	   /*  /MODULE  */
 
 EXPORT_SYMBOL(sis_malloc);
 EXPORT_SYMBOL(sis_free);
 EXPORT_SYMBOL(sis_dispinfo);
 
 EXPORT_SYMBOL(ivideo);
-                                                                                           
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/sis_main.h linux-2.4.26-pre6/drivers/video/sis/sis_main.h
--- linux-2.4.25/drivers/video/sis/sis_main.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/sis_main.h	2004-03-25 00:18:28.000000000 +0000
@@ -32,7 +32,7 @@
 
 #define VER_MAJOR                 1
 #define VER_MINOR                 6
-#define VER_LEVEL                 25
+#define VER_LEVEL                 32
 
 #include "sis.h"
 
@@ -161,12 +161,12 @@
 #define MMIO_QUEUE_WRITEPORT      0x85C4
 #define MMIO_QUEUE_READPORT       0x85C8
 
-#define IND_SIS_CRT2_WRITE_ENABLE_300 0x24
-#define IND_SIS_CRT2_WRITE_ENABLE_315 0x2F
+#define SIS_CRT2_WENABLE_300 0x24
+#define SIS_CRT2_WENABLE_315 0x2F
 
 #define SIS_PASSWORD              0x86  /* SR05 */
 #define SIS_INTERLACED_MODE       0x20  /* SR06 */
-#define SIS_8BPP_COLOR_MODE       0x0 
+#define SIS_8BPP_COLOR_MODE       0x0
 #define SIS_15BPP_COLOR_MODE      0x1 
 #define SIS_16BPP_COLOR_MODE      0x2 
 #define SIS_32BPP_COLOR_MODE      0x4 
@@ -187,10 +187,10 @@
 #define SIS315_DATA_BUS_64        0x00
 #define SIS315_DATA_BUS_128       0x01
 #define SIS315_DUAL_CHANNEL_MASK  0x0C
-#define SIS315_SINGLE_CHANNEL_1_RANK  	0x0
-#define SIS315_SINGLE_CHANNEL_2_RANK  	0x1
+#define SIS315_SINGLE_CHANNEL_1_RANK  	0x00
+#define SIS315_SINGLE_CHANNEL_2_RANK  	0x01
 #define SIS315_ASYM_DDR		  	0x02
-#define SIS315_DUAL_CHANNEL_1_RANK    	0x3
+#define SIS315_DUAL_CHANNEL_1_RANK    	0x03
 
 #define SIS_SCRATCH_REG_1A_MASK   0x10
 
@@ -314,9 +314,40 @@
                                           outSISIDXREG(base,idx,__Temp); \
                                         } while (0)
 
-/* ------------------- Global Variables ----------------------------- */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+/* Offscreen layout */
+typedef struct _SIS_GLYINFO {
+	unsigned char ch;
+	int fontwidth;
+	int fontheight;
+	u8 gmask[72];
+	int ngmask;
+} SIS_GLYINFO;
+
+static char sisfb_fontname[40];
+#endif
 
-/* Fbcon variables */
+typedef struct _SIS_OH {
+	struct _SIS_OH *poh_next;
+	struct _SIS_OH *poh_prev;
+	unsigned long offset;
+	unsigned long size;
+} SIS_OH;
+
+typedef struct _SIS_OHALLOC {
+	struct _SIS_OHALLOC *poha_next;
+	SIS_OH aoh[1];
+} SIS_OHALLOC;
+
+typedef struct _SIS_HEAP {
+	SIS_OH oh_free;
+	SIS_OH oh_used;
+	SIS_OH *poh_freelist;
+	SIS_OHALLOC *poha_chain;
+	unsigned long max_freesize;
+} SIS_HEAP;
+
+/* Fbcon stuff */
 static struct fb_info *sis_fb_info;
 
 static struct fb_var_screeninfo default_var = {
@@ -384,38 +415,28 @@ static int sisfb_inverse = 0;
 static int currcon = 0;
 #endif
 
-/* global flags */
 static int sisfb_off = 0;
 static int sisfb_crt1off = 0;
 static int sisfb_forcecrt1 = -1;
-static int sisvga_enabled = 0;
+static int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
+static int sisfb_tvplug    = -1;	/* Tv plug type (for overriding autodetection) */
 static int sisfb_userom = 1;
 static int sisfb_useoem = -1;
 static int sisfb_parm_rate = -1;
-static int sisfb_registered = 0;
 static int sisfb_mem = 0;
-static int sisfb_pdc = 0;
+static int sisfb_pdc = 0xff;
+static int sisfb_pdca = 0xff;
 static int sisfb_ypan = -1;
 static int sisfb_max = -1;
 static int sisfb_nocrt2rate = 0;
 static int sisfb_dstn = 0;
 static int sisfb_fstn = 0;
-
-VGA_ENGINE sisvga_engine = UNKNOWN_VGA;
 int 	   sisfb_accel = -1;
-
-/* These are to adapted according to VGA_ENGINE type */
-static int sisfb_hwcursor_size = 0;
-static int sisfb_CRT2_write_enable = 0;
-
-int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
-int sisfb_tvplug    = -1;	/* Tv plug type (for overriding autodetection) */
-
-int sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
-
-unsigned char sisfb_detectedpdc = 0;
-
-unsigned char sisfb_detectedlcda = 0xff;
+int 	   sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
+#if !defined(__i386__) && !defined(__x86_64__)
+static int sisfb_resetcard = 0;
+static int sisfb_videoram = 0;
+#endif
 
 /* data for sis hardware ("par") */
 struct video_info ivideo;
@@ -429,10 +450,6 @@ SIS_HW_INFO sishw_ext;
 /* SiS private structure */
 SiS_Private  SiS_Pr;
 
-/* Card parameters */
-static unsigned long sisfb_mmio_size = 0;
-static u8            sisfb_caps = 0;
-
 typedef enum _SIS_CMDTYPE {
 	MMIO_CMD = 0,
 	AGP_CMD_QUEUE,
@@ -440,22 +457,43 @@ typedef enum _SIS_CMDTYPE {
 } SIS_CMDTYPE;
 
 /* List of supported chips */
-static struct board {
-	u16 vendor, device;
-	const char *name;
-} sisdev_list[] = {
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     "SIS 300"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630/730 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    "SIS 315H"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     "SIS 315"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  "SIS 315PRO"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, "SIS 550 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, "SIS 65x/M65x/740 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     "SIS 330"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, "SIS 661FX/M661FX/741/760 VGA"},
-	{0, 0, NULL}
+static struct sisfb_chip_info {
+        int 		chip;
+	VGA_ENGINE 	vgaengine;
+	int 		hwcursor_size;
+	int		CRT2_write_enable;
+	const char 	*chip_name;
+} sisfb_chip_info[] __devinitdata = {
+	{ SIS_300,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
+	{ SIS_540,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
+	{ SIS_630,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
+	{ SIS_315H,   SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
+	{ SIS_315,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
+	{ SIS_315PRO, SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
+	{ SIS_550,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
+	{ SIS_650,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 65x" },
+	{ SIS_330,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
+	{ SIS_660,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+};
+
+static struct pci_device_id __devinitdata sisfb_pci_table[] = {
+#ifdef CONFIG_FB_SIS_300
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+#endif
+#ifdef CONFIG_FB_SIS_315
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+#endif
+	{ 0 }
 };
+MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
 
 #define MD_SIS300 1
 #define MD_SIS315 2
@@ -563,7 +601,11 @@ struct _sisbios_mode {
 	{"1280x768x16",  0x24, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
 	{"1280x768x24",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
 	{"1280x768x32",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x960x8",   0x7c, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315}, 
+	{"1280x800x8",   0x14, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
+	{"1280x800x16",  0x15, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
+	{"1280x800x24",  0x16, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x800x32",  0x16, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x960x8",   0x7c, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
 	{"1280x960x16",  0x7d, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
 	{"1280x960x24",  0x7e, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
 	{"1280x960x32",  0x7e, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
@@ -587,6 +629,10 @@ struct _sisbios_mode {
 	{"1600x1200x16", 0x3d, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
 	{"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
 	{"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1680x1050x8",  0x17, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x16", 0x18, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x24", 0x19, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x32", 0x19, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
 	{"1920x1440x8",  0x68, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
 	{"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
 	{"1920x1440x24", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
@@ -604,8 +650,6 @@ int sisfb_mode_idx = MODE_INDEX_NONE;  /
 #else
 int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
 #endif
-u8  sisfb_mode_no  = 0;
-u8  sisfb_rate_idx = 0;
 
 /* CR36 evaluation */
 const USHORT sis300paneltype[] =
@@ -620,15 +664,21 @@ const USHORT sis310paneltype[] =
       LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
       LCD_640x480_2, LCD_640x480_3, LCD_320x480,   LCD_1024x768 };
 
+const USHORT sis661paneltype[] =
+    { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+      LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
+      LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
+      LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_1024x768 };
+
 #define FL_550_DSTN 0x01
 #define FL_550_FSTN 0x02
 
-static const struct _sis_crt2type {
+static struct _sis_crt2type {
 	char name[10];
 	int type_no;
 	int tvplug_no;
 	unsigned short flags;
-} sis_crt2type[] = {
+} sis_crt2type[] __initdata = {
 	{"NONE", 	0, 		-1,        0},
 	{"LCD",  	CRT2_LCD, 	-1,        0},
 	{"TV",   	CRT2_TV, 	-1,        0},
@@ -642,10 +692,10 @@ static const struct _sis_crt2type {
 };
 
 /* Queue mode selection for 310 series */
-static const struct _sis_queuemode {
+static struct _sis_queuemode {
 	char name[6];
 	int type_no;
-} sis_queuemode[] = {
+} sis_queuemode[] __initdata = {
 	{"AGP",  	AGP_CMD_QUEUE},
 	{"VRAM", 	VM_CMD_QUEUE},
 	{"MMIO", 	MMIO_CMD},
@@ -653,10 +703,10 @@ static const struct _sis_queuemode {
 };
 
 /* TV standard */
-static const struct _sis_tvtype {
+static struct _sis_tvtype {
 	char name[6];
 	int type_no;
-} sis_tvtype[] = {
+} sis_tvtype[] __initdata = {
 	{"PAL",  	TV_PAL},
 	{"NTSC", 	TV_NTSC},
 	{"\0",   	-1}
@@ -696,6 +746,7 @@ static const struct _sis_vrate {
 	{1, 1152,  864,  75,  TRUE}, {2, 1152,  864,  84,  TRUE},
 	{1, 1280,  720,  60,  TRUE}, {2, 1280,  720,  75,  TRUE}, {3, 1280,  720,  85,  TRUE},
 	{1, 1280,  768,  60,  TRUE},
+	{1, 1280,  800,  60,  TRUE},
 	{1, 1280,  960,  60,  TRUE}, {2, 1280,  960,  85,  TRUE},
 	{1, 1280, 1024,  43,  TRUE}, {2, 1280, 1024,  60,  TRUE}, {3, 1280, 1024,  75,  TRUE},
 	{4, 1280, 1024,  85,  TRUE},
@@ -705,6 +756,7 @@ static const struct _sis_vrate {
 	{1, 1600, 1200,  60,  TRUE}, {2, 1600, 1200,  65,  TRUE}, {3, 1600, 1200,  70,  TRUE},
 	{4, 1600, 1200,  75,  TRUE}, {5, 1600, 1200,  85,  TRUE}, {6, 1600, 1200, 100,  TRUE},
 	{7, 1600, 1200, 120,  TRUE},
+	{1, 1680, 1050,  60,  TRUE},
 	{1, 1920, 1440,  60,  TRUE}, {2, 1920, 1440,  65,  TRUE}, {3, 1920, 1440,  70,  TRUE},
 	{4, 1920, 1440,  75,  TRUE}, {5, 1920, 1440,  85,  TRUE}, {6, 1920, 1440, 100,  TRUE},
 	{1, 2048, 1536,  60,  TRUE}, {2, 2048, 1536,  65,  TRUE}, {3, 2048, 1536,  70,  TRUE},
@@ -764,18 +816,20 @@ static const struct _sisfbddcfmodes {
 static u8 sisfb_lastrates[128];
 #endif
 
-static const struct _chswtable {
+#ifdef CONFIG_FB_SIS_300
+static struct _chswtable {
     int subsysVendor;
     int subsysCard;
     char *vendorName;
     char *cardName;
-} mychswtable[] = {
+} mychswtable[] __devinitdata = {
         { 0x1631, 0x1002, "Mitachi", "0x1002" },
 	{ 0x1071, 0x7521, "Mitac"  , "7521P"  },
 	{ 0,      0,      ""       , ""       }
 };
+#endif
 
-static const struct _customttable {
+static struct _customttable {
     unsigned short chipID;
     char *biosversion;
     char *biosdate;
@@ -788,7 +842,7 @@ static const struct _customttable {
     char *cardName;
     unsigned long SpecialID;
     char *optionName;
-} mycustomttable[] = {
+} mycustomttable[] __devinitdata = {
 	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
 	  0x3240A8,
 	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
@@ -917,40 +971,7 @@ static const struct _customttable {
 	}
 };
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* Offscreen layout */
-typedef struct _SIS_GLYINFO {
-	unsigned char ch;
-	int fontwidth;
-	int fontheight;
-	u8 gmask[72];
-	int ngmask;
-} SIS_GLYINFO;
 
-static char sisfb_fontname[40];
-#endif
-
-typedef struct _SIS_OH {
-	struct _SIS_OH *poh_next;
-	struct _SIS_OH *poh_prev;
-	unsigned long offset;
-	unsigned long size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
-	struct _SIS_OHALLOC *poha_next;
-	SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
-	SIS_OH oh_free;
-	SIS_OH oh_used;
-	SIS_OH *poh_freelist;
-	SIS_OHALLOC *poha_chain;
-	unsigned long max_freesize;
-} SIS_HEAP;
-
-static unsigned long sisfb_hwcursor_vbase;
 
 static unsigned long sisfb_heap_start;
 static unsigned long sisfb_heap_end;
@@ -1208,7 +1229,7 @@ static int      sisfb_do_set_var(struct 
 static void     sisfb_pre_setmode(void);
 static void     sisfb_post_setmode(void);
 
-static char *   sis_find_rom(void);
+static char *   sis_find_rom(struct pci_dev *pdev);
 static BOOLEAN  sisfb_CheckVBRetrace(void);
 static BOOLEAN  sisfbcheckvretracecrt2(void);
 static BOOLEAN  sisfbcheckvretracecrt1(void);
@@ -1224,10 +1245,6 @@ void            sis_dispinfo(struct ap_d
 void            sis_malloc(struct sis_memreq *req);
 void            sis_free(unsigned long base);
 
-/* Internal hardware access routines */
-void            sisfb_set_reg4(u16 port, unsigned long data);
-u32             sisfb_get_reg3(u16 port);
-
 /* Chipset-dependent internal routines */
 #ifdef CONFIG_FB_SIS_300
 static int      sisfb_get_dram_size_300(void);
@@ -1252,9 +1269,9 @@ BOOLEAN         sisfb_query_north_bridge
 	         	unsigned long offset, unsigned long set, unsigned long *value);
 
 /* Sensing routines */
-void            SiS_Sense30x(void);
-int             SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
-void            SiS_SenseCh(void);
+static void     SiS_Sense30x(void);
+static int      SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
+static void     SiS_SenseCh(void);
 
 /* Routines from init.c/init301.c */
 extern USHORT   SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
@@ -1268,6 +1285,8 @@ extern BOOLEAN  SiSSetMode(SiS_Private *
 extern void     SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 extern void     SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
 
+extern BOOLEAN  SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+
 extern BOOLEAN  sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
 
@@ -1286,6 +1305,6 @@ extern void 	SiS_Chrontel701xBLOn(SiS_Pr
 extern void 	SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
 extern void 	SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
 extern void 	SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-
-			
 #endif
+
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/vgatypes.h linux-2.4.26-pre6/drivers/video/sis/vgatypes.h
--- linux-2.4.25/drivers/video/sis/vgatypes.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/vgatypes.h	2004-03-25 00:16:50.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -187,6 +184,7 @@ typedef enum _SIS_LCD_TYPE {
     LCD_848x480,
     LCD_1280x800,
     LCD_1680x1050,
+    LCD_1280x720,
     LCD_CUSTOM,
     LCD_UNKNOWN
 } SIS_LCD_TYPE;
@@ -220,25 +218,27 @@ struct _SIS_HW_INFO
                                  /* of Linear VGA memory */
 
     ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
+
     SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0) */
+
     UCHAR  jChipType;            /* Used to Identify SiS Graphics Chip */
                                  /* defined in the data structure type  */
                                  /* "SIS_CHIP_TYPE" */
 
     UCHAR  jChipRevision;        /* Used to Identify SiS Graphics Chip Revision */
+
     UCHAR  ujVBChipID;           /* the ID of video bridge */
                                  /* defined in the data structure type */
                                  /* "SIS_VB_CHIP_TYPE" */
 #ifdef LINUX_KERNEL
     BOOLEAN Is301BDH;
+    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
+                                 /* "SIS_LCD_TYPE" */
 #endif
 
     USHORT usExternalChip;       /* NO VB or other video bridge (other than  */
                                  /* SiS video bridge) */
 
-    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
-                                 /* "SIS_LCD_TYPE" */
-                                     
     BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
                                       
     BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
@@ -254,12 +254,6 @@ struct _SIS_HW_INFO
                                  /* Note : restore cR registers if  */
                                  /* bSkipDramSizing = TRUE */
 #endif
-
-    PSIS_QUERYSPACE  pQueryVGAConfigSpace; /* Get/Set VGA Configuration  */
-                                           /* space */
- 
-    PSIS_QUERYSPACE  pQueryNorthBridgeSpace;/* Get/Set North Bridge  */
-                                            /* space  */
 };
 #endif
 
@@ -275,42 +269,44 @@ struct _SIS_HW_INFO
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	unsigned long sisfb_id;         /* for identifying sisfb */
+	CARD32 	sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which sisfb manages */
-	int    heapstart;               /* heap start (= sisfb "mem" argument) in KB */
-	unsigned char fbvidmode;	/* current sisfb mode */
+ 	CARD32 	chip_id;		/* PCI ID of detected chip */
+	CARD32	memory;			/* video memory in KB which sisfb manages */
+	CARD32	heapstart;             	/* heap start (= sisfb "mem" argument) in KB */
+	CARD8 	fbvidmode;		/* current sisfb mode */
+
+	CARD8 	sisfb_version;
+	CARD8	sisfb_revision;
+	CARD8 	sisfb_patchlevel;
+
+	CARD8 	sisfb_caps;		/* sisfb's capabilities */
 
-	unsigned char sisfb_version;
-	unsigned char sisfb_revision;
-	unsigned char sisfb_patchlevel;
+	CARD32 	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	unsigned char sisfb_caps;	/* sisfb's capabilities */
+	CARD32 	sisfb_pcibus;      	/* The card's PCI ID */
+	CARD32 	sisfb_pcislot;
+	CARD32 	sisfb_pcifunc;
 
-	int    sisfb_tqlen;		/* turbo queue length (in KB) */
+	CARD8 	sisfb_lcdpdc;
 
-	unsigned int sisfb_pcibus;      /* The card's PCI ID */
-	unsigned int sisfb_pcislot;
-	unsigned int sisfb_pcifunc;
+	CARD8	sisfb_lcda;
 
-	unsigned char sisfb_lcdpdc;
-	
-	unsigned char sisfb_lcda;
+	CARD32	sisfb_vbflags;
+	CARD32	sisfb_currentvbflags;
 
-	unsigned long sisfb_vbflags;
-	unsigned long sisfb_currentvbflags;
+	CARD32 	sisfb_scalelcd;
+	CARD32 	sisfb_specialtiming;
 
-	int sisfb_scalelcd;
-	unsigned long sisfb_specialtiming;
+	CARD8 	sisfb_haveemi;
+	CARD8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	CARD8 	sisfb_haveemilcd;
 
-	unsigned char sisfb_haveemi;
-	unsigned char sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	unsigned char sisfb_haveemilcd;
+	CARD8 	sisfb_lcdpdca;
 
-	char reserved[213]; 		/* for future use */
+	CARD8 reserved[212]; 		/* for future use */
 };
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/sis/vstruct.h linux-2.4.26-pre6/drivers/video/sis/vstruct.h
--- linux-2.4.25/drivers/video/sis/vstruct.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/drivers/video/sis/vstruct.h	2004-03-25 00:17:36.000000000 +0000
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -164,7 +161,6 @@ typedef struct _SiS_ExtStruct
 {
 	UCHAR  Ext_ModeID;
 	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
 	USHORT Ext_VESAID;
 	UCHAR  Ext_RESINFO;
 	UCHAR  VB_ExtTVFlickerIndex;
@@ -180,6 +176,7 @@ typedef struct _SiS_Ext2Struct
 	UCHAR  Ext_CRT1CRTC;
 	UCHAR  Ext_CRTVCLK;
 	UCHAR  Ext_CRT2CRTC;
+	UCHAR  Ext_CRT2CRTC_NS;
 	UCHAR  ModeID;
 	USHORT XRes;
 	USHORT YRes;
@@ -228,6 +225,8 @@ typedef struct _SiS_ModeResInfoStruct
 	UCHAR  YChar;
 } SiS_ModeResInfoStruct;
 
+
+
 typedef UCHAR DRAM4Type[4];
 
 /* Defines for SiS_CustomT */
@@ -289,18 +288,21 @@ typedef struct _SiS_Private
         USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
 #endif
 	BOOLEAN SiS_UseROM;
-	int    SiS_CHOverScan;
+	BOOLEAN SiS_ROMNew;
+	BOOLEAN PanelSelfDetected;
+	int     SiS_CHOverScan;
 	BOOLEAN SiS_CHSOverScan;
 	BOOLEAN SiS_ChSW;
 	BOOLEAN SiS_UseLCDA;
-	int    SiS_UseOEM;
-	ULONG  SiS_CustomT;
-	USHORT SiS_Backup70xx;
+	int     SiS_UseOEM;
+	ULONG   SiS_CustomT;
+	USHORT  SiS_Backup70xx;
 	BOOLEAN HaveEMI;
 	BOOLEAN HaveEMILCD;
 	BOOLEAN OverruleEMI;
 	UCHAR  EMI_30,EMI_31,EMI_32,EMI_33;
-	UCHAR  PDC;
+	SHORT  PDC, PDCA;
+	UCHAR  SiS_MyCR63;
 	USHORT SiS_CRT1Mode;
 	USHORT SiS_flag_clearbuffer;
 	int    SiS_RAMType;
@@ -339,32 +341,19 @@ typedef struct _SiS_Private
 	USHORT SiS_DDC_Port;
 	USHORT SiS_DDC_Index;
 	USHORT SiS_DDC_Data;
+	USHORT SiS_DDC_NData;
 	USHORT SiS_DDC_Clk;
-	USHORT SiS_DDC_DataShift;
+	USHORT SiS_DDC_NClk;
 	USHORT SiS_DDC_DeviceAddr;
 	USHORT SiS_DDC_ReadAddr;
 	USHORT SiS_DDC_SecAddr;
-	USHORT SiS_Panel800x600;
-	USHORT SiS_Panel1024x768;
-	USHORT SiS_Panel1280x1024;
-	USHORT SiS_Panel1600x1200;
-	USHORT SiS_Panel1280x960;
-	USHORT SiS_Panel1400x1050;
-	USHORT SiS_Panel320x480;
-	USHORT SiS_Panel1152x768;
-	USHORT SiS_Panel1280x768;
-	USHORT SiS_Panel1024x600;
-	USHORT SiS_Panel640x480;
-	USHORT SiS_Panel640x480_2;
-	USHORT SiS_Panel640x480_3;
-	USHORT SiS_Panel1152x864;
-	USHORT SiS_PanelCustom;
-	USHORT SiS_PanelBarco1366;
-	USHORT SiS_PanelMax;
+	USHORT SiS_ChrontelInit;
+	BOOLEAN SiS_SensibleSR11;
+	USHORT SiS661LCD2TableSize;
+
 	USHORT SiS_PanelMinLVDS;
 	USHORT SiS_PanelMin301;
-	USHORT SiS_ChrontelInit;
-	
+
 	const SiS_StStruct          *SiS_SModeIDTable;
 	SiS_StandTableStruct        *SiS_StandTable;
 	const SiS_ExtStruct         *SiS_EModeIDTable;
@@ -373,11 +362,10 @@ typedef struct _SiS_Private
 	const SiS_CRT1TableStruct   *SiS_CRT1Table;
 	const SiS_MCLKDataStruct    *SiS_MCLKData_0;
 	const SiS_MCLKDataStruct    *SiS_MCLKData_1;
-	const SiS_VCLKDataStruct    *SiS_VCLKData;
-	const SiS_VBVCLKDataStruct  *SiS_VBVCLKData;
+	SiS_VCLKDataStruct    	    *SiS_VCLKData;
+	SiS_VBVCLKDataStruct        *SiS_VBVCLKData;
 	const SiS_StResInfoStruct   *SiS_StResInfo;
 	const SiS_ModeResInfoStruct *SiS_ModeResInfo;
-	const UCHAR                 *SiS_ScreenOffset;
 
 	const UCHAR                 *pSiS_OutputSelect;
 	const UCHAR                 *pSiS_SoftSetting;
@@ -407,6 +395,12 @@ typedef struct _SiS_Private
 	const USHORT *pSiS_VideoSenseData2;
 	const USHORT *pSiS_YCSenseData2;
 #endif
+
+	const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
+	const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+
+	/* SiS bridge */
+
 	const UCHAR *SiS_NTSCPhase;
 	const UCHAR *SiS_PALPhase;
 	const UCHAR *SiS_NTSCPhase2;
@@ -418,29 +412,27 @@ typedef struct _SiS_Private
 	const UCHAR *SiS_SpecialPhase;
 	const UCHAR *SiS_SpecialPhaseM;
 	const UCHAR *SiS_SpecialPhaseJ;
-	const SiS_LCDDataStruct  *SiS_StLCD1024x768Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1024x768Data;
 	const SiS_LCDDataStruct  *SiS_St2LCD1024x768Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1280x1024Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x720Data;
+	const SiS_LCDDataStruct  *SiS_StLCD1280x768_2Data;
+	const SiS_LCDDataStruct  *SiS_ExtLCD1280x768_2Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x768_3Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x800Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1280x1024Data;
 	const SiS_LCDDataStruct  *SiS_St2LCD1280x1024Data;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1024x768;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1280x1024;
-	const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1400x1050;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1600x1200;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1280x768;
 	const SiS_LCDDataStruct  *SiS_StLCD1400x1050Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1280x768Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1400x1050Data;
+	const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1600x1200Data;
-	const SiS_LCDDataStruct  *SiS_ExtLCD1280x768Data;
+	const SiS_LCDDataStruct  *SiS_LCD1680x1050Data;
 	const SiS_LCDDataStruct  *SiS_NoScaleData;
 	const SiS_TVDataStruct   *SiS_StPALData;
 	const SiS_TVDataStruct   *SiS_ExtPALData;
 	const SiS_TVDataStruct   *SiS_StNTSCData;
 	const SiS_TVDataStruct   *SiS_ExtNTSCData;
+	const SiS_TVDataStruct   *SiS_St1HiTVData;
 	const SiS_TVDataStruct   *SiS_St2HiTVData;
 	const SiS_TVDataStruct   *SiS_ExtHiTVData;
 	const SiS_TVDataStruct   *SiS_St525iData;
@@ -454,12 +446,22 @@ typedef struct _SiS_Private
 	const UCHAR *SiS_HiTVExtTiming;
 	const UCHAR *SiS_HiTVSt1Timing;
 	const UCHAR *SiS_HiTVSt2Timing;
-	const UCHAR *SiS_HiTVTextTiming;
 	const UCHAR *SiS_HiTVGroup3Data;
 	const UCHAR *SiS_HiTVGroup3Simu;
+#if 0
+	const UCHAR *SiS_HiTVTextTiming;
 	const UCHAR *SiS_HiTVGroup3Text;
-	const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
-	const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+#endif
+
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
+
+	/* LVDS, Chrontel */
+
 	const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDS1024x768Data_1;
@@ -481,14 +483,6 @@ typedef struct _SiS_Private
 	const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDS320x480Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1024x768Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1024x768Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1280x1024Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1280x1024Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1400x1050Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1400x1050Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1600x1200Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1600x1200Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDSXXXxXXXData_1;
 	const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_2;
@@ -505,6 +499,7 @@ typedef struct _SiS_Private
 	const SiS_LVDSDataStruct  *SiS_CHTVUPALNData;
 	const SiS_LVDSDataStruct  *SiS_CHTVOPALNData;
 	const SiS_LVDSDataStruct  *SiS_CHTVSOPALData;
+
 	const SiS_LVDSDesStruct  *SiS_PanelType00_1;
 	const SiS_LVDSDesStruct  *SiS_PanelType01_1;
 	const SiS_LVDSDesStruct  *SiS_PanelType02_1;
@@ -539,20 +534,11 @@ typedef struct _SiS_Private
 	const SiS_LVDSDesStruct  *SiS_PanelType0e_2;
 	const SiS_LVDSDesStruct  *SiS_PanelType0f_2;
 	const SiS_LVDSDesStruct  *SiS_PanelTypeNS_2;
-
-	const SiS_LVDSDesStruct  *LVDS1024x768Des_1;
-	const SiS_LVDSDesStruct  *LVDS1280x1024Des_1;
-	const SiS_LVDSDesStruct  *LVDS1400x1050Des_1;
-	const SiS_LVDSDesStruct  *LVDS1600x1200Des_1;
-	const SiS_LVDSDesStruct  *LVDS1024x768Des_2;
-	const SiS_LVDSDesStruct  *LVDS1280x1024Des_2;
-	const SiS_LVDSDesStruct  *LVDS1400x1050Des_2;
-	const SiS_LVDSDesStruct  *LVDS1600x1200Des_2;
-
 	const SiS_LVDSDesStruct  *SiS_CHTVUNTSCDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVONTSCDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVUPALDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVOPALDesData;
+
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_1;
@@ -593,44 +579,13 @@ typedef struct _SiS_Private
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_2_H;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3_H;
+	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UNTSC;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1ONTSC;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UPAL;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1OPAL;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1SOPAL;
 
-	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
-
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_2_H;
-
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_3;
-
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
@@ -640,6 +595,7 @@ typedef struct _SiS_Private
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL;
+
 	const UCHAR *SiS_CHTVVCLKUNTSC;
 	const UCHAR *SiS_CHTVVCLKONTSC;
 	const UCHAR *SiS_CHTVVCLKUPAL;
@@ -650,9 +606,13 @@ typedef struct _SiS_Private
 	const UCHAR *SiS_CHTVVCLKOPALN;
 	const UCHAR *SiS_CHTVVCLKSOPAL;
 
-	USHORT  PanelXRes;
-	USHORT  PanelYRes;
-	
+	USHORT  PanelXRes, PanelHT;
+	USHORT  PanelYRes, PanelVT;
+	USHORT  PanelHRS,  PanelHRE;
+  	USHORT 	PanelVRS,  PanelVRE;
+	USHORT  PanelVCLKIdx300;
+	USHORT  PanelVCLKIdx315;
+
 	BOOLEAN UseCustomMode;
 	BOOLEAN CRT1UsesCustomMode;
 	USHORT  CHDisplay;
@@ -694,10 +654,11 @@ typedef struct _SiS_Private
 	UCHAR Backup_1d;
 	
 	int     UsePanelScaler;
+	int	CenterScreen;
 
 	USHORT  CP_Vendor, CP_Product;
 	BOOLEAN CP_HaveCustomData;
-	int     CP_PreferredX, CP_PreferredY;
+	int     CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
 	int	CP_MaxX, CP_MaxY, CP_MaxClock;
 	BOOLEAN CP_Supports64048075;
 	int     CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/devfs/base.c linux-2.4.26-pre6/fs/devfs/base.c
--- linux-2.4.25/fs/devfs/base.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/fs/devfs/base.c	2004-03-25 00:17:59.000000000 +0000
@@ -3549,7 +3549,7 @@ void __init mount_devfs_fs (void)
     int err;
 
     if ( !(boot_options & OPTION_MOUNT) ) return;
-    err = do_mount ("none", "/dev", "devfs", 0, "");
+    err = do_mount ("none", "/dev", "devfs", 0, NULL);
     if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n");
     else PRINTK ("(): unable to mount devfs, err: %d\n", err);
 }   /*  End Function mount_devfs_fs  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/fat/inode.c linux-2.4.26-pre6/fs/fat/inode.c
--- linux-2.4.25/fs/fat/inode.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/fat/inode.c	2004-03-25 00:19:35.000000000 +0000
@@ -421,11 +421,13 @@ static void fat_read_root(struct inode *
  *  0/  i_ino - for fast, reliable lookup if still in the cache
  *  1/  i_generation - to see if i_ino is still valid
  *          bit 0 == 0 iff directory
- *  2/  i_pos - if ino has changed, but still in cache (hi)
- *  3/  i_pos - if ino has changed, but still in cache (low)
- *  4/  i_logstart - to semi-verify inode found at i_location
- *  5/  parent->i_logstart - maybe used to hunt for the file on disc
+ *  2/  i_pos(8-39) - if ino has changed, but still in cache
+ *  3/  i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos
+ *  4/  i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc
  *
+ * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum
+ * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits
+ * of i_logstart is used to store the directory entry offset.
  */
 struct dentry *fat_fh_to_dentry(struct super_block *sb, __u32 *fh,
 				int len, int fhtype, int parent)
@@ -436,7 +438,7 @@ struct dentry *fat_fh_to_dentry(struct s
 
 	if (fhtype != 3)
 		return ERR_PTR(-ESTALE);
-	if (len < 6)
+	if (len < 5)
 		return ERR_PTR(-ESTALE);
 	/* We cannot find the parent,
 	   It better just *be* there */
@@ -444,13 +446,17 @@ struct dentry *fat_fh_to_dentry(struct s
 		return ERR_PTR(-ESTALE);
 
 	inode = iget(sb, fh[0]);
-	if (!inode || is_bad_inode(inode) ||
-	    inode->i_generation != fh[1]) {
-		if (inode) iput(inode);
+	if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {
+		if (inode)
+			iput(inode);
 		inode = NULL;
 	}
 	if (!inode) {
-		loff_t i_pos = ((loff_t)fh[2] << 32) | fh[3];
+		loff_t i_pos;
+		int i_logstart = fh[3] & 0x0fffffff;
+
+		i_pos = (loff_t)fh[2] << 8;
+		i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);
 
 		/* try 2 - see if i_pos is in F-d-c
 		 * require i_logstart to be the same
@@ -458,7 +464,7 @@ struct dentry *fat_fh_to_dentry(struct s
 		 */
 
 		inode = fat_iget(sb, i_pos);
-		if (inode && MSDOS_I(inode)->i_logstart != fh[4]) {
+		if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {
 			iput(inode);
 			inode = NULL;
 		}
@@ -508,24 +514,26 @@ struct dentry *fat_fh_to_dentry(struct s
 	result->d_op = sb->s_root->d_op;
 	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
 	return result;
-
-		
 }
 
 int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent)
 {
 	int len = *lenp;
 	struct inode *inode =  de->d_inode;
+	u32 ipos_h, ipos_m, ipos_l;
 	
-	if (len < 6)
+	if (len < 5)
 		return 255; /* no room */
-	*lenp = 6;
+
+	ipos_h = MSDOS_I(inode)->i_pos >> 8;
+	ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
+	ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;
+	*lenp = 5;
 	fh[0] = inode->i_ino;
 	fh[1] = inode->i_generation;
-	fh[2] = (__u32)(MSDOS_I(inode)->i_pos >> 32);
-	fh[3] = (__u32)MSDOS_I(inode)->i_pos;
-	fh[4] = MSDOS_I(inode)->i_logstart;
-	fh[5] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
+	fh[2] = ipos_h;
+	fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
+	fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
 	return 3;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/hfsplus/wrapper.c linux-2.4.26-pre6/fs/hfsplus/wrapper.c
--- linux-2.4.25/fs/hfsplus/wrapper.c	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.26-pre6/fs/hfsplus/wrapper.c	2004-03-25 00:19:01.000000000 +0000
@@ -14,6 +14,7 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #include <linux/buffer_head.h>
 #endif
+#include <asm/unaligned.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
@@ -45,7 +46,7 @@ static int hfsplus_read_mdb(unsigned cha
 		return 0;
 	wd->ablk_start = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
 
-	extent = be32_to_cpu(*(u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT));
+	extent = be32_to_cpu(get_unaligned((u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
 	wd->embed_start = (extent >> 16) & 0xFFFF;
 	wd->embed_count = extent & 0xFFFF;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/jbd/journal.c linux-2.4.26-pre6/fs/jbd/journal.c
--- linux-2.4.25/fs/jbd/journal.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/jbd/journal.c	2004-03-25 00:17:57.000000000 +0000
@@ -671,6 +671,7 @@ struct journal_head * journal_get_descri
 
 	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
 	lock_buffer(bh);
+	memset(bh->b_data, 0, journal->j_blocksize);
 	BUFFER_TRACE(bh, "return this buffer");
 	return journal_add_journal_head(bh);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/jfs/jfs_logmgr.c linux-2.4.26-pre6/fs/jfs/jfs_logmgr.c
--- linux-2.4.25/fs/jfs/jfs_logmgr.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/jfs/jfs_logmgr.c	2004-03-25 00:22:24.000000000 +0000
@@ -1697,7 +1697,7 @@ static int lbmLogInit(struct jfs_log * l
 		if (lbuf == 0)
 			goto error;
 		lbuf->l_bh.b_data = lbuf->l_ldata =
-		    (char *) __get_free_page(GFP_KERNEL);
+		    (char *) get_zeroed_page(GFP_KERNEL);
 		if (lbuf->l_ldata == 0) {
 			kfree(lbuf);
 			goto error;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/jfs/jfs_metapage.c linux-2.4.26-pre6/fs/jfs/jfs_metapage.c
--- linux-2.4.25/fs/jfs/jfs_metapage.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/fs/jfs/jfs_metapage.c	2004-03-25 00:20:58.000000000 +0000
@@ -385,6 +385,10 @@ struct metapage *__get_metapage(struct i
 		}
 		mp->data = kmap(mp->page) + page_offset;
 	}
+
+	if (new)
+		memset(mp->data, 0, PSIZE);
+
 	jfs_info("__get_metapage: returning = 0x%p", mp);
 	return mp;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/jfs/super.c linux-2.4.26-pre6/fs/jfs/super.c
--- linux-2.4.25/fs/jfs/super.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/fs/jfs/super.c	2004-03-25 00:22:35.000000000 +0000
@@ -481,10 +481,10 @@ static void init_once(void *foo, kmem_ca
 
 	if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
+		memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
 		INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
 		init_rwsem(&jfs_ip->rdwrlock);
 		init_MUTEX(&jfs_ip->commit_sem);
-		jfs_ip->atlhead = 0;
 		jfs_ip->active_ag = -1;
 	}
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/lockd/svc4proc.c linux-2.4.26-pre6/fs/lockd/svc4proc.c
--- linux-2.4.25/fs/lockd/svc4proc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/fs/lockd/svc4proc.c	2004-03-25 00:19:03.000000000 +0000
@@ -471,7 +471,7 @@ nlm4svc_proc_granted_res(struct svc_rqst
 
         dprintk("lockd: GRANTED_RES   called\n");
 
-        nlmsvc_grant_reply(&argp->cookie, argp->status);
+        nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status);
         return rpc_success;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/lockd/svclock.c linux-2.4.26-pre6/fs/lockd/svclock.c
--- linux-2.4.25/fs/lockd/svclock.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/fs/lockd/svclock.c	2004-03-25 00:18:37.000000000 +0000
@@ -113,11 +113,11 @@ nlmsvc_lookup_block(struct nlm_file *fil
 				(long long)lock->fl.fl_end, lock->fl.fl_type);
 	for (head = &nlm_blocked; (block = *head); head = &block->b_next) {
 		fl = &block->b_call.a_args.lock.fl;
-		dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%x\n",
+		dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
 				block->b_file, fl->fl_pid,
 				(long long)fl->fl_start,
 				(long long)fl->fl_end, fl->fl_type,
-				*(unsigned int*)(block->b_call.a_args.cookie.data));
+				nlmdbg_cookie2a(&block->b_call.a_args.cookie));
 		if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
 			if (remove) {
 				*head = block->b_next;
@@ -143,14 +143,15 @@ static inline int nlm_cookie_match(struc
  * Find a block with a given NLM cookie.
  */
 static inline struct nlm_block *
-nlmsvc_find_block(struct nlm_cookie *cookie)
+nlmsvc_find_block(struct nlm_cookie *cookie,  struct sockaddr_in *sin)
 {
 	struct nlm_block *block;
 
 	for (block = nlm_blocked; block; block = block->b_next) {
 		dprintk("cookie: head of blocked queue %p, block %p\n", 
 			nlm_blocked, block);
-		if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie))
+		if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie)
+				&& nlm_cmp_addr(sin, &block->b_host->h_addr))
 			break;
 	}
 
@@ -579,12 +580,16 @@ nlmsvc_grant_callback(struct rpc_task *t
 	struct nlm_rqst		*call = (struct nlm_rqst *) task->tk_calldata;
 	struct nlm_block	*block;
 	unsigned long		timeout;
+	struct sockaddr_in	*peer_addr = RPC_PEERADDR(task->tk_client);
 
 	dprintk("lockd: GRANT_MSG RPC callback\n");
-	dprintk("callback: looking for cookie %x \n", 
-		*(unsigned int *)(call->a_args.cookie.data));
-	if (!(block = nlmsvc_find_block(&call->a_args.cookie))) {
-		dprintk("lockd: no block for cookie %x\n", *(u32 *)(call->a_args.cookie.data));
+	dprintk("callback: looking for cookie %s, host %u.%u.%u.%u\n", 
+		nlmdbg_cookie2a(&call->a_args.cookie),
+		NIPQUAD(peer_addr->sin_addr.s_addr));
+	if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
+		dprintk("lockd: no block for cookie %s, host %u.%u.%u.%u\n",
+				nlmdbg_cookie2a(&call->a_args.cookie),
+				NIPQUAD(peer_addr->sin_addr.s_addr));
 		return;
 	}
 
@@ -613,18 +618,21 @@ nlmsvc_grant_callback(struct rpc_task *t
  * block.
  */
 void
-nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
+nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status)
 {
 	struct nlm_block	*block;
 	struct nlm_file		*file;
 
-	if (!(block = nlmsvc_find_block(cookie)))
+	dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", 
+		*(unsigned int *)(cookie->data), 
+		ntohl(rqstp->rq_addr.sin_addr.s_addr), status);
+	if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
 		return;
 	file = block->b_file;
 
 	file->f_count++;
 	down(&file->f_sema);
-	if ((block = nlmsvc_find_block(cookie)) != NULL) {
+	if ((block = nlmsvc_find_block(cookie,&rqstp->rq_addr)) != NULL) {
 		if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
 			/* Try again in a couple of seconds */
 			nlmsvc_insert_block(block, 10 * HZ);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/lockd/svcproc.c linux-2.4.26-pre6/fs/lockd/svcproc.c
--- linux-2.4.25/fs/lockd/svcproc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/fs/lockd/svcproc.c	2004-03-25 00:20:48.000000000 +0000
@@ -499,7 +499,7 @@ nlmsvc_proc_granted_res(struct svc_rqst 
 
 	dprintk("lockd: GRANTED_RES   called\n");
 
-	nlmsvc_grant_reply(&argp->cookie, argp->status);
+	nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status);
 	return rpc_success;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/lockd/xdr.c linux-2.4.26-pre6/fs/lockd/xdr.c
--- linux-2.4.25/fs/lockd/xdr.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/fs/lockd/xdr.c	2004-03-25 00:17:22.000000000 +0000
@@ -55,7 +55,7 @@ static inline u32 *nlm_decode_cookie(u32
 		c->len=4;
 		memset(c->data, 0, 4);	/* hockeypux brain damage */
 	}
-	else if(len<=8)
+	else if(len<=NLM_MAXCOOKIELEN)
 	{
 		c->len=len;
 		memcpy(c->data, p, len);
@@ -64,7 +64,7 @@ static inline u32 *nlm_decode_cookie(u32
 	else 
 	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
+			"lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
 		return NULL;
 	}
 	return p;
@@ -86,7 +86,7 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f)
 
 	if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
 		printk(KERN_NOTICE
-			"lockd: bad fhandle size %x (should be %d)\n",
+			"lockd: bad fhandle size %d (should be %d)\n",
 			len, NFS2_FHSIZE);
 		return NULL;
 	}
@@ -534,7 +534,7 @@ nlmclt_decode_res(struct rpc_rqst *req, 
  * Buffer requirements for NLM
  */
 #define NLM_void_sz		0
-#define NLM_cookie_sz		3	/* 1 len , 2 data */
+#define NLM_cookie_sz		1+QUADLEN(NLM_MAXCOOKIELEN)
 #define NLM_caller_sz		1+QUADLEN(sizeof(system_utsname.nodename))
 #define NLM_netobj_sz		1+QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM_owner_sz		1+QUADLEN(NLM_MAXOWNER) */
@@ -643,3 +643,32 @@ nlm_procname(u32 proc)
 }
 #endif
 
+#ifdef RPC_DEBUG
+const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
+{
+	/*
+	 * We can get away with a static buffer because we're only
+	 * called with BKL held.
+	 */
+	static char buf[2*NLM_MAXCOOKIELEN+1];
+	int i;
+	int len = sizeof(buf);
+	char *p = buf;
+
+	len--;	/* allow for trailing \0 */
+	if (len < 3)
+		return "???";
+	for (i = 0 ; i < cookie->len ; i++) {
+		if (len < 2) {
+			strcpy(p-3, "...");
+			break;
+		}
+		sprintf(p, "%02x", cookie->data[i]);
+		p += 2;
+		len -= 2;
+	}
+	*p = '\0';
+
+	return buf;
+}
+#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/lockd/xdr4.c linux-2.4.26-pre6/fs/lockd/xdr4.c
--- linux-2.4.25/fs/lockd/xdr4.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/fs/lockd/xdr4.c	2004-03-25 00:17:07.000000000 +0000
@@ -56,7 +56,7 @@ nlm4_decode_cookie(u32 *p, struct nlm_co
 		c->len=4;
 		memset(c->data, 0, 4);	/* hockeypux brain damage */
 	}
-	else if(len<=8)
+	else if(len<=NLM_MAXCOOKIELEN)
 	{
 		c->len=len;
 		memcpy(c->data, p, len);
@@ -65,7 +65,7 @@ nlm4_decode_cookie(u32 *p, struct nlm_co
 	else 
 	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
+			"lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
 		return NULL;
 	}
 	return p;
@@ -540,7 +540,7 @@ nlm4clt_decode_res(struct rpc_rqst *req,
  * Buffer requirements for NLM
  */
 #define NLM4_void_sz		0
-#define NLM4_cookie_sz		3	/* 1 len , 2 data */
+#define NLM4_cookie_sz		1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
 #define NLM4_caller_sz		1+XDR_QUADLEN(NLM_MAXSTRLEN)
 #define NLM4_netobj_sz		1+XDR_QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM4_owner_sz		1+XDR_QUADLEN(NLM4_MAXOWNER) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/locks.c linux-2.4.26-pre6/fs/locks.c
--- linux-2.4.25/fs/locks.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/locks.c	2004-03-25 00:22:05.000000000 +0000
@@ -1740,7 +1740,14 @@ void locks_remove_posix(struct file *fil
 	before = &inode->i_flock;
 	while ((fl = *before) != NULL) {
 		if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) {
+			struct file *filp = fl->fl_file;
+			/* Note: locks_unlock_delete() can sleep, and
+			 * so we may race with the call to sys_close()
+			 * by the thread that actually owns this filp.
+			 */
+			get_file(filp);
 			locks_unlock_delete(before);
+			fput(filp);
 			before = &inode->i_flock;
 			continue;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/nfs/dir.c linux-2.4.26-pre6/fs/nfs/dir.c
--- linux-2.4.25/fs/nfs/dir.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/fs/nfs/dir.c	2004-03-25 00:19:53.000000000 +0000
@@ -545,6 +545,11 @@ static int nfs_dentry_delete(struct dent
 		/* Unhash it, so that ->d_iput() would be called */
 		return 1;
 	}
+	if (!(dentry->d_sb->s_flags & MS_ACTIVE)) {
+		/* Unhash it, so that ancestors of killed async unlink
+		 * files will be cleaned up during umount */
+		return 1;
+	}
 	return 0;
 
 }
@@ -1065,6 +1070,7 @@ go_ahead:
 
 	nfs_zap_caches(new_dir);
 	nfs_zap_caches(old_dir);
+	NFS_CACHEINV(old_inode);
 	error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
 					   new_dir, &new_dentry->d_name);
 out:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/nfs/file.c linux-2.4.26-pre6/fs/nfs/file.c
--- linux-2.4.25/fs/nfs/file.c	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.26-pre6/fs/nfs/file.c	2004-03-25 00:20:45.000000000 +0000
@@ -81,7 +81,7 @@ nfs_file_flush(struct file *file)
 	if (file->f_mode & FMODE_READ)
 		nfs_pagein_inode(inode, 0, 0);
 
-	status = nfs_wb_file(inode, file);
+	status = nfs_wb_all(inode);
 	if (!status) {
 		status = file->f_error;
 		file->f_error = 0;
@@ -136,7 +136,7 @@ nfs_fsync(struct file *file, struct dent
 	dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
 	lock_kernel();
-	status = nfs_wb_file(inode, file);
+	status = nfs_wb_all(inode);
 	if (!status) {
 		status = file->f_error;
 		file->f_error = 0;
@@ -241,6 +241,93 @@ out_swapfile:
 	goto out;
 }
 
+static int
+do_getlk(struct inode *inode, int cmd, struct file_lock *fl)
+{
+	int status;
+
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	unlock_kernel();
+	return status;
+}
+
+static int
+do_unlk(struct inode *inode, int cmd, struct file_lock *fl)
+{
+	sigset_t oldset;
+	int status;
+
+	rpc_clnt_sigmask(NFS_CLIENT(inode), &oldset);
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	filemap_fdatasync(inode->i_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);
+	up(&inode->i_sem);
+	filemap_fdatawait(inode->i_mapping);
+
+	/* NOTE: special case
+	 *	If we're signalled while cleaning up locks on process exit, we
+	 *	still need to complete the unlock.
+	 */
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	unlock_kernel();
+	rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
+	return status;
+}
+
+static int
+do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	int status;
+
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	status = filemap_fdatasync(inode->i_mapping);
+	if (status == 0) {
+		down(&inode->i_sem);
+		status = nfs_wb_all(inode);
+		up(&inode->i_sem);
+		if (status == 0)
+			status = filemap_fdatawait(inode->i_mapping);
+	}
+	if (status < 0)
+		return status;
+
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	/* If we were signalled we still need to ensure that
+	 * we clean up any state on the server. We therefore
+	 * record the lock call as having succeeded in order to
+	 * ensure that locks_remove_posix() cleans it out when
+	 * the process exits.
+	 */
+	if (status == -EINTR || status == -ERESTARTSYS)
+		posix_lock_file(filp, fl, 0);
+	unlock_kernel();
+	if (status < 0)
+		return status;
+
+	/*
+	 * Make sure we clear the cache whenever we try to get the lock.
+	 * This makes locking act as a cache coherency point.
+	 */
+	filemap_fdatasync(inode->i_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);      /* we may have slept */
+	up(&inode->i_sem);
+	filemap_fdatawait(inode->i_mapping);
+	nfs_zap_caches(inode);
+	return 0;
+}
+
 /*
  * Lock a (portion of) a file
  */
@@ -248,8 +335,6 @@ int
 nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
 	struct inode * inode = filp->f_dentry->d_inode;
-	int	status = 0;
-	int	status2;
 
 	dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
 			inode->i_dev, inode->i_ino,
@@ -266,8 +351,8 @@ nfs_lock(struct file *filp, int cmd, str
 	/* Fake OK code if mounted without NLM support */
 	if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) {
 		if (IS_GETLK(cmd))
-			status = LOCK_USE_CLNT;
-		goto out_ok;
+			return LOCK_USE_CLNT;
+		return 0;
 	}
 
 	/*
@@ -280,42 +365,9 @@ nfs_lock(struct file *filp, int cmd, str
 	if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX)
 		return -ENOLCK;
 
-	/*
-	 * Flush all pending writes before doing anything
-	 * with locks..
-	 */
-	status = filemap_fdatasync(inode->i_mapping);
-	down(&inode->i_sem);
-	status2 = nfs_wb_all(inode);
-	if (status2 && !status)
-		status = status2;
-	up(&inode->i_sem);
-	status2 = filemap_fdatawait(inode->i_mapping);
-	if (status2 && !status)
-		status = status2;
-	if (status < 0)
-		return status;
-
-	lock_kernel();
-	status = nlmclnt_proc(inode, cmd, fl);
-	unlock_kernel();
-	if (status < 0)
-		return status;
-	
-	status = 0;
-
-	/*
-	 * Make sure we clear the cache whenever we try to get the lock.
-	 * This makes locking act as a cache coherency point.
-	 */
- out_ok:
-	if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
-		filemap_fdatasync(inode->i_mapping);
-		down(&inode->i_sem);
-		nfs_wb_all(inode);      /* we may have slept */
-		up(&inode->i_sem);
-		filemap_fdatawait(inode->i_mapping);
-		nfs_zap_caches(inode);
-	}
-	return status;
+	if (IS_GETLK(cmd))
+		return do_getlk(inode, cmd, fl);
+	if (fl->fl_type == F_UNLCK)
+		return do_unlk(inode, cmd, fl);
+	return do_setlk(filp, cmd, fl);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/nfs/inode.c linux-2.4.26-pre6/fs/nfs/inode.c
--- linux-2.4.25/fs/nfs/inode.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/fs/nfs/inode.c	2004-03-25 00:21:19.000000000 +0000
@@ -121,7 +121,7 @@ nfs_write_inode(struct inode *inode, int
 {
 	int flags = sync ? FLUSH_WAIT : 0;
 
-	nfs_sync_file(inode, NULL, 0, 0, flags);
+	nfs_sync_file(inode, 0, 0, flags);
 }
 
 static void
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/nfs/pagelist.c linux-2.4.26-pre6/fs/nfs/pagelist.c
--- linux-2.4.25/fs/nfs/pagelist.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.26-pre6/fs/nfs/pagelist.c	2004-03-25 00:21:59.000000000 +0000
@@ -364,7 +364,6 @@ nfs_scan_lru_timeout(struct list_head *h
  * nfs_scan_list - Scan a list for matching requests
  * @head: One of the NFS inode request lists
  * @dst: Destination list
- * @file: if set, ensure we match requests from this file
  * @idx_start: lower bound of page->index to scan
  * @npages: idx_start + npages sets the upper bound to scan.
  *
@@ -376,7 +375,6 @@ nfs_scan_lru_timeout(struct list_head *h
  */
 int
 nfs_scan_list(struct list_head *head, struct list_head *dst,
-	      struct file *file,
 	      unsigned long idx_start, unsigned int npages)
 {
 	struct list_head	*pos, *tmp;
@@ -395,9 +393,6 @@ nfs_scan_list(struct list_head *head, st
 
 		req = nfs_list_entry(pos);
 
-		if (file && req->wb_file != file)
-			continue;
-
 		pg_idx = page_index(req->wb_page);
 		if (pg_idx < idx_start)
 			continue;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/nfs/read.c linux-2.4.26-pre6/fs/nfs/read.c
--- linux-2.4.25/fs/nfs/read.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.26-pre6/fs/nfs/read.c	2004-03-25 00:16:48.000000000 +0000
@@ -371,7 +371,7 @@ static int
 nfs_scan_read(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
 {
 	int	res;
-	res = nfs_scan_list(&inode->u.nfs_i.read, dst, NULL, idx_start, npages);
+	res = nfs_scan_list(&inode->u.nfs_i.read, dst, idx_start, npages);
 	inode->u.nfs_i.nread -= res;
 	if ((inode->u.nfs_i.nread == 0) != list_empty(&inode->u.nfs_i.read))
 		printk(KERN_ERR "NFS: desynchronized value of nfs_i.nread.\n");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/nfs/write.c linux-2.4.26-pre6/fs/nfs/write.c
--- linux-2.4.25/fs/nfs/write.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/fs/nfs/write.c	2004-03-25 00:21:11.000000000 +0000
@@ -445,7 +445,7 @@ nfs_mark_request_commit(struct nfs_page 
  * Interruptible by signals only if mounted with intr flag.
  */
 static int
-nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_start, unsigned int npages)
+nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages)
 {
 	struct list_head	*p, *head;
 	unsigned long		idx_end;
@@ -464,9 +464,6 @@ nfs_wait_on_requests(struct inode *inode
 		unsigned long pg_idx;
 		struct nfs_page *req = nfs_inode_wb_entry(p);
 
-		if (file && req->wb_file != file)
-			continue;
-
 		pg_idx = page_index(req->wb_page);
 		if (pg_idx < idx_start)
 			break;
@@ -538,7 +535,6 @@ nfs_scan_lru_dirty(struct nfs_server *se
  * nfs_scan_dirty - Scan an inode for dirty requests
  * @inode: NFS inode to scan
  * @dst: destination list
- * @file: if set, ensure we match requests from this file
  * @idx_start: lower bound of page->index to scan.
  * @npages: idx_start + npages sets the upper bound to scan.
  *
@@ -546,10 +542,10 @@ nfs_scan_lru_dirty(struct nfs_server *se
  * The requests are *not* checked to ensure that they form a contiguous set.
  */
 static int
-nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages)
+nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
 {
 	int	res;
-	res = nfs_scan_list(&inode->u.nfs_i.dirty, dst, file, idx_start, npages);
+	res = nfs_scan_list(&inode->u.nfs_i.dirty, dst, idx_start, npages);
 	inode->u.nfs_i.ndirty -= res;
 	if ((inode->u.nfs_i.ndirty == 0) != list_empty(&inode->u.nfs_i.dirty))
 		printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
@@ -577,7 +573,7 @@ nfs_scan_lru_commit_timeout(struct nfs_s
 	npages = nfs_scan_lru_timeout(&server->lru_commit, dst, 1);
 	if (npages) {
 		inode = nfs_list_entry(dst->next)->wb_inode;
-		npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, NULL, 0, 0);
+		npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, 0, 0);
 		inode->u.nfs_i.ncommit -= npages;
 	}
 	return npages;
@@ -604,7 +600,7 @@ nfs_scan_lru_commit(struct nfs_server *s
 	npages = nfs_scan_lru(&server->lru_commit, dst, 1);
 	if (npages) {
 		inode = nfs_list_entry(dst->next)->wb_inode;
-		npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, NULL, 0, 0);
+		npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, 0, 0);
 		inode->u.nfs_i.ncommit -= npages;
 	}
 	return npages;
@@ -614,7 +610,6 @@ nfs_scan_lru_commit(struct nfs_server *s
  * nfs_scan_commit - Scan an inode for commit requests
  * @inode: NFS inode to scan
  * @dst: destination list
- * @file: if set, ensure we collect requests from this file only.
  * @idx_start: lower bound of page->index to scan.
  * @npages: idx_start + npages sets the upper bound to scan.
  *
@@ -622,10 +617,10 @@ nfs_scan_lru_commit(struct nfs_server *s
  * The requests are *not* checked to ensure that they form a contiguous set.
  */
 static int
-nfs_scan_commit(struct inode *inode, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages)
+nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
 {
 	int	res;
-	res = nfs_scan_list(&inode->u.nfs_i.commit, dst, file, idx_start, npages);
+	res = nfs_scan_list(&inode->u.nfs_i.commit, dst, idx_start, npages);
 	inode->u.nfs_i.ncommit -= res;
 	if ((inode->u.nfs_i.ncommit == 0) != list_empty(&inode->u.nfs_i.commit))
 		printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
@@ -753,12 +748,12 @@ nfs_strategy(struct inode *inode)
 #ifdef CONFIG_NFS_V3
 	if (NFS_PROTO(inode)->version == 2) {
 		if (dirty >= NFS_STRATEGY_PAGES * wpages)
-			nfs_flush_file(inode, NULL, 0, 0, 0);
+			nfs_flush_file(inode, 0, 0, 0);
 	} else if (dirty >= wpages)
-		nfs_flush_file(inode, NULL, 0, 0, 0);
+		nfs_flush_file(inode, 0, 0, 0);
 #else
 	if (dirty >= NFS_STRATEGY_PAGES * wpages)
-		nfs_flush_file(inode, NULL, 0, 0, 0);
+		nfs_flush_file(inode, 0, 0, 0);
 #endif
 }
 
@@ -1250,7 +1245,7 @@ nfs_commit_done(struct rpc_task *task)
 }
 #endif
 
-int nfs_flush_file(struct inode *inode, struct file *file, unsigned long idx_start,
+int nfs_flush_file(struct inode *inode, unsigned long idx_start,
 		   unsigned int npages, int how)
 {
 	LIST_HEAD(head);
@@ -1258,7 +1253,7 @@ int nfs_flush_file(struct inode *inode, 
 				error = 0;
 
 	spin_lock(&nfs_wreq_lock);
-	res = nfs_scan_dirty(inode, &head, file, idx_start, npages);
+	res = nfs_scan_dirty(inode, &head, idx_start, npages);
 	spin_unlock(&nfs_wreq_lock);
 	if (res)
 		error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how);
@@ -1268,15 +1263,14 @@ int nfs_flush_file(struct inode *inode, 
 }
 
 #ifdef CONFIG_NFS_V3
-int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_start,
-		    unsigned int npages, int how)
+int nfs_commit_file(struct inode *inode, int how)
 {
 	LIST_HEAD(head);
 	int			res,
 				error = 0;
 
 	spin_lock(&nfs_wreq_lock);
-	res = nfs_scan_commit(inode, &head, file, idx_start, npages);
+	res = nfs_scan_commit(inode, &head, 0, 0);
 	spin_unlock(&nfs_wreq_lock);
 	if (res)
 		error = nfs_commit_list(&head, how);
@@ -1286,7 +1280,7 @@ int nfs_commit_file(struct inode *inode,
 }
 #endif
 
-int nfs_sync_file(struct inode *inode, struct file *file, unsigned long idx_start,
+int nfs_sync_file(struct inode *inode, unsigned long idx_start,
 		  unsigned int npages, int how)
 {
 	int	error,
@@ -1295,18 +1289,15 @@ int nfs_sync_file(struct inode *inode, s
 	wait = how & FLUSH_WAIT;
 	how &= ~FLUSH_WAIT;
 
-	if (!inode && file)
-		inode = file->f_dentry->d_inode;
-
 	do {
 		error = 0;
 		if (wait)
-			error = nfs_wait_on_requests(inode, file, idx_start, npages);
+			error = nfs_wait_on_requests(inode, idx_start, npages);
 		if (error == 0)
-			error = nfs_flush_file(inode, file, idx_start, npages, how);
+			error = nfs_flush_file(inode, idx_start, npages, how);
 #ifdef CONFIG_NFS_V3
 		if (error == 0)
-			error = nfs_commit_file(inode, file, idx_start, npages, how);
+			error = nfs_commit_file(inode, how);
 #endif
 	} while (error > 0);
 	return error;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/Makefile linux-2.4.26-pre6/fs/xfs/Makefile
--- linux-2.4.25/fs/xfs/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/Makefile	2004-03-25 00:18:20.000000000 +0000
@@ -108,7 +108,9 @@ obj-y				+= xfs_alloc.o \
 				   xfs_vfsops.o \
 				   xfs_vnodeops.o \
 				   xfs_refcache.o \
-				   xfs_rw.o
+				   xfs_rw.o \
+				   xfs_dmops.o \
+				   xfs_qmops.o
 
 # Objects not built in this directory
 obj-y				+= linux/linux_xfs.o \
@@ -119,15 +121,11 @@ subdir-$(CONFIG_XFS_FS)		+= linux suppor
 ifeq ($(CONFIG_XFS_DMAPI),y)
   subdir-$(CONFIG_XFS_FS)	+= dmapi
   obj-y				+= dmapi/xfs_dmapi.o
-else
-  obj-y				+= xfs_dmops.o
 endif
 
 ifeq ($(CONFIG_XFS_QUOTA),y)
   subdir-$(CONFIG_XFS_FS)	+= quota
   obj-y				+= quota/xfs_quota.o
-else
-  obj-y				+= xfs_qmops.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/kmem.h linux-2.4.26-pre6/fs/xfs/linux/kmem.h
--- linux-2.4.25/fs/xfs/linux/kmem.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/kmem.h	2004-03-25 00:21:13.000000000 +0000
@@ -59,6 +59,12 @@ typedef unsigned long xfs_pflags_t;
         current->flags |= PF_FSTRANS;   \
 } while (0)
 
+#define PFLAGS_CLEAR_FSTRANS(STATEP) do { \
+	*(STATEP) = current->flags;	\
+	current->flags &= ~PF_FSTRANS;	\
+} while (0)
+
+
 #define PFLAGS_RESTORE(STATEP) do {     \
 	current->flags = *(STATEP);     \
 } while (0)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_aops.c linux-2.4.26-pre6/fs/xfs/linux/xfs_aops.c
--- linux-2.4.25/fs/xfs/linux/xfs_aops.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_aops.c	2004-03-25 00:22:17.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -54,8 +54,54 @@
 #include "xfs_iomap.h"
 #include <linux/iobuf.h>
 
-STATIC void convert_page(struct inode *, struct page *,
-			xfs_iomap_t *, void *, int, int);
+STATIC void xfs_count_page_state(struct page *, int *, int *, int *);
+STATIC void xfs_convert_page(struct inode *, struct page *,
+				xfs_iomap_t *, void *, int, int);
+
+#if defined(XFS_RW_TRACE)
+void
+xfs_page_trace(
+	int		tag,
+	struct inode	*inode,
+	struct page	*page,
+	int		mask)
+{
+	xfs_inode_t	*ip;
+	bhv_desc_t	*bdp;
+	vnode_t		*vp = LINVFS_GET_VP(inode);
+	loff_t		isize = i_size_read(inode);
+	loff_t		offset = page->index << PAGE_CACHE_SHIFT;
+	int		delalloc = -1, unmapped = -1, unwritten = -1;
+
+	if (page_has_buffers(page))
+		xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
+
+	bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
+	ip = XFS_BHVTOI(bdp);
+	if (!ip->i_rwtrace)
+		return;
+
+	ktrace_enter(ip->i_rwtrace,
+		(void *)((unsigned long)tag),
+		(void *)ip,
+		(void *)inode,
+		(void *)page,
+		(void *)((unsigned long)mask),
+		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
+		(void *)((unsigned long)((isize >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(isize & 0xffffffff)),
+		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(offset & 0xffffffff)),
+		(void *)((unsigned long)delalloc),
+		(void *)((unsigned long)unmapped),
+		(void *)((unsigned long)unwritten),
+		(void *)NULL,
+		(void *)NULL);
+}
+#else
+#define xfs_page_trace(tag, inode, page, mask)
+#endif
 
 void
 linvfs_unwritten_done(
@@ -97,7 +143,7 @@ linvfs_unwritten_convert(
 }
 
 STATIC int
-map_blocks(
+xfs_map_blocks(
 	struct inode		*inode,
 	loff_t			offset,
 	ssize_t			count,
@@ -127,12 +173,11 @@ retry:
 }
 
 /*
- * match_offset_to_mapping
  * Finds the corresponding mapping in block @map array of the
  * given @offset within a @page.
  */
 STATIC xfs_iomap_t *
-match_offset_to_mapping(
+xfs_offset_to_map(
 	struct page		*page,
 	xfs_iomap_t		*iomapp,
 	unsigned long		offset)
@@ -153,7 +198,7 @@ match_offset_to_mapping(
 }
 
 STATIC void
-map_buffer_at_offset(
+xfs_map_at_offset(
 	struct page		*page,
 	struct buffer_head	*bh,
 	unsigned long		offset,
@@ -194,7 +239,7 @@ map_buffer_at_offset(
  * in units of filesystem blocks.
  */
 STATIC struct page *
-probe_unwritten_page(
+xfs_probe_unwritten_page(
 	struct address_space	*mapping,
 	unsigned long		index,
 	xfs_iomap_t		*iomapp,
@@ -218,11 +263,11 @@ probe_unwritten_page(
 		do {
 			if (!buffer_unwritten(bh))
 				break;
-			if (!match_offset_to_mapping(page, iomapp, p_offset))
+			if (!xfs_offset_to_map(page, iomapp, p_offset))
 				break;
 			if (p_offset >= max_offset)
 				break;
-			map_buffer_at_offset(page, bh, p_offset, bbits, iomapp);
+			xfs_map_at_offset(page, bh, p_offset, bbits, iomapp);
 			set_buffer_unwritten_io(bh);
 			bh->b_private = pb;
 			p_offset += bh->b_size;
@@ -242,7 +287,7 @@ probe_unwritten_page(
  * yet - clustering for mmap write case.
  */
 STATIC unsigned int
-probe_unmapped_page(
+xfs_probe_unmapped_page(
 	struct address_space	*mapping,
 	unsigned long		index,
 	unsigned int		pg_offset)
@@ -275,7 +320,7 @@ probe_unmapped_page(
 }
 
 STATIC unsigned int
-probe_unmapped_cluster(
+xfs_probe_unmapped_cluster(
 	struct inode		*inode,
 	struct page		*startpage,
 	struct buffer_head	*bh,
@@ -300,7 +345,7 @@ probe_unmapped_cluster(
 		/* Prune this back to avoid pathological behavior */
 		tloff = min(tlast, startpage->index + 64);
 		for (tindex = startpage->index + 1; tindex < tloff; tindex++) {
-			len = probe_unmapped_page(mapping, tindex,
+			len = xfs_probe_unmapped_page(mapping, tindex,
 							PAGE_CACHE_SIZE);
 			if (!len)
 				return total;
@@ -308,7 +353,8 @@ probe_unmapped_cluster(
 		}
 		if (tindex == tlast &&
 		    (tloff = i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) {
-			total += probe_unmapped_page(mapping, tindex, tloff);
+			total += xfs_probe_unmapped_page(mapping,
+							tindex, tloff);
 		}
 	}
 	return total;
@@ -320,7 +366,7 @@ probe_unmapped_cluster(
  * reference count.
  */
 STATIC struct page *
-probe_delalloc_page(
+xfs_probe_delalloc_page(
 	struct inode		*inode,
 	unsigned long		index)
 {
@@ -353,7 +399,7 @@ probe_delalloc_page(
 }
 
 STATIC int
-map_unwritten(
+xfs_map_unwritten(
 	struct inode		*inode,
 	struct page		*start_page,
 	struct buffer_head	*head,
@@ -401,22 +447,16 @@ map_unwritten(
 	do {
 		if (!buffer_unwritten(bh))
 			break;
-		tmp = match_offset_to_mapping(start_page, iomapp, p_offset);
+		tmp = xfs_offset_to_map(start_page, iomapp, p_offset);
 		if (!tmp)
 			break;
-		map_buffer_at_offset(start_page, bh, p_offset, block_bits, iomapp);
+		xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp);
 		set_buffer_unwritten_io(bh);
 		bh->b_private = pb;
 		p_offset += bh->b_size;
 		nblocks++;
 	} while ((bh = bh->b_this_page) != head);
 
-	if (unlikely(nblocks == 0)) {
-		printk("XFS: bad unwritten extent map: bh=0x%p, iomapp=0x%p\n",
-		       curr, iomapp);
-		BUG();
-	}
-
 	atomic_add(nblocks, &pb->pb_io_remaining);
 
 	/* If we reached the end of the page, map forwards in any
@@ -432,13 +472,15 @@ map_unwritten(
 		tloff = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
 		tloff = min(tlast, tloff);
 		for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
-			page = probe_unwritten_page(mapping, tindex, iomapp, pb,
+			page = xfs_probe_unwritten_page(mapping,
+						tindex, iomapp, pb,
 						PAGE_CACHE_SIZE, &bs, bbits);
 			if (!page)
 				break;
 			nblocks += bs;
 			atomic_add(bs, &pb->pb_io_remaining);
-			convert_page(inode, page, iomapp, pb, startio, all_bh);
+			xfs_convert_page(inode, page, iomapp, pb,
+							startio, all_bh);
 			/* stop if converting the next page might add
 			 * enough blocks that the corresponding byte
 			 * count won't fit in our ulong page buf length */
@@ -448,12 +490,14 @@ map_unwritten(
 
 		if (tindex == tlast &&
 		    (tloff = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) {
-			page = probe_unwritten_page(mapping, tindex, iomapp, pb,
+			page = xfs_probe_unwritten_page(mapping,
+							tindex, iomapp, pb,
 							tloff, &bs, bbits);
 			if (page) {
 				nblocks += bs;
 				atomic_add(bs, &pb->pb_io_remaining);
-				convert_page(inode, page, iomapp, pb, startio, all_bh);
+				xfs_convert_page(inode, page, iomapp, pb,
+							startio, all_bh);
 				if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits))
 					goto enough;
 			}
@@ -480,7 +524,7 @@ enough:
 }
 
 STATIC void
-submit_page(
+xfs_submit_page(
 	struct page		*page,
 	struct buffer_head	*bh_arr[],
 	int			cnt)
@@ -511,7 +555,7 @@ submit_page(
  * that the page has no mapping at all.
  */
 STATIC void
-convert_page(
+xfs_convert_page(
 	struct inode		*inode,
 	struct page		*page,
 	xfs_iomap_t		*iomapp,
@@ -544,7 +588,7 @@ convert_page(
 			}
 			continue;
 		}
-		tmp = match_offset_to_mapping(page, mp, offset);
+		tmp = xfs_offset_to_map(page, mp, offset);
 		if (!tmp)
 			continue;
 		ASSERT(!(tmp->iomap_flags & IOMAP_HOLE));
@@ -556,10 +600,10 @@ convert_page(
 		 */
 		if (buffer_unwritten(bh) && !bh->b_end_io) {
 			ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN);
-			map_unwritten(inode, page, head, bh,
+			xfs_map_unwritten(inode, page, head, bh,
 					offset, bbits, tmp, startio, all_bh);
 		} else if (! (buffer_unwritten(bh) && buffer_locked(bh))) {
-			map_buffer_at_offset(page, bh, offset, bbits, tmp);
+			xfs_map_at_offset(page, bh, offset, bbits, tmp);
 			if (buffer_unwritten(bh)) {
 				set_buffer_unwritten_io(bh);
 				bh->b_private = private;
@@ -575,7 +619,7 @@ convert_page(
 	} while (i++, (bh = bh->b_this_page) != head);
 
 	if (startio) {
-		submit_page(page, bh_arr, index);
+		xfs_submit_page(page, bh_arr, index);
 	} else {
 		unlock_page(page);
 	}
@@ -586,7 +630,7 @@ convert_page(
  * by mp and following the start page.
  */
 STATIC void
-cluster_write(
+xfs_cluster_write(
 	struct inode		*inode,
 	unsigned long		tindex,
 	xfs_iomap_t		*iomapp,
@@ -598,10 +642,10 @@ cluster_write(
 
 	tlast = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
 	for (; tindex < tlast; tindex++) {
-		page = probe_delalloc_page(inode, tindex);
+		page = xfs_probe_delalloc_page(inode, tindex);
 		if (!page)
 			break;
-		convert_page(inode, page, iomapp, NULL, startio, all_bh);
+		xfs_convert_page(inode, page, iomapp, NULL, startio, all_bh);
 	}
 }
 
@@ -625,7 +669,7 @@ cluster_write(
  */
 
 STATIC int
-page_state_convert(
+xfs_page_state_convert(
 	struct inode	*inode,
 	struct page	*page,
 	int		startio,
@@ -668,7 +712,7 @@ page_state_convert(
 			continue;
 
 		if (iomp) {
-			iomp = match_offset_to_mapping(page, &iomap, p_offset);
+			iomp = xfs_offset_to_map(page, &iomap, p_offset);
 		}
 
 		/*
@@ -677,17 +721,17 @@ page_state_convert(
 		 */
 		if (buffer_unwritten(bh)) {
 			if (!iomp) {
-				err = map_blocks(inode, offset, len, &iomap,
+				err = xfs_map_blocks(inode, offset, len, &iomap,
 						BMAPI_READ|BMAPI_IGNSTATE);
 				if (err) {
 					goto error;
 				}
-				iomp = match_offset_to_mapping(page, &iomap,
+				iomp = xfs_offset_to_map(page, &iomap,
 								p_offset);
 			}
-			if (iomp) {
+			if (iomp && startio) {
 				if (!bh->b_end_io) {
-					err = map_unwritten(inode, page,
+					err = xfs_map_unwritten(inode, page,
 							head, bh, p_offset,
 							inode->i_blkbits, iomp,
 							startio, unmapped);
@@ -695,12 +739,7 @@ page_state_convert(
 						goto error;
 					}
 				}
-				if (startio) {
-					bh_arr[cnt++] = bh;
-				} else {
-					unlock_buffer(bh);
-					mark_buffer_dirty(bh);
-				}
+				bh_arr[cnt++] = bh;
 				page_dirty = 0;
 			}
 		/*
@@ -709,17 +748,17 @@ page_state_convert(
 		 */
 		} else if (buffer_delay(bh)) {
 			if (!iomp) {
-				err = map_blocks(inode, offset, len, &iomap,
-					BMAPI_ALLOCATE | flags);
+				err = xfs_map_blocks(inode, offset, len, &iomap,
+						BMAPI_ALLOCATE | flags);
 				if (err) {
 					goto error;
 				}
-				iomp = match_offset_to_mapping(page, &iomap,
+				iomp = xfs_offset_to_map(page, &iomap,
 								p_offset);
 			}
 			if (iomp) {
-				map_buffer_at_offset(page, bh, p_offset,
-					inode->i_blkbits, iomp);
+				xfs_map_at_offset(page, bh, p_offset,
+						inode->i_blkbits, iomp);
 				if (startio) {
 					bh_arr[cnt++] = bh;
 				} else {
@@ -740,19 +779,19 @@ page_state_convert(
 				 * need to write the whole page out.
 				 */
 				if (!iomp) {
-					size = probe_unmapped_cluster(
+					size = xfs_probe_unmapped_cluster(
 							inode, page, bh, head);
-					err = map_blocks(inode, offset,
-						size, &iomap,
-						BMAPI_WRITE | BMAPI_MMAP);
+					err = xfs_map_blocks(inode, offset,
+							size, &iomap,
+							BMAPI_WRITE|BMAPI_MMAP);
 					if (err) {
 						goto error;
 					}
-					iomp = match_offset_to_mapping(page, &iomap,
+					iomp = xfs_offset_to_map(page, &iomap,
 								     p_offset);
 				}
 				if (iomp) {
-					map_buffer_at_offset(page,
+					xfs_map_at_offset(page,
 							bh, p_offset,
 							inode->i_blkbits, iomp);
 					if (startio) {
@@ -778,10 +817,10 @@ page_state_convert(
 		SetPageUptodate(page);
 
 	if (startio)
-		submit_page(page, bh_arr, cnt);
+		xfs_submit_page(page, bh_arr, cnt);
 
 	if (iomp)
-		cluster_write(inode, page->index + 1, iomp, startio, unmapped);
+		xfs_cluster_write(inode, page->index + 1, iomp, startio, unmapped);
 
 	return page_dirty;
 
@@ -841,9 +880,9 @@ linvfs_get_block_core(
 		loff_t			delta;
 
 		/* For unwritten extents do not report a disk address on
-		 * the read case.
+		 * the read case (treat as if we're reading into a hole).
 		 */
-		if (create || ((iomap.iomap_flags & IOMAP_UNWRITTEN) == 0)) {
+		if (create || !(iomap.iomap_flags & IOMAP_UNWRITTEN)) {
 			delta = offset - iomap.iomap_offset;
 			delta >>= inode->i_blkbits;
 
@@ -853,10 +892,7 @@ linvfs_get_block_core(
 			bh_result->b_blocknr = bn;
 			set_buffer_mapped(bh_result);
 		}
-		if (iomap.iomap_flags & IOMAP_UNWRITTEN) {
-			if (create) {
-				set_buffer_mapped(bh_result);
-			}
+		if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
 			set_buffer_unwritten(bh_result);
 			set_buffer_delay(bh_result);
 		}
@@ -946,7 +982,7 @@ linvfs_readpage(
 }
 
 STATIC void
-count_page_state(
+xfs_count_page_state(
 	struct page		*page,
 	int			*delalloc,
 	int			*unmapped,
@@ -998,13 +1034,15 @@ linvfs_writepage(
 	int			need_trans;
 	int			delalloc, unmapped, unwritten;
 	struct inode		*inode = page->mapping->host;
-        xfs_pflags_t            pflags;
+	xfs_pflags_t		pflags;
+
+	xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0);
 
 	/*
 	 * We need a transaction if:
 	 *  1. There are delalloc buffers on the page
-	 *  2. The page is upto date and we have unmapped buffers
-	 *  3. The page is upto date and we have no buffers
+	 *  2. The page is uptodate and we have unmapped buffers
+	 *  3. The page is uptodate and we have no buffers
 	 *  4. There are unwritten buffers on the page
 	 */
 
@@ -1012,7 +1050,7 @@ linvfs_writepage(
 		unmapped = 1;
 		need_trans = 1;
 	} else {
-		count_page_state(page, &delalloc, &unmapped, &unwritten);
+		xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
 		if (!PageUptodate(page))
 			unmapped = 0;
 		need_trans = delalloc + unmapped + unwritten;
@@ -1041,7 +1079,7 @@ linvfs_writepage(
 	 */
 	if (need_trans)
 		PFLAGS_SET_NOIO(&pflags);
-	error = page_state_convert(inode, page, 1, unmapped);
+	error = xfs_page_state_convert(inode, page, 1, unmapped);
 	if (need_trans)
 		PFLAGS_RESTORE(&pflags);
 	if (error == -EAGAIN)
@@ -1085,22 +1123,31 @@ linvfs_release_page(
 	int			gfp_mask)
 {
 	struct inode		*inode = page->mapping->host;
-	int			delalloc, unmapped, unwritten;
+	int			dirty, delalloc, unmapped, unwritten;
+
+	xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask);
 
-	count_page_state(page, &delalloc, &unmapped, &unwritten);
+	xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
 	if (!delalloc && !unwritten)
 		return 1;
 
 	if (!(gfp_mask & __GFP_FS))
 		return 0;
 
+	/* If we are already inside a transaction or the thread cannot
+	 * do I/O, we cannot release this page.
+	 */
+	if (PFLAGS_TEST_FSTRANS() || PFLAGS_TEST_NOIO())
+		return 0;
+
 	/*
 	 * Convert delalloc space to real space, do not flush the
 	 * data out to disk, that will be done by the caller.
 	 * Never need to allocate space here - we will always
 	 * come back to writepage in that case.
 	 */
-	return (page_state_convert(inode, page, 0, 0) == 0) ? 1 : 0;
+	dirty = xfs_page_state_convert(inode, page, 0, 0);
+	return (dirty == 0 && !unwritten) ? 1 : 0;
 }
 
 STATIC int
@@ -1155,7 +1202,7 @@ linvfs_direct_IO(
 	map_flags = (rw ? BMAPI_WRITE : BMAPI_READ) | BMAPI_DIRECT;
 	pb_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIO | PBF_DIRECTIO;
 	while (length) {
-		error = map_blocks(inode, offset, length, &iomap, map_flags);
+		error = xfs_map_blocks(inode, offset, length, &iomap, map_flags);
 		if (error)
 			break;
 		BUG_ON(iomap.iomap_flags & IOMAP_DELAY);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_buf.c linux-2.4.26-pre6/fs/xfs/linux/xfs_buf.c
--- linux-2.4.25/fs/xfs/linux/xfs_buf.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_buf.c	2004-03-25 00:17:50.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -56,18 +56,8 @@
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
 
-#include <support/ktrace.h>
-#include <support/debug.h>
-#include "kmem.h"
-
-#include "xfs_types.h"
-#include "xfs_cred.h"
-#include "xfs_lrw.h"
-#include "xfs_buf.h"
-
-#define NBBY		8
-#define BBSHIFT		9
-#define BBMASK		((1 << BBSHIFT) - 1)
+#include "xfs_linux.h"
+
 #define BN_ALIGN_MASK	((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
 
 #ifndef GFP_READAHEAD
@@ -128,63 +118,12 @@ static spinlock_t		pb_resv_bh_lock = SPI
 struct buffer_head		*pb_resv_bh = NULL;	/* list of bh */
 int				pb_resv_bh_cnt = 0;	/* # of bh available */
 
-STATIC void pagebuf_daemon_wakeup(int);
+STATIC void pagebuf_daemon_wakeup(void);
 STATIC void _pagebuf_ioapply(page_buf_t *);
 STATIC void pagebuf_delwri_queue(page_buf_t *, int);
 STATIC void pagebuf_runall_queues(struct list_head[]);
 
 /*
- * Pagebuf module configuration parameters, exported via
- * /proc/sys/vm/pagebuf
- */
-
-typedef struct pb_sysctl_val {
-	int	min;
-	int	val;
-	int	max;
-} pb_sysctl_val_t;
-
-struct {
-	pb_sysctl_val_t	flush_interval;	/* interval between runs of the
-					 * delwri flush daemon.  */
-	pb_sysctl_val_t	age_buffer;	/* time for buffer to age before
-					 * we flush it.  */
-	pb_sysctl_val_t	stats_clear;	/* clear the pagebuf stats */
-	pb_sysctl_val_t	debug;		/* debug tracing on or off */
-} pb_params = {
-			  /*	MIN	DFLT	MAX	*/
-	.flush_interval	= {	HZ/2,	HZ,	30*HZ	},
-	.age_buffer	= {	1*HZ,	15*HZ,	300*HZ	},
-	.stats_clear	= {	0,	0,	1	},
-	.debug		= {	0,	0,	1	},
-};
-
-enum {
-	PB_FLUSH_INT = 1,
-	PB_FLUSH_AGE = 2,
-	PB_STATS_CLEAR = 3,
-	PB_DEBUG = 4,
-};
-
-/*
- * Pagebuf statistics variables
- */
-
-struct {
-	u_int32_t	pb_get;
-	u_int32_t	pb_create;
-	u_int32_t	pb_get_locked;
-	u_int32_t	pb_get_locked_waited;
-	u_int32_t	pb_busy_locked;
-	u_int32_t	pb_miss_locked;
-	u_int32_t	pb_page_retries;
-	u_int32_t	pb_page_found;
-	u_int32_t	pb_get_read;
-} pbstats;
-
-#define PB_STATS_INC(count)	( pbstats.count++ )
-
-/*
  * Pagebuf debugging
  */
 
@@ -196,8 +135,6 @@ pagebuf_trace(
 	void		*data,
 	void		*ra)
 {
-	if (!pb_params.debug.val)
-		return;
 	ktrace_enter(pagebuf_trace_buf,
 		pb, id,
 		(void *)(unsigned long)pb->pb_flags,
@@ -254,7 +191,6 @@ ktrace_t *pagebuf_trace_buf;
 
 typedef struct {
 	struct list_head	pb_hash;
-	int			pb_count;
 	spinlock_t		pb_hash_lock;
 } pb_hash_t;
 
@@ -372,7 +308,7 @@ _pagebuf_initialize(
 	atomic_set(&pb->pb_pin_count, 0);
 	init_waitqueue_head(&pb->pb_waiters);
 
-	PB_STATS_INC(pb_create);
+	XFS_STATS_INC(pb_create);
 	PB_TRACE(pb, "initialize", target);
 }
 
@@ -386,8 +322,6 @@ _pagebuf_get_pages(
 	int			page_count,
 	page_buf_flags_t	flags)
 {
-	int			gpf_mask = pb_to_gfp(flags);
-
 	/* Make sure that we have a page list */
 	if (pb->pb_pages == NULL) {
 		pb->pb_offset = page_buf_poff(pb->pb_file_offset);
@@ -395,8 +329,8 @@ _pagebuf_get_pages(
 		if (page_count <= PB_PAGES) {
 			pb->pb_pages = pb->pb_page_array;
 		} else {
-			pb->pb_pages = kmalloc(sizeof(struct page *) *
-					page_count, gpf_mask);
+			pb->pb_pages = kmem_alloc(sizeof(struct page *) *
+					page_count, pb_to_km(flags));
 			if (pb->pb_pages == NULL)
 				return -ENOMEM;
 		}
@@ -425,53 +359,41 @@ _pagebuf_freepages(
 }
 
 /*
- *	_pagebuf_free_object
+ *	pagebuf_free
  *
- *	_pagebuf_free_object releases the contents specified buffer.
- *	The modification state of any associated pages is left unchanged.
+ *	pagebuf_free releases the specified buffer.  The modification
+ *	state of any associated pages is left unchanged.
  */
 void
-_pagebuf_free_object(
-	pb_hash_t		*hash,	/* hash bucket for buffer */
-	page_buf_t		*pb)	/* buffer to deallocate	*/
-{
-	page_buf_flags_t	pb_flags = pb->pb_flags;
-
-	PB_TRACE(pb, "free_object", 0);
-	pb->pb_flags |= PBF_FREED;
-
-	if (hash) {
-		if (!list_empty(&pb->pb_hash_list)) {
-			hash->pb_count--;
-			list_del_init(&pb->pb_hash_list);
-		}
-		spin_unlock(&hash->pb_hash_lock);
-	}
+pagebuf_free(
+	page_buf_t		*pb)
+{
+	PB_TRACE(pb, "free", 0);
+	
+	ASSERT(list_empty(&pb->pb_hash_list));
 
-	if (!(pb_flags & PBF_FREED)) {
-		/* release any virtual mapping */ ;
-		if (pb->pb_flags & _PBF_ADDR_ALLOCATED) {
-			void *vaddr = pagebuf_mapout_locked(pb);
-			if (vaddr) {
-				free_address(vaddr);
-			}
+	/* release any virtual mapping */ ;
+	if (pb->pb_flags & _PBF_ADDR_ALLOCATED) {
+		void *vaddr = pagebuf_mapout_locked(pb);
+		if (vaddr) {
+			free_address(vaddr);
 		}
+	}
 
-		if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
-			if (pb->pb_pages) {
-				/* release the pages in the address list */
-				if ((pb->pb_pages[0]) &&
-				    (pb->pb_flags & _PBF_MEM_SLAB)) {
-					kfree(pb->pb_addr);
-				} else {
-					_pagebuf_freepages(pb);
-				}
-				if (pb->pb_pages != pb->pb_page_array)
-					kfree(pb->pb_pages);
-				pb->pb_pages = NULL;
+	if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
+		if (pb->pb_pages) {
+			/* release the pages in the address list */
+			if ((pb->pb_pages[0]) &&
+			    (pb->pb_flags & _PBF_MEM_SLAB)) {
+				kfree(pb->pb_addr);
+			} else {
+				_pagebuf_freepages(pb);
 			}
-			pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
+			if (pb->pb_pages != pb->pb_page_array)
+				kfree(pb->pb_pages);
+			pb->pb_pages = NULL;
 		}
+		pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
 	}
 
 	pagebuf_deallocate(pb);
@@ -496,32 +418,11 @@ _pagebuf_lookup_pages(
 	loff_t			next_buffer_offset;
 	unsigned long		page_count, pi, index;
 	struct page		*page;
-	int			gfp_mask, retry_count = 5, rval = 0;
-	int			all_mapped, good_pages;
+	int			gfp_mask = pb_to_gfp(flags);
+	int			all_mapped, good_pages, rval, retries;
 	size_t			blocksize;
 
-	/* For pagebufs where we want to map an address, do not use
-	 * highmem pages - so that we do not need to use kmap resources
-	 * to access the data.
-	 *
-	 * For pages where the caller has indicated there may be resource
-	 * contention (e.g. called from a transaction) do not flush
-	 * delalloc pages to obtain memory.
-	 */
-
-	if (flags & PBF_READ_AHEAD) {
-		gfp_mask = GFP_READAHEAD;
-		retry_count = 0;
-	} else if (flags & PBF_DONT_BLOCK) {
-		gfp_mask = GFP_NOFS;
-	} else if (flags & PBF_MAPPABLE) {
-		gfp_mask = GFP_KERNEL;
-	} else {
-		gfp_mask = GFP_HIGHUSER;
-	}
-
 	next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length;
-
 	good_pages = page_count = (page_buf_btoc(next_buffer_offset) -
 				   page_buf_btoct(pb->pb_file_offset));
 
@@ -532,6 +433,7 @@ _pagebuf_lookup_pages(
 		}
 		if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) {
 			all_mapped = 1;
+			rval = 0;
 			goto mapit;
 		}
 		return 0;
@@ -549,21 +451,30 @@ _pagebuf_lookup_pages(
 	index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT;
 	for (pi = 0; pi < page_count; pi++, index++) {
 		if (pb->pb_pages[pi] == 0) {
+			retries = 0;
 		      retry:
 			page = find_or_create_page(aspace, index, gfp_mask);
 			if (!page) {
-				if (--retry_count > 0) {
-					PB_STATS_INC(pb_page_retries);
-					pagebuf_daemon_wakeup(1);
-					current->state = TASK_UNINTERRUPTIBLE;
-					schedule_timeout(10);
-					goto retry;
+				if (flags & PBF_READ_AHEAD)
+					return -ENOMEM;
+				/*
+				 * This could deadlock.  But until all the
+				 * XFS lowlevel code is revamped to handle
+				 * buffer allocation failures we can't do
+				 * much.
+				 */
+				if (!(++retries % 100)) {
+					printk(KERN_ERR
+					       "possibly deadlocking in %s\n",
+					       __FUNCTION__);
 				}
-				rval = -ENOMEM;
-				all_mapped = 0;
-				continue;
+				XFS_STATS_INC(pb_page_retries);
+				pagebuf_daemon_wakeup();
+				current->state = TASK_UNINTERRUPTIBLE;
+				schedule_timeout(10);
+				goto retry;
 			}
-			PB_STATS_INC(pb_page_found);
+			XFS_STATS_INC(pb_page_found);
 			mark_page_accessed(page);
 			pb->pb_pages[pi] = page;
 		} else {
@@ -587,6 +498,7 @@ _pagebuf_lookup_pages(
 		}
 	}
 
+	pb->pb_flags |= _PBF_PAGECACHE;
 mapit:
 	pb->pb_flags |= _PBF_MEM_ALLOCATED;
 	if (all_mapped) {
@@ -780,16 +692,14 @@ _pagebuf_find(				/* find buffer for blo
 	list_for_each(p, &h->pb_hash) {
 		pb = list_entry(p, page_buf_t, pb_hash_list);
 
-		if ((target == pb->pb_target) &&
-		    (pb->pb_file_offset == range_base) &&
-		    (pb->pb_buffer_length == range_length)) {
-			if (pb->pb_flags & PBF_FREED)
-				break;
+		if (pb->pb_target == target &&
+		    pb->pb_file_offset == range_base &&
+		    pb->pb_buffer_length == range_length) {
 			/* If we look at something bring it to the
 			 * front of the list for next time
 			 */
-			list_del(&pb->pb_hash_list);
-			list_add(&pb->pb_hash_list, &h->pb_hash);
+			atomic_inc(&pb->pb_hold);
+			list_move(&pb->pb_hash_list, &h->pb_hash);
 			goto found;
 		}
 	}
@@ -797,19 +707,17 @@ _pagebuf_find(				/* find buffer for blo
 	/* No match found */
 	if (new_pb) {
 		_pagebuf_initialize(new_pb, target, range_base,
-				range_length, flags | _PBF_LOCKABLE);
+				range_length, flags);
 		new_pb->pb_hash_index = hval;
-		h->pb_count++;
 		list_add(&new_pb->pb_hash_list, &h->pb_hash);
 	} else {
-		PB_STATS_INC(pb_miss_locked);
+		XFS_STATS_INC(pb_miss_locked);
 	}
 
 	spin_unlock(&h->pb_hash_lock);
 	return (new_pb);
 
 found:
-	atomic_inc(&pb->pb_hold);
 	spin_unlock(&h->pb_hash_lock);
 
 	/* Attempt to get the semaphore without sleeping,
@@ -822,7 +730,7 @@ found:
 			/* wait for buffer ownership */
 			PB_TRACE(pb, "get_lock", 0);
 			pagebuf_lock(pb);
-			PB_STATS_INC(pb_get_locked_waited);
+			XFS_STATS_INC(pb_get_locked_waited);
 		} else {
 			/* We asked for a trylock and failed, no need
 			 * to look at file offset and length here, we
@@ -832,7 +740,7 @@ found:
 			 */
 
 			pagebuf_rele(pb);
-			PB_STATS_INC(pb_busy_locked);
+			XFS_STATS_INC(pb_busy_locked);
 			return (NULL);
 		}
 	} else {
@@ -841,15 +749,13 @@ found:
 	}
 
 	if (pb->pb_flags & PBF_STALE)
-		pb->pb_flags &= PBF_MAPPABLE | \
-				PBF_MAPPED | \
-				_PBF_LOCKABLE | \
+		pb->pb_flags &= PBF_MAPPED | \
 				_PBF_ALL_PAGES_MAPPED | \
 				_PBF_ADDR_ALLOCATED | \
 				_PBF_MEM_ALLOCATED | \
 				_PBF_MEM_SLAB;
 	PB_TRACE(pb, "got_lock", 0);
-	PB_STATS_INC(pb_get_locked);
+	XFS_STATS_INC(pb_get_locked);
 	return (pb);
 }
 
@@ -905,13 +811,14 @@ pagebuf_get(				/* allocate a buffer		*/
 			return (NULL);
 	}
 
-	PB_STATS_INC(pb_get);
+	XFS_STATS_INC(pb_get);
 
 	/* fill in any missing pages */
 	error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags);
 	if (unlikely(error)) {
-		pagebuf_free(pb);
-		return (NULL);
+		printk(KERN_WARNING
+			"pagebuf_get: warning, failed to lookup pages\n");
+		goto no_buffer;
 	}
 
 	/*
@@ -924,7 +831,7 @@ pagebuf_get(				/* allocate a buffer		*/
 	if (flags & PBF_READ) {
 		if (PBF_NOT_DONE(pb)) {
 			PB_TRACE(pb, "get_read", (unsigned long)flags);
-			PB_STATS_INC(pb_get_read);
+			XFS_STATS_INC(pb_get_read);
 			pagebuf_iostart(pb, flags);
 		} else if (flags & PBF_ASYNC) {
 			PB_TRACE(pb, "get_read_async", (unsigned long)flags);
@@ -932,10 +839,7 @@ pagebuf_get(				/* allocate a buffer		*/
 			 * Read ahead call which is already satisfied,
 			 * drop the buffer
 			 */
-			if (flags & (PBF_LOCK | PBF_TRYLOCK))
-				pagebuf_unlock(pb);
-			pagebuf_rele(pb);
-			return NULL;
+			goto no_buffer;
 		} else {
 			PB_TRACE(pb, "get_read_done", (unsigned long)flags);
 			/* We do not want read in the flags */
@@ -944,7 +848,14 @@ pagebuf_get(				/* allocate a buffer		*/
 	} else {
 		PB_TRACE(pb, "get_write", (unsigned long)flags);
 	}
-	return (pb);
+
+	return pb;
+
+no_buffer:
+	if (flags & (PBF_LOCK | PBF_TRYLOCK))
+		pagebuf_unlock(pb);
+	pagebuf_rele(pb);
+	return NULL;
 }
 
 /*
@@ -959,7 +870,7 @@ pagebuf_lookup(
 {
 	page_buf_t		*pb;
 
-	flags |= _PBF_PRIVATE_BH | _PBF_LOCKABLE;
+	flags |= _PBF_PRIVATE_BH;
 	pb = pagebuf_allocate(flags);
 	if (pb) {
 		_pagebuf_initialize(pb, target, ioff, isize, flags);
@@ -978,7 +889,7 @@ pagebuf_readahead(
 	size_t			isize,
 	page_buf_flags_t	flags)
 {
-	flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD);
+	flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_READ_AHEAD);
 	pagebuf_get(target, ioff, isize, flags);
 }
 
@@ -989,9 +900,9 @@ pagebuf_get_empty(
 {
 	page_buf_t		*pb;
 
-	pb = pagebuf_allocate(_PBF_LOCKABLE);
+	pb = pagebuf_allocate(0);
 	if (pb)
-		_pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE);
+		_pagebuf_initialize(pb, target, 0, len, 0);
 	return pb;
 }
 
@@ -1065,7 +976,7 @@ pagebuf_get_no_daddr(
 {
 	int			rval;
 	void			*rmem = NULL;
-	page_buf_flags_t	flags = _PBF_LOCKABLE | PBF_FORCEIO;
+	page_buf_flags_t	flags = PBF_FORCEIO;
 	page_buf_t		*pb;
 	size_t			tlen = 0;
 
@@ -1124,26 +1035,6 @@ pagebuf_hold(
 }
 
 /*
- *	pagebuf_free
- *
- *	pagebuf_free releases the specified buffer.  The modification
- *	state of any associated pages is left unchanged.
- */
-void
-pagebuf_free(
-	page_buf_t		*pb)
-{
-	if (pb->pb_flags & _PBF_LOCKABLE) {
-		pb_hash_t	*h = pb_hash(pb);
-
-		spin_lock(&h->pb_hash_lock);
-		_pagebuf_free_object(h, pb);
-	} else {
-		_pagebuf_free_object(NULL, pb);
-	}
-}
-
-/*
  *	pagebuf_rele
  *
  *	pagebuf_rele releases a hold on the specified buffer.  If the
@@ -1153,44 +1044,37 @@ void
 pagebuf_rele(
 	page_buf_t		*pb)
 {
-	pb_hash_t		*h;
+	pb_hash_t		*hash = pb_hash(pb);
 
 	PB_TRACE(pb, "rele", pb->pb_relse);
-	if (pb->pb_flags & _PBF_LOCKABLE) {
-		h = pb_hash(pb);
-		spin_lock(&h->pb_hash_lock);
-	} else {
-		h = NULL;
-	}
 
-	if (atomic_dec_and_test(&pb->pb_hold)) {
+	if (atomic_dec_and_lock(&pb->pb_hold, &hash->pb_hash_lock)) {
 		int		do_free = 1;
 
 		if (pb->pb_relse) {
 			atomic_inc(&pb->pb_hold);
-			if (h)
-				spin_unlock(&h->pb_hash_lock);
+			spin_unlock(&hash->pb_hash_lock);
 			(*(pb->pb_relse)) (pb);
+			spin_lock(&hash->pb_hash_lock);
 			do_free = 0;
 		}
+
 		if (pb->pb_flags & PBF_DELWRI) {
 			pb->pb_flags |= PBF_ASYNC;
 			atomic_inc(&pb->pb_hold);
-			if (h && do_free)
-				spin_unlock(&h->pb_hash_lock);
 			pagebuf_delwri_queue(pb, 0);
 			do_free = 0;
 		} else if (pb->pb_flags & PBF_FS_MANAGED) {
-			if (h)
-				spin_unlock(&h->pb_hash_lock);
 			do_free = 0;
 		}
 
 		if (do_free) {
-			_pagebuf_free_object(h, pb);
+			list_del_init(&pb->pb_hash_list);
+			spin_unlock(&hash->pb_hash_lock);
+			pagebuf_free(pb);
+		} else {
+			spin_unlock(&hash->pb_hash_lock);
 		}
-	} else if (h) {
-		spin_unlock(&h->pb_hash_lock);
 	}
 }
 
@@ -1221,7 +1105,6 @@ pagebuf_cond_lock(			/* lock buffer, if 
 {
 	int			locked;
 
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
 	locked = down_trylock(&pb->pb_sema) == 0;
 	if (locked) {
 		PB_SET_OWNER(pb);
@@ -1239,7 +1122,6 @@ int
 pagebuf_lock_value(
 	page_buf_t		*pb)
 {
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
 	return(atomic_read(&pb->pb_sema.count));
 }
 
@@ -1255,8 +1137,6 @@ int
 pagebuf_lock(
 	page_buf_t		*pb)
 {
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
-
 	PB_TRACE(pb, "lock", 0);
 	if (atomic_read(&pb->pb_io_remaining))
 		blk_run_queues();
@@ -1277,7 +1157,6 @@ void
 pagebuf_unlock(				/* unlock buffer		*/
 	page_buf_t		*pb)	/* buffer to unlock		*/
 {
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
 	PB_CLEAR_OWNER(pb);
 	up(&pb->pb_sema);
 	PB_TRACE(pb, "unlock", 0);
@@ -1387,7 +1266,7 @@ pagebuf_iodone_sched(
 	}
 
 	if (pb->pb_flags & PBF_ASYNC) {
-		if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse)
+		if (!pb->pb_relse)
 			pagebuf_unlock(pb);
 		pagebuf_rele(pb);
 	}
@@ -1457,7 +1336,7 @@ pagebuf_iostart(			/* start I/O on a buf
 	page_buf_t		*pb,	/* buffer to start		  */
 	page_buf_flags_t	flags)	/* PBF_LOCK, PBF_ASYNC, PBF_READ, */
 					/* PBF_WRITE, PBF_DELWRI,	  */
-					/* PBF_SYNC, PBF_DONT_BLOCK	  */
+					/* PBF_DONT_BLOCK		  */
 {
 	int			status = 0;
 
@@ -1465,16 +1344,15 @@ pagebuf_iostart(			/* start I/O on a buf
 
 	if (flags & PBF_DELWRI) {
 		pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);
-		pb->pb_flags |= flags &
-				(PBF_DELWRI | PBF_ASYNC | PBF_SYNC);
+		pb->pb_flags |= flags & (PBF_DELWRI | PBF_ASYNC);
 		pagebuf_delwri_queue(pb, 1);
 		return status;
 	}
 
-	pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \
-			PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES);
+	pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | PBF_DELWRI | \
+			PBF_READ_AHEAD | PBF_RUN_QUEUES);
 	pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \
-			PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES);
+			PBF_READ_AHEAD | PBF_RUN_QUEUES);
 
 	BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL);
 
@@ -1510,7 +1388,7 @@ _pagebuf_iolocked(
 		return pb->pb_locked;
 	if (pb->pb_flags & PBF_READ)
 		return pb->pb_locked;
-	return (!(pb->pb_flags & _PBF_LOCKABLE));
+	return (pb->pb_flags & _PBF_PAGECACHE);
 }
 
 STATIC void
@@ -2000,7 +1878,6 @@ _pagebuf_ioapply(			/* apply function to
  * Pagebuf delayed write buffer handling
  */
 
-STATIC int pbd_active = 1;
 STATIC LIST_HEAD(pbd_delwrite_queue);
 STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED;
 
@@ -2020,12 +1897,11 @@ pagebuf_delwri_queue(
 	}
 
 	list_add_tail(&pb->pb_list, &pbd_delwrite_queue);
-	pb->pb_flushtime = jiffies + pb_params.age_buffer.val;
+	pb->pb_flushtime = jiffies + xfs_age_buffer;
 	spin_unlock(&pbd_delwrite_lock);
 
-	if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) {
+	if (unlock)
 		pagebuf_unlock(pb);
-	}
 }
 
 void
@@ -2062,10 +1938,10 @@ pagebuf_iodone_daemon(
 	daemonize();
 
 	/* Avoid signals */
-	spin_lock_irq(&current->sigmask_lock);
+	sigmask_lock();
 	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+	__recalc_sigpending(current);
+	sigmask_unlock();
 
 	/* Migrate to the right CPU */
 	migrate_to_cpu(cpu);
@@ -2134,21 +2010,19 @@ pagebuf_dataiodone_daemon(
 
 
 /* Defines for pagebuf daemon */
-DECLARE_WAIT_QUEUE_HEAD(pbd_waitq);
+STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
+STATIC struct task_struct *pagebuf_daemon_task;
+STATIC int pagebuf_daemon_active;
 STATIC int force_flush;
 
 STATIC void
-pagebuf_daemon_wakeup(
-	int			flag)
+pagebuf_daemon_wakeup(void)
 {
-	force_flush = flag;
-	if (waitqueue_active(&pbd_waitq)) {
-		wake_up_interruptible(&pbd_waitq);
-	}
+	force_flush = 1;
+	barrier();
+	wake_up_process(pagebuf_daemon_task);
 }
 
-typedef void (*timeout_fn)(unsigned long);
-
 STATIC int
 pagebuf_daemon(
 	void			*data)
@@ -2156,32 +2030,28 @@ pagebuf_daemon(
 	int			count;
 	page_buf_t		*pb;
 	struct list_head	*curr, *next, tmp;
-	struct timer_list	pb_daemon_timer =
-		{ {NULL, NULL}, 0, 0, (timeout_fn)pagebuf_daemon_wakeup };
 
 	/*  Set up the thread  */
 	daemonize();
 
+	/* Mark it active */
+	pagebuf_daemon_task = current;
+	pagebuf_daemon_active = 1;
+	barrier();
+
 	/* Avoid signals */
-	spin_lock_irq(&current->sigmask_lock);
+	sigmask_lock();
 	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+	__recalc_sigpending(current);
+	sigmask_unlock();
 
-	strcpy(current->comm, "pagebufd");
+	strcpy(current->comm, "xfsbufd");
 	current->flags |= PF_MEMALLOC;
 
 	INIT_LIST_HEAD(&tmp);
 	do {
-		if (pbd_active == 1) {
-			mod_timer(&pb_daemon_timer,
-				  jiffies + pb_params.flush_interval.val);
-			interruptible_sleep_on(&pbd_waitq);
-		}
-
-		if (pbd_active == 0) {
-			del_timer_sync(&pb_daemon_timer);
-		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(xfs_flush_interval);
 
 		spin_lock(&pbd_delwrite_lock);
 
@@ -2191,10 +2061,8 @@ pagebuf_daemon(
 
 			PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
 
-			if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) &&
-			    (((pb->pb_flags & _PBF_LOCKABLE) == 0) ||
-			     !pagebuf_cond_lock(pb))) {
-
+			if ((pb->pb_flags & PBF_DELWRI) &&
+			     !pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
 				if (!force_flush &&
 				    time_before(jiffies, pb->pb_flushtime)) {
 					pagebuf_unlock(pb);
@@ -2203,10 +2071,7 @@ pagebuf_daemon(
 
 				pb->pb_flags &= ~PBF_DELWRI;
 				pb->pb_flags |= PBF_WRITE;
-
-				list_del(&pb->pb_list);
-				list_add(&pb->pb_list, &tmp);
-
+				list_move(&pb->pb_list, &tmp);
 				count++;
 			}
 		}
@@ -2225,12 +2090,9 @@ pagebuf_daemon(
 			blk_run_queues();
 
 		force_flush = 0;
-	} while (pbd_active == 1);
-
-	pbd_active = -1;
-	wake_up_interruptible(&pbd_waitq);
+	} while (pagebuf_daemon_active);
 
-	return 0;
+	complete_and_exit(&pagebuf_daemon_done, 0);
 }
 
 void
@@ -2359,10 +2221,9 @@ pagebuf_daemon_stop(void)
 {
 	int		cpu, pcpu;
 
-	pbd_active = 0;
-
-	wake_up_interruptible(&pbd_waitq);
-	wait_event_interruptible(pbd_waitq, pbd_active);
+	pagebuf_daemon_active = 0;
+	barrier();
+	wait_for_completion(&pagebuf_daemon_done);
 
 	for (pcpu = 0; pcpu < min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++) {
 		cpu = CPU_TO_DAEMON(cpu_logical_map(pcpu));
@@ -2380,107 +2241,10 @@ pagebuf_daemon_stop(void)
 }
 
 
-/*
- * Pagebuf sysctl interface
- */
-
-STATIC int
-pb_stats_clear_handler(
-	ctl_table		*ctl,
-	int			write,
-	struct file		*filp,
-	void			*buffer,
-	size_t			*lenp)
-{
-	int			ret;
-	int			*valp = ctl->data;
-
-	ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp);
-
-	if (!ret && write && *valp) {
-		printk("XFS Clearing pbstats\n");
-		memset(&pbstats, 0, sizeof(pbstats));
-		pb_params.stats_clear.val = 0;
-	}
-
-	return ret;
-}
-
-STATIC struct ctl_table_header *pagebuf_table_header;
-
-STATIC ctl_table pagebuf_table[] = {
-	{PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&pb_params.flush_interval.min, &pb_params.flush_interval.max},
-
-	{PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL, 
-	&pb_params.age_buffer.min, &pb_params.age_buffer.max},
-
-	{PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val,
-	sizeof(int), 0644, NULL, &pb_stats_clear_handler,
-	&sysctl_intvec, NULL, 
-	&pb_params.stats_clear.min, &pb_params.stats_clear.max},
-
-#ifdef PAGEBUF_TRACE
-	{PB_DEBUG, "debug", &pb_params.debug.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL, 
-	&pb_params.debug.min, &pb_params.debug.max},
-#endif
-	{0}
-};
-
-STATIC ctl_table pagebuf_dir_table[] = {
-	{VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table},
-	{0}
-};
-
-STATIC ctl_table pagebuf_root_table[] = {
-	{CTL_VM, "vm",  NULL, 0, 0555, pagebuf_dir_table},
-	{0}
-};
-
-#ifdef CONFIG_PROC_FS
-STATIC int
-pagebuf_readstats(
-	char			*buffer,
-	char			**start,
-	off_t			offset,
-	int			count,
-	int			*eof,
-	void			*data)
-{
-	int			i, len;
-
-	len = 0;
-	len += sprintf(buffer + len, "pagebuf");
-	for (i = 0; i < sizeof(pbstats) / sizeof(u_int32_t); i++) {
-		len += sprintf(buffer + len, " %u",
-			*(((u_int32_t*)&pbstats) + i));
-	}
-	buffer[len++] = '\n';
-
-	if (offset >= len) {
-		*start = buffer;
-		*eof = 1;
-		return 0;
-	}
-	*start = buffer + offset;
-	if ((len -= offset) > count)
-		return count;
-	*eof = 1;
-
-	return len;
-}
-#endif  /* CONFIG_PROC_FS */
-
 STATIC int
 pagebuf_shaker(int number, unsigned int mask)
 {
-	pagebuf_daemon_wakeup(1);
+	pagebuf_daemon_wakeup();
 	return 0;
 }
 
@@ -2494,14 +2258,6 @@ pagebuf_init(void)
 {
 	int			i;
 
-	pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1);
-
-#ifdef CONFIG_PROC_FS
-	if (proc_mkdir("fs/pagebuf", 0))
-		create_proc_read_entry(
-			"fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL);
-#endif
-
 	pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0,
 			SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (pagebuf_cache == NULL) {
@@ -2549,10 +2305,4 @@ pagebuf_terminate(void)
 
 	kmem_cache_destroy(pagebuf_cache);
 	kmem_shake_deregister(pagebuf_shaker);
-
-	unregister_sysctl_table(pagebuf_table_header);
-#ifdef  CONFIG_PROC_FS
-	remove_proc_entry("fs/pagebuf/stat", NULL);
-	remove_proc_entry("fs/pagebuf", NULL);
-#endif
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_buf.h linux-2.4.26-pre6/fs/xfs/linux/xfs_buf.h
--- linux-2.4.25/fs/xfs/linux/xfs_buf.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_buf.h	2004-03-25 00:21:35.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -47,6 +47,16 @@
 #include <linux/fs.h>
 #include <linux/uio.h>
 
+/* nptl patch changes where the sigmask_lock is defined */
+#ifdef CLONE_SIGNAL /* stock */
+#define sigmask_lock()		spin_lock_irq(&current->sigmask_lock);
+#define sigmask_unlock()	spin_unlock_irq(&current->sigmask_lock);
+#define __recalc_sigpending(x)	recalc_sigpending(x)
+#else /* nptl */
+#define sigmask_lock()		spin_lock_irq(&current->sighand->siglock);
+#define sigmask_unlock()	spin_unlock_irq(&current->sighand->siglock);
+#define __recalc_sigpending(x)	recalc_sigpending()
+#endif
 /*
  *	Base types
  */
@@ -76,9 +86,6 @@ typedef enum page_buf_flags_e {		/* pb_f
 	PBF_ASYNC = (1 << 4),   /* initiator will not wait for completion  */
 	PBF_NONE = (1 << 5),    /* buffer not read at all                  */
 	PBF_DELWRI = (1 << 6),  /* buffer has dirty pages                  */
-	PBF_FREED = (1 << 7),   /* buffer has been freed and is invalid    */
-	PBF_SYNC = (1 << 8),    /* force updates to disk                   */
-	PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages          */
 	PBF_STALE = (1 << 10),	/* buffer has been staled, do not find it  */
 	PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory  */
 	PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad  */
@@ -89,7 +96,7 @@ typedef enum page_buf_flags_e {		/* pb_f
 	PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread	   */
 
 	/* flags used only internally */
-	_PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked		   */
+	_PBF_PAGECACHE = (1 << 16),	/* backed by pagecache		   */
 	_PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads	   */
 	_PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped	   */
 	_PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated	   */
@@ -205,7 +212,7 @@ extern page_buf_t *pagebuf_lookup(
 		loff_t,			/* starting offset of range	*/
 		size_t,			/* length of range		*/
 		page_buf_flags_t);	/* PBF_READ, PBF_WRITE,		*/
-					/* PBF_FORCEIO, _PBF_LOCKABLE	*/
+					/* PBF_FORCEIO, 		*/
 
 extern page_buf_t *pagebuf_get_empty(	/* allocate pagebuf struct with	*/
 					/*  no memory or disk address	*/
@@ -270,7 +277,7 @@ extern int pagebuf_iostart(		/* start I/
 		page_buf_t *,		/* buffer to start		*/
 		page_buf_flags_t);	/* PBF_LOCK, PBF_ASYNC,		*/
 					/* PBF_READ, PBF_WRITE,		*/
-					/* PBF_DELWRI, PBF_SYNC		*/
+					/* PBF_DELWRI			*/
 
 extern int pagebuf_iorequest(		/* start real I/O		*/
 		page_buf_t *);		/* buffer to convey to device	*/
@@ -403,7 +410,7 @@ BUFFER_FNS(Delay, delay)
 
 #define XFS_BUF_BFLAGS(x)	((x)->pb_flags)
 #define XFS_BUF_ZEROFLAGS(x)	\
-	((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI))
+	((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI))
 
 #define XFS_BUF_STALE(x)	((x)->pb_flags |= XFS_B_STALE)
 #define XFS_BUF_UNSTALE(x)	((x)->pb_flags &= ~XFS_B_STALE)
@@ -555,17 +562,15 @@ extern inline xfs_caddr_t xfs_buf_offset
 
 #define xfs_buf_read(target, blkno, len, flags) \
 		pagebuf_get((target), (blkno), (len), \
-			PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE)
+			PBF_LOCK | PBF_READ | PBF_MAPPED)
 #define xfs_buf_get(target, blkno, len, flags) \
 		pagebuf_get((target), (blkno), (len), \
-			PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE)
+			PBF_LOCK | PBF_MAPPED)
 
 #define xfs_buf_read_flags(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_READ | PBF_MAPPABLE | flags)
+		pagebuf_get((target), (blkno), (len), PBF_READ | (flags))
 #define xfs_buf_get_flags(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_MAPPABLE | flags)
+		pagebuf_get((target), (blkno), (len), (flags))
 
 static inline int	xfs_bawrite(void *mp, page_buf_t *bp)
 {
@@ -577,7 +582,7 @@ static inline int	xfs_bawrite(void *mp, 
 
 static inline void	xfs_buf_relse(page_buf_t *bp)
 {
-	if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse)
+	if (!bp->pb_relse)
 		pagebuf_unlock(bp);
 	pagebuf_rele(bp);
 }
@@ -608,7 +613,6 @@ static inline int	XFS_bwrite(page_buf_t 
 	int	iowait = (pb->pb_flags & PBF_ASYNC) == 0;
 	int	error = 0;
 
-	pb->pb_flags |= PBF_SYNC;
 	if (!iowait)
 		pb->pb_flags |= PBF_RUN_QUEUES;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_globals.c linux-2.4.26-pre6/fs/xfs/linux/xfs_globals.c
--- linux-2.4.25/fs/xfs/linux/xfs_globals.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_globals.c	2004-03-25 00:22:00.000000000 +0000
@@ -64,6 +64,8 @@ xfs_param_t xfs_params = {
 	.inherit_sync	= {	0,	1,	1	},
 	.inherit_nodump	= {	0,	1,	1	},
 	.inherit_noatim = {	0,	1,	1	},
+	.flush_interval	= {	HZ/2,	HZ,	30*HZ	},
+	.age_buffer	= {	1*HZ,	15*HZ,	300*HZ	},
 };
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_ioctl.c linux-2.4.26-pre6/fs/xfs/linux/xfs_ioctl.c
--- linux-2.4.25/fs/xfs/linux/xfs_ioctl.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_ioctl.c	2004-03-25 00:21:53.000000000 +0000
@@ -310,7 +310,6 @@ xfs_open_by_handle(
 	struct dentry		*dentry;
 	vnode_t			*vp;
 	xfs_fsop_handlereq_t	hreq;
-	struct list_head	*lp;
 
 	error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
 					sizeof(xfs_fsop_handlereq_t),
@@ -356,32 +355,13 @@ xfs_open_by_handle(
 		return new_fd;
 	}
 
-	/* Now to find a dentry.  If possible, get a well-connected one. */
-	spin_lock(&dcache_lock);
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
-		dentry = list_entry(lp, struct dentry, d_alias);
-		if (! (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-			dget_locked(dentry);
-			dentry->d_vfs_flags |= DCACHE_REFERENCED;
-			spin_unlock(&dcache_lock);
-			iput(inode);
-			goto found;
-		}
-	}
-	spin_unlock(&dcache_lock);
-
-	/* ELSE didn't find dentry.  Create anonymous dcache entry. */
-	dentry = d_alloc_root(inode);
+	dentry = d_alloc_anon(inode);
 	if (dentry == NULL) {
 		iput(inode);
 		put_unused_fd(new_fd);
 		return -XFS_ERROR(ENOMEM);
 	}
 
-	/* Keep nfsd happy. */
-	dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
-
- found:
 	/* Ensure umount returns EBUSY on umounts while this file is open. */
 	mntget(parfilp->f_vfsmnt);
 
@@ -721,9 +701,7 @@ xfs_ioctl(
 
 		error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
 							NULL);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_GETBMAP:
@@ -755,9 +733,7 @@ xfs_ioctl(
 
 	case XFS_IOC_SWAPEXT: {
 		error = xfs_swapext((struct xfs_swapext *)arg);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FSCOUNTS: {
@@ -785,6 +761,8 @@ xfs_ioctl(
 		/* input parameter is passed in resblks field of structure */
 		in = inout.resblks;
 		error = xfs_reserve_blocks(mp, &in, &inout);
+		if (error)
+			return -error;
 
 		if (copy_to_user((char *)arg, &inout, sizeof(inout)))
 			return -XFS_ERROR(EFAULT);
@@ -817,9 +795,7 @@ xfs_ioctl(
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_data(mp, &in);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FSGROWFSLOG: {
@@ -832,9 +808,7 @@ xfs_ioctl(
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_log(mp, &in);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FSGROWFSRT: {
@@ -847,9 +821,7 @@ xfs_ioctl(
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_rt(mp, &in);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FREEZE:
@@ -864,6 +836,19 @@ xfs_ioctl(
 		xfs_fs_thaw(mp);
 		return 0;
 
+	case XFS_IOC_GOINGDOWN: {
+		__uint32_t in;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (get_user(in, (__uint32_t *)arg))
+			return -XFS_ERROR(EFAULT);
+
+		error = xfs_fs_goingdown(mp, in);
+		return -error;
+	}
+
 	case XFS_IOC_ERROR_INJECTION: {
 		xfs_error_injection_t in;
 
@@ -871,9 +856,7 @@ xfs_ioctl(
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_errortag_add(in.errtag, mp);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_ERROR_CLEARALL:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_iops.c linux-2.4.26-pre6/fs/xfs/linux/xfs_iops.c
--- linux-2.4.25/fs/xfs/linux/xfs_iops.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_iops.c	2004-03-25 00:20:02.000000000 +0000
@@ -616,8 +616,7 @@ linvfs_listxattr(
 
 	if (!size)
 		xflags |= ATTR_KERNOVAL;
-	if (capable(CAP_SYS_ADMIN))
-		xflags |= ATTR_KERNFULLS;
+	xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
 
 	error = attr_generic_list(vp, data, size, xflags, &result);
 	if (error < 0)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_linux.h linux-2.4.26-pre6/fs/xfs/linux/xfs_linux.h
--- linux-2.4.25/fs/xfs/linux/xfs_linux.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_linux.h	2004-03-25 00:20:58.000000000 +0000
@@ -135,6 +135,8 @@ BUFFER_FNS(Unwritten, unwritten)
 #define xfs_inherit_sync	xfs_params.inherit_sync.val
 #define xfs_inherit_nodump	xfs_params.inherit_nodump.val
 #define xfs_inherit_noatime	xfs_params.inherit_noatim.val
+#define xfs_flush_interval	xfs_params.flush_interval.val
+#define xfs_age_buffer		xfs_params.age_buffer.val
 
 #define current_cpu()		smp_processor_id()
 #define current_pid()		(current->pid)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_lrw.c linux-2.4.26-pre6/fs/xfs/linux/xfs_lrw.c
--- linux-2.4.25/fs/xfs/linux/xfs_lrw.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_lrw.c	2004-03-25 00:17:18.000000000 +0000
@@ -311,9 +311,10 @@ xfs_read(
 	    !(ioflags & IO_INVIS)) {
 		int error;
 		vrwlock_t locktype = VRWLOCK_READ;
+		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
 		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, size,
-				      FILP_DELAY_FLAG(file), &locktype);
+				      dmflags, &locktype);
 		if (error) {
 			if (!(ioflags & IO_ISLOCKED))
 				xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -322,9 +323,13 @@ xfs_read(
 	}
 
 	if (unlikely(ioflags & IO_ISDIRECT)) {
+		xfs_rw_enter_trace(XFS_DIORD_ENTER, &ip->i_iocore,
+					buf, size, *offset, ioflags);
 		ret = do_generic_direct_read(file, buf, size, offset);
 		UPDATE_ATIME(file->f_dentry->d_inode);
 	} else {
+		xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
+					buf, size, *offset, ioflags);
 		ret = generic_file_read(file, buf, size, offset);
 	}
 
@@ -593,7 +598,7 @@ xfs_write(
 	if (size == 0)
 		return 0;
 
-	io = &(xip->i_iocore);
+	io = &xip->i_iocore;
 	mp = io->io_mount;
 
 	xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE);
@@ -645,11 +650,12 @@ start:
 	if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
 	    !(ioflags & IO_INVIS) && !eventsent)) {
 		loff_t		savedsize = *offset;
+		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
 		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
 				      *offset, size,
-				      FILP_DELAY_FLAG(file), &locktype);
+				      dmflags, &locktype);
 		if (error) {
 			if (iolock) xfs_iunlock(xip, iolock);
 			return -error;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_lrw.h linux-2.4.26-pre6/fs/xfs/linux/xfs_lrw.h
--- linux-2.4.25/fs/xfs/linux/xfs_lrw.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_lrw.h	2004-03-25 00:20:15.000000000 +0000
@@ -45,9 +45,7 @@ struct xfs_iomap;
 /*
  * Defines for the trace mechanisms in xfs_lrw.c.
  */
-#define	XFS_RW_KTRACE_SIZE	64
-#define	XFS_STRAT_KTRACE_SIZE	64
-#define	XFS_STRAT_GTRACE_SIZE	512
+#define	XFS_RW_KTRACE_SIZE	128
 
 #define	XFS_READ_ENTER		1
 #define	XFS_WRITE_ENTER		2
@@ -69,6 +67,12 @@ struct xfs_iomap;
 #define	XFS_INVAL_CACHED	18
 #define	XFS_DIORD_ENTER		19
 #define	XFS_DIOWR_ENTER		20
+#define	XFS_SENDFILE_ENTER	21
+#define	XFS_WRITEPAGE_ENTER	22
+#define	XFS_RELEASEPAGE_ENTER	23
+#define	XFS_IOMAP_ALLOC_ENTER	24
+#define	XFS_IOMAP_ALLOC_MAP	25
+#define	XFS_IOMAP_UNWRITTEN	26
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
 			const char *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_stats.c linux-2.4.26-pre6/fs/xfs/linux/xfs_stats.c
--- linux-2.4.25/fs/xfs/linux/xfs_stats.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_stats.c	2004-03-25 00:18:01.000000000 +0000
@@ -63,6 +63,7 @@ xfs_read_xfsstats(
 		{ "attr",		XFSSTAT_END_ATTRIBUTE_OPS	},
 		{ "icluster",		XFSSTAT_END_INODE_CLUSTER	},
 		{ "vnodes",		XFSSTAT_END_VNODE_OPS		},
+		{ "buf",		XFSSTAT_END_BUF			},
 	};
 
 	for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_stats.h linux-2.4.26-pre6/fs/xfs/linux/xfs_stats.h
--- linux-2.4.25/fs/xfs/linux/xfs_stats.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_stats.h	2004-03-25 00:19:56.000000000 +0000
@@ -120,6 +120,16 @@ struct xfsstats {
 	__uint32_t		vn_reclaim;	/* # times vn_reclaim called */
 	__uint32_t		vn_remove;	/* # times vn_remove called */
 	__uint32_t		vn_free;	/* # times vn_free called */
+#define XFSSTAT_END_BUF			(XFSSTAT_END_VNODE_OPS+9)
+	__uint32_t		pb_get;
+	__uint32_t		pb_create;
+	__uint32_t		pb_get_locked;
+	__uint32_t		pb_get_locked_waited;
+	__uint32_t		pb_busy_locked;
+	__uint32_t		pb_miss_locked;
+	__uint32_t		pb_page_retries;
+	__uint32_t		pb_page_found;
+	__uint32_t		pb_get_read;
 /* Extra precision counters */
 	__uint64_t		xs_xstrat_bytes;
 	__uint64_t		xs_write_bytes;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_super.c linux-2.4.26-pre6/fs/xfs/linux/xfs_super.c
--- linux-2.4.25/fs/xfs/linux/xfs_super.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_super.c	2004-03-25 00:20:58.000000000 +0000
@@ -260,6 +260,30 @@ xfs_flush_device(
 	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 }
 
+struct dentry *
+d_alloc_anon(struct inode *inode)
+{
+	struct dentry *dentry;
+
+	spin_lock(&dcache_lock);
+	list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+		if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
+			goto found;
+	}
+	spin_unlock(&dcache_lock);
+
+	dentry = d_alloc_root(inode);
+	if (likely(dentry != NULL))
+		dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
+	return dentry;
+ found:
+	dget_locked(dentry);
+	dentry->d_vfs_flags |= DCACHE_REFERENCED;
+	spin_unlock(&dcache_lock);
+	iput(inode);
+	return dentry;
+}
+
 /*ARGSUSED*/
 int
 xfs_blkdev_get(
@@ -484,10 +508,10 @@ syncd(void *arg)
 
 	daemonize();
 	reparent_to_init();
-	spin_lock_irq(&current->sigmask_lock);
+	sigmask_lock();
 	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+	__recalc_sigpending(current);
+	sigmask_unlock();
 
 	sprintf(current->comm, "xfssyncd");
 
@@ -686,7 +710,6 @@ linvfs_fh_to_dentry(
 {
 	vnode_t			*vp;
 	struct inode		*inode = NULL;
-	struct list_head	*lp;
 	struct dentry		*result;
 	xfs_fid2_t		xfid;
 	vfs_t			*vfsp = LINVFS_GET_VFS(sb);
@@ -711,24 +734,12 @@ linvfs_fh_to_dentry(
 		return ERR_PTR(-ESTALE) ;
 
 	inode = LINVFS_GET_IP(vp);
-	spin_lock(&dcache_lock);
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
-		result = list_entry(lp,struct dentry, d_alias);
-		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-			dget_locked(result);
-			result->d_vfs_flags |= DCACHE_REFERENCED;
-			spin_unlock(&dcache_lock);
-			iput(inode);
-			return result;
-		}
-	}
-	spin_unlock(&dcache_lock);
-	result = d_alloc_root(inode);
-	if (result == NULL) {
+
+	result = d_alloc_anon(inode);
+	if (unlikely(result == NULL)) {
 		iput(inode);
 		return ERR_PTR(-ENOMEM);
 	}
-	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
 	return result;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_super.h linux-2.4.26-pre6/fs/xfs/linux/xfs_super.h
--- linux-2.4.25/fs/xfs/linux/xfs_super.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_super.h	2004-03-25 00:19:24.000000000 +0000
@@ -44,6 +44,8 @@
 
 #ifdef CONFIG_XFS_QUOTA
 # define vfs_insertquota(vfs)	vfs_insertops(vfsp, &xfs_qmops)
+extern void xfs_qm_init(void);
+extern void xfs_qm_exit(void);
 # define vfs_initquota()	xfs_qm_init()
 # define vfs_exitquota()	xfs_qm_exit()
 #else
@@ -133,4 +135,7 @@ extern int xfs_readonly_buftarg(struct p
 extern void xfs_setsize_buftarg(struct pb_target *, unsigned int, unsigned int);
 extern unsigned int xfs_getsize_buftarg(struct pb_target *);
 
+/* matching a 2.6 kernel export, thus no xfs_ prefix */
+extern struct dentry *d_alloc_anon(struct inode *inode);
+
 #endif	/* __XFS_SUPER_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_sysctl.c linux-2.4.26-pre6/fs/xfs/linux/xfs_sysctl.c
--- linux-2.4.25/fs/xfs/linux/xfs_sysctl.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_sysctl.c	2004-03-25 00:21:58.000000000 +0000
@@ -149,6 +149,16 @@ STATIC ctl_table xfs_table[] = {
 	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
 	&sysctl_intvec, NULL,
 	&xfs_params.inherit_noatim.min, &xfs_params.inherit_noatim.max},
+	
+	{XFS_FLUSH_INTERVAL, "flush_interval", &xfs_params.flush_interval.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.flush_interval.min, &xfs_params.flush_interval.max},
+
+	{XFS_AGE_BUFFER, "age_buffer", &xfs_params.age_buffer.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.age_buffer.min, &xfs_params.age_buffer.max},
 
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_sysctl.h linux-2.4.26-pre6/fs/xfs/linux/xfs_sysctl.h
--- linux-2.4.25/fs/xfs/linux/xfs_sysctl.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_sysctl.h	2004-03-25 00:18:36.000000000 +0000
@@ -60,6 +60,10 @@ typedef struct xfs_param {
 	xfs_sysctl_val_t inherit_sync;	/* Inherit the "sync" inode flag. */
 	xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */
 	xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
+	xfs_sysctl_val_t flush_interval;/* interval between runs of the
+					 * delwri flush daemon.  */
+	xfs_sysctl_val_t age_buffer;	/* time for buffer to age before
+					 * we flush it.  */
 } xfs_param_t;
 
 /*
@@ -90,6 +94,8 @@ enum {
 	XFS_INHERIT_SYNC = 13,
 	XFS_INHERIT_NODUMP = 14,
 	XFS_INHERIT_NOATIME = 15,
+	XFS_FLUSH_INTERVAL = 16,
+	XFS_AGE_BUFFER = 17,
 };
 
 extern xfs_param_t	xfs_params;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/linux/xfs_vfs.c linux-2.4.26-pre6/fs/xfs/linux/xfs_vfs.c
--- linux-2.4.25/fs/xfs/linux/xfs_vfs.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/linux/xfs_vfs.c	2004-03-25 00:18:32.000000000 +0000
@@ -117,7 +117,6 @@ vfs_mntupdate(
 	return ((*bhvtovfsops(next)->vfs_mntupdate)(next, fl, args));
 }
 
-
 int
 vfs_root(
 	struct bhv_desc		*bdp,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_ag.h linux-2.4.26-pre6/fs/xfs/xfs_ag.h
--- linux-2.4.25/fs/xfs/xfs_ag.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_ag.h	2004-03-25 00:17:18.000000000 +0000
@@ -230,39 +230,6 @@ typedef struct xfs_perag
 	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
 } xfs_perag_t;
 
-#define	XFS_AG_MIN_BYTES	(1LL << 24)	/* 16 MB */
-#define	XFS_AG_BEST_BYTES	(1LL << 30)	/*  1 GB */
-#define	XFS_AG_MAX_BYTES	(1LL << 32)	/*  4 GB */
-
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MIN_BLOCKS)
-xfs_extlen_t xfs_ag_min_blocks(int bl);
-#define	XFS_AG_MIN_BLOCKS(bl)		xfs_ag_min_blocks(bl)
-#else
-#define	XFS_AG_MIN_BLOCKS(bl)	((xfs_extlen_t)(XFS_AG_MIN_BYTES >> bl))
-#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_BEST_BLOCKS)
-xfs_extlen_t xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks);
-#define	XFS_AG_BEST_BLOCKS(bl,blks)	xfs_ag_best_blocks(bl,blks)
-#else
-/*--#define XFS_AG_BEST_BLOCKS(bl) ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl))*/
-/*
- * Best is XFS_AG_BEST_BLOCKS at and below 64 Gigabyte filesystems, and
- * XFS_AG_MAX_BLOCKS above 64 Gigabytes.
- */
-#define XFS_AG_BEST_BLOCKS(bl,blks)	\
-	((xfs_extlen_t)((1LL << (36 - bl)) >= blks) ? \
-		((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl)) : \
-		XFS_AG_MAX_BLOCKS(bl))
-#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAX_BLOCKS)
-xfs_extlen_t xfs_ag_max_blocks(int bl);
-#define	XFS_AG_MAX_BLOCKS(bl)		xfs_ag_max_blocks(bl)
-#else
-#define	XFS_AG_MAX_BLOCKS(bl)	((xfs_extlen_t)(XFS_AG_MAX_BYTES >> bl))
-#endif
-
-#define	XFS_MAX_AGNUMBER	((xfs_agnumber_t)(NULLAGNUMBER - 1))
-
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAXLEVELS)
 int xfs_ag_maxlevels(struct xfs_mount *mp);
 #define	XFS_AG_MAXLEVELS(mp)		xfs_ag_maxlevels(mp)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_alloc.c linux-2.4.26-pre6/fs/xfs/xfs_alloc.c
--- linux-2.4.25/fs/xfs/xfs_alloc.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_alloc.c	2004-03-25 00:17:27.000000000 +0000
@@ -780,14 +780,8 @@ xfs_alloc_ag_vextent_near(
 	/*
 	 * Randomly don't execute the first algorithm.
 	 */
-	static int	seed;		/* randomizing seed value */
 	int		dofirst;	/* set to do first algorithm */
-	timespec_t	now;		/* current time */
 
-	if (!seed) {
-		nanotime(&now);
-		seed = (int)now.tv_sec ^ (int)now.tv_nsec;
-	}
 	dofirst = random() & 1;
 #endif
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_attr.h linux-2.4.26-pre6/fs/xfs/xfs_attr.h
--- linux-2.4.25/fs/xfs/xfs_attr.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_attr.h	2004-03-25 00:22:17.000000000 +0000
@@ -91,10 +91,14 @@ extern int attr_generic_list(struct vnod
 #define ATTR_CREATE	0x0010	/* pure create: fail if attr already exists */
 #define ATTR_REPLACE	0x0020	/* pure set: fail if attr does not exist */
 #define ATTR_SYSTEM	0x0100	/* use attrs in system (pseudo) namespace */
+
 #define ATTR_KERNOTIME	0x1000	/* [kernel] don't update inode timestamps */
 #define ATTR_KERNOVAL	0x2000	/* [kernel] get attr size only, not value */
 #define ATTR_KERNAMELS	0x4000	/* [kernel] list attr names (simple list) */
-#define ATTR_KERNFULLS	0x8000	/* [kernel] full attr list, ie. root+user */
+
+#define ATTR_KERNORMALS	0x0800	/* [kernel] normal attr list: user+secure */
+#define ATTR_KERNROOTLS	0x8000	/* [kernel] include root in the attr list */
+#define ATTR_KERNFULLS	(ATTR_KERNORMALS|ATTR_KERNROOTLS)
 
 /*
  * The maximum size (into the kernel or returned from the kernel) of an
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_attr_leaf.c linux-2.4.26-pre6/fs/xfs/xfs_attr_leaf.c
--- linux-2.4.25/fs/xfs/xfs_attr_leaf.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_attr_leaf.c	2004-03-25 00:18:43.000000000 +0000
@@ -460,9 +460,15 @@ xfs_attr_shortform_list(xfs_attr_list_co
 				i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
 			attrnames_t	*namesp;
 
+			if (((context->flags & ATTR_SECURE) != 0) !=
+			    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
+			    !(context->flags & ATTR_KERNORMALS)) {
+				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
+				continue;
+			}
 			if (((context->flags & ATTR_ROOT) != 0) !=
 			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-			    !(context->flags & ATTR_KERNFULLS)) {
+			    !(context->flags & ATTR_KERNROOTLS)) {
 				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 				continue;
 			}
@@ -511,9 +517,15 @@ xfs_attr_shortform_list(xfs_attr_list_co
 			kmem_free(sbuf, sbsize);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
+		if (((context->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
+		    !(context->flags & ATTR_KERNORMALS)) {
+			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
+			continue;
+		}
 		if (((context->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNFULLS)) {
+		    !(context->flags & ATTR_KERNROOTLS)) {
 			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 			continue;
 		}
@@ -2309,9 +2321,13 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, 
 
 		if (entry->flags & XFS_ATTR_INCOMPLETE)
 			continue;		/* skip incomplete entries */
+		if (((context->flags & ATTR_SECURE) != 0) !=
+		    ((entry->flags & XFS_ATTR_SECURE) != 0) &&
+		    !(context->flags & ATTR_KERNORMALS))
+			continue;		/* skip non-matching entries */
 		if (((context->flags & ATTR_ROOT) != 0) !=
 		    ((entry->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNFULLS))
+		    !(context->flags & ATTR_KERNROOTLS))
 			continue;		/* skip non-matching entries */
 
 		namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_buf_item.c linux-2.4.26-pre6/fs/xfs/xfs_buf_item.c
--- linux-2.4.25/fs/xfs/xfs_buf_item.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_buf_item.c	2004-03-25 00:17:32.000000000 +0000
@@ -429,7 +429,7 @@ xfs_buf_item_unpin(
 		 */
 		if (bip->bli_flags & XFS_BLI_STALE_INODE) {
 			xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip);
-			XFS_BUF_FSPRIVATE(bp, void *) = NULL;
+			XFS_BUF_SET_FSPRIVATE(bp, NULL);
 			XFS_BUF_CLR_IODONE_FUNC(bp);
 		} else {
 			AIL_LOCK(mp,s);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_clnt.h linux-2.4.26-pre6/fs/xfs/xfs_clnt.h
--- linux-2.4.25/fs/xfs/xfs_clnt.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_clnt.h	2004-03-25 00:21:23.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -57,10 +57,10 @@ struct xfs_mount_args {
 	int	flags;		/* flags -> see XFSMNT_... macros below */
 	int	logbufs;	/* Number of log buffers, -1 to default */
 	int	logbufsize;	/* Size of log buffers, -1 to default */
-	char	fsname[MAXNAMELEN];	/* data device name */
-	char	rtname[MAXNAMELEN];	/* realtime device filename */
-	char	logname[MAXNAMELEN];	/* journal device filename */
-	char	mtpt[MAXNAMELEN];	/* filesystem mount point */
+	char	fsname[MAXNAMELEN+1];	/* data device name */
+	char	rtname[MAXNAMELEN+1];	/* realtime device filename */
+	char	logname[MAXNAMELEN+1];	/* journal device filename */
+	char	mtpt[MAXNAMELEN+1];	/* filesystem mount point */
 	int	sunit;		/* stripe unit (BBs) */
 	int	swidth;		/* stripe width (BBs), multiple of sunit */
 	uchar_t iosizelog;	/* log2 of the preferred I/O size */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_dir2_node.c linux-2.4.26-pre6/fs/xfs/xfs_dir2_node.c
--- linux-2.4.25/fs/xfs/xfs_dir2_node.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_dir2_node.c	2004-03-25 00:17:48.000000000 +0000
@@ -1573,15 +1573,16 @@ xfs_dir2_node_addname_int(
 					"%llu needed freesp block %lld for\n"
 					"  data block %lld, got %lld\n"
 					"  ifbno %llu lastfbno %d\n",
-					dp->i_ino,
-					XFS_DIR2_DB_TO_FDB(mp, dbno),
-					dbno, fbno,
-					ifbno, lastfbno);
+					(unsigned long long)dp->i_ino,
+					(long long)XFS_DIR2_DB_TO_FDB(mp, dbno),
+					(long long)dbno, (long long)fbno,
+					(unsigned long long)ifbno, lastfbno);
 				if (fblk) {
 					cmn_err(CE_ALERT,
-						" fblk 0x%llu blkno %llu "
+						" fblk 0x%p blkno %llu "
 						"index %d magic 0x%x\n",
-						fblk, fblk->blkno,
+						fblk,
+						(unsigned long long)fblk->blkno,
 						fblk->index,
 						fblk->magic);
 				} else {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_dmapi.h linux-2.4.26-pre6/fs/xfs/xfs_dmapi.h
--- linux-2.4.25/fs/xfs/xfs_dmapi.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_dmapi.h	2004-03-25 00:21:29.000000000 +0000
@@ -165,6 +165,27 @@ typedef enum {
 
 #define DM_FLAGS_NDELAY		0x001	/* return EAGAIN after dm_pending() */
 #define DM_FLAGS_UNWANTED	0x002	/* event not in fsys dm_eventset_t */
+#define DM_FLAGS_ISEM		0x004	/* thread holds i_sem */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
+/* i_alloc_sem was added in 2.4.22-pre1 */
+#define DM_FLAGS_IALLOCSEM_RD	0x010	/* thread holds i_alloc_sem rd */
+#define DM_FLAGS_IALLOCSEM_WR	0x020	/* thread holds i_alloc_sem wr */
+#endif
+#endif
+
+/*
+ *	Based on IO_ISDIRECT, decide which i_ flag is set.
+ */
+#ifdef DM_FLAGS_IALLOCSEM_RD
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+			      DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
+#define DM_SEM_FLAG_WR	(DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+#else
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+			      0 : DM_FLAGS_ISEM)
+#define DM_SEM_FLAG_WR	(DM_FLAGS_ISEM)
+#endif
 
 /*
  *	Macros to turn caller specified delay/block flags into
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_dmops.c linux-2.4.26-pre6/fs/xfs/xfs_dmops.c
--- linux-2.4.25/fs/xfs/xfs_dmops.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_dmops.c	2004-03-25 00:19:21.000000000 +0000
@@ -43,7 +43,7 @@
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 
-xfs_dmops_t	xfs_dmcore_xfs = {
+xfs_dmops_t	xfs_dmcore_stub = {
 	.xfs_send_data		= (xfs_send_data_t)fs_nosys,
 	.xfs_send_mmap		= (xfs_send_mmap_t)fs_noerr,
 	.xfs_send_destroy	= (xfs_send_destroy_t)fs_nosys,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_error.c linux-2.4.26-pre6/fs/xfs/xfs_error.c
--- linux-2.4.25/fs/xfs/xfs_error.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_error.c	2004-03-25 00:18:07.000000000 +0000
@@ -218,13 +218,17 @@ xfs_errortag_clearall(xfs_mount_t *mp)
 static void
 xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
 {
-	char	*newfmt;
-	int	len = 16 + mp->m_fsname_len + strlen(fmt);
-
-	newfmt = kmem_alloc(len, KM_SLEEP);
-	sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
-	icmn_err(level, newfmt, ap);
-	kmem_free(newfmt, len);
+	if (mp != NULL) {
+		char	*newfmt;
+		int	len = 16 + mp->m_fsname_len + strlen(fmt);
+
+		newfmt = kmem_alloc(len, KM_SLEEP);
+		sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
+		icmn_err(level, newfmt, ap);
+		kmem_free(newfmt, len);
+	} else {
+		icmn_err(level, fmt, ap);
+	}
 }
 
 void
@@ -267,16 +271,10 @@ xfs_error_report(
 	inst_t		*ra)
 {
 	if (level <= xfs_error_level) {
-		if (mp != NULL) {
-			xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
-				    CE_ALERT, mp,
+		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
+			    CE_ALERT, mp,
 		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
-				    tag, linenum, fname, ra);
-		} else {
-			cmn_err(CE_ALERT,
-		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
-				tag, linenum, fname, ra);
-		}
+			    tag, linenum, fname, ra);
 
 		xfs_stack_trace();
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_fs.h linux-2.4.26-pre6/fs/xfs/xfs_fs.h
--- linux-2.4.25/fs/xfs/xfs_fs.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_fs.h	2004-03-25 00:19:35.000000000 +0000
@@ -437,6 +437,12 @@ typedef struct xfs_handle {
 
 #define FSHSIZE		sizeof(fsid_t)
 
+/* 
+ * Flags for going down operation
+ */
+#define XFS_FSOP_GOING_FLAGS_DEFAULT		0x0	/* going down */
+#define XFS_FSOP_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
+#define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
 
 /*
  * ioctl commands that replace IRIX fcntl()'s
@@ -490,6 +496,7 @@ typedef struct xfs_handle {
 #define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
 #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
 #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 124, struct xfs_fsop_geom)
+#define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, __uint32_t)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_fsops.c linux-2.4.26-pre6/fs/xfs/xfs_fsops.c
--- linux-2.4.25/fs/xfs/xfs_fsops.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_fsops.c	2004-03-25 00:19:56.000000000 +0000
@@ -626,3 +626,28 @@ xfs_fs_thaw(
 	xfs_finish_freeze(mp);
 	return 0;
 }
+
+int
+xfs_fs_goingdown(
+	xfs_mount_t	*mp,
+	__uint32_t	inflags)
+{
+	switch (inflags)
+	{
+	case XFS_FSOP_GOING_FLAGS_DEFAULT:
+		xfs_fs_freeze(mp);
+		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+		xfs_fs_thaw(mp);
+		break;
+	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
+		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+		break;
+	case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
+		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR);
+		break;
+	default:
+		return XFS_ERROR(EINVAL);
+	}
+
+	return 0;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_fsops.h linux-2.4.26-pre6/fs/xfs/xfs_fsops.h
--- linux-2.4.25/fs/xfs/xfs_fsops.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_fsops.h	2004-03-25 00:17:36.000000000 +0000
@@ -67,4 +67,9 @@ int
 xfs_fs_thaw(
 	xfs_mount_t		*mp);
 
+int
+xfs_fs_goingdown(
+	xfs_mount_t		*mp,
+	__uint32_t		inflags);
+
 #endif	/* __XFS_FSOPS_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_iomap.c linux-2.4.26-pre6/fs/xfs/xfs_iomap.c
--- linux-2.4.25/fs/xfs/xfs_iomap.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_iomap.c	2004-03-25 00:17:35.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -69,6 +69,76 @@
 #include "xfs_utils.h"
 #include "xfs_iomap.h"
 
+#if defined(XFS_RW_TRACE)
+void
+xfs_iomap_enter_trace(
+	int		tag,
+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	ssize_t		count)
+{
+	xfs_inode_t	*ip = XFS_IO_INODE(io);
+
+	if (!ip->i_rwtrace)
+		return;
+
+	ktrace_enter(ip->i_rwtrace,
+		(void *)((unsigned long)tag),
+		(void *)ip,
+		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
+		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(offset & 0xffffffff)),
+		(void *)((unsigned long)count),
+		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL);
+}
+
+void
+xfs_iomap_map_trace(
+	int		tag,
+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	ssize_t		count,
+	xfs_iomap_t	*iomapp,
+	xfs_bmbt_irec_t	*imapp,
+	int		flags)
+{
+	xfs_inode_t	*ip = XFS_IO_INODE(io);
+
+	if (!ip->i_rwtrace)
+		return;
+
+	ktrace_enter(ip->i_rwtrace,
+		(void *)((unsigned long)tag),
+		(void *)ip,
+		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
+		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(offset & 0xffffffff)),
+		(void *)((unsigned long)count),
+		(void *)((unsigned long)flags),
+		(void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)),
+		(void *)((unsigned long)(iomapp->iomap_delta)),
+		(void *)((unsigned long)(iomapp->iomap_bsize)),
+		(void *)((unsigned long)(iomapp->iomap_bn)),
+		(void *)(__psint_t)(imapp->br_startoff),
+		(void *)((unsigned long)(imapp->br_blockcount)),
+		(void *)(__psint_t)(imapp->br_startblock));
+}
+#else
+#define xfs_iomap_enter_trace(tag, io, offset, count)
+#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags)
+#endif
+
 #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
 						<< mp->m_writeio_log)
 #define XFS_STRAT_WRITE_IMAPS	2
@@ -149,17 +219,20 @@ xfs_iomap(
 		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
 		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
 	case BMAPI_READ:
+		xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
 		lockmode = XFS_LCK_MAP_SHARED(mp, io);
 		bmapi_flags = XFS_BMAPI_ENTIRE;
 		if (flags & BMAPI_IGNSTATE)
 			bmapi_flags |= XFS_BMAPI_IGSTATE;
 		break;
 	case BMAPI_WRITE:
+		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
 		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
 		bmapi_flags = 0;
 		XFS_ILOCK(mp, io, lockmode);
 		break;
 	case BMAPI_ALLOCATE:
+		xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);
 		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
 		bmapi_flags = XFS_BMAPI_ENTIRE;
 		/* Attempt non-blocking lock */
@@ -201,8 +274,11 @@ phase2:
 	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
 	case BMAPI_WRITE:
 		/* If we found an extent, return it */
-		if (nimaps && (imap.br_startblock != HOLESTARTBLOCK))
+		if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) {
+			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
+					offset, count, iomapp, &imap, flags);
 			break;
+		}
 
 		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
 			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
@@ -211,6 +287,10 @@ phase2:
 			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
 					flags, &imap, &nimaps);
 		}
+		if (!error) {
+			xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,
+					offset, count, iomapp, &imap, flags);
+		}
 		iomap_flags = IOMAP_NEW;
 		break;
 	case BMAPI_ALLOCATE:
@@ -218,8 +298,11 @@ phase2:
 		XFS_IUNLOCK(mp, io, lockmode);
 		lockmode = 0;
 
-		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock))
+		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) {
+			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
+					offset, count, iomapp, &imap, flags);
 			break;
+		}
 
 		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
 		break;
@@ -309,7 +392,6 @@ xfs_iomap_write_direct(
 	 * Make sure that the dquots are there. This doesn't hold
 	 * the ilock across a disk read.
 	 */
-
 	error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
 	if (error)
 		return XFS_ERROR(error);
@@ -540,8 +622,9 @@ retry:
 	 * If bmapi returned us nothing, and if we didn't get back EDQUOT,
 	 * then we must have run out of space.
 	 */
-
 	if (nimaps == 0) {
+		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
+					io, offset, count);
 		if (xfs_flush_space(ip, &fsynced, &ioflag))
 			return XFS_ERROR(ENOSPC);
 
@@ -584,7 +667,6 @@ xfs_iomap_write_allocate(
 	/*
 	 * Make sure that the dquots are there.
 	 */
-
 	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
 		return XFS_ERROR(error);
 
@@ -612,7 +694,6 @@ xfs_iomap_write_allocate(
 					XFS_WRITE_LOG_RES(mp),
 					0, XFS_TRANS_PERM_LOG_RES,
 					XFS_WRITE_LOG_COUNT);
-
 			if (error == ENOSPC) {
 				error = xfs_trans_reserve(tp, 0,
 						XFS_WRITE_LOG_RES(mp),
@@ -653,19 +734,16 @@ xfs_iomap_write_allocate(
 			error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
 					XFS_BMAPI_WRITE, &first_block, 1,
 					imap, &nimaps, &free_list);
-
 			if (error)
 				goto trans_cancel;
 
 			error = xfs_bmap_finish(&tp, &free_list,
 					first_block, &committed);
-
 			if (error)
 				goto trans_cancel;
 
 			error = xfs_trans_commit(tp,
 					XFS_TRANS_RELEASE_LOG_RES, NULL);
-
 			if (error)
 				goto error0;
 
@@ -725,6 +803,9 @@ xfs_iomap_write_unwritten(
 	xfs_fsblock_t	firstfsb;
 	xfs_bmap_free_t	free_list;
 
+	xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN,
+				&ip->i_iocore, offset, count);
+
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 	count_fsb = XFS_B_TO_FSB(mp, count);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_log.c linux-2.4.26-pre6/fs/xfs/xfs_log.c
--- linux-2.4.25/fs/xfs/xfs_log.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_log.c	2004-03-25 00:21:13.000000000 +0000
@@ -759,8 +759,9 @@ xfs_log_move_tail(xfs_mount_t	*mp,
 	/* Also an invalid lsn.  1 implies that we aren't passing in a valid
 	 * tail_lsn.
 	 */
-	if (tail_lsn != 1)
+	if (tail_lsn != 1) {
 		log->l_tail_lsn = tail_lsn;
+	}
 
 	if ((tic = log->l_write_headq)) {
 #ifdef DEBUG
@@ -866,10 +867,11 @@ xlog_assign_tail_lsn(xfs_mount_t *mp)
 
 	tail_lsn = xfs_trans_tail_ail(mp);
 	s = GRANT_LOCK(log);
-	if (tail_lsn != 0)
+	if (tail_lsn != 0) {
 		log->l_tail_lsn = tail_lsn;
-	else
+	} else {
 		tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn;
+	}
 	GRANT_UNLOCK(log, s);
 
 	return tail_lsn;
@@ -921,10 +923,8 @@ xlog_space_left(xlog_t *log, int cycle, 
 		 * In this case we just want to return the size of the
 		 * log as the amount of space left.
 		 */
-/* This assert does not take into account padding from striped log writes *
 		ASSERT((tail_cycle == (cycle + 1)) ||
 		       ((bytes + log->l_roundoff) >= tail_bytes));
-*/
 		free_bytes = log->l_logsize;
 	}
 	return free_bytes;
@@ -1183,14 +1183,6 @@ xlog_alloc_log(xfs_mount_t	*mp,
 	log->l_grant_reserve_cycle = 1;
 	log->l_grant_write_cycle = 1;
 
-	if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
-		if (mp->m_sb.sb_logsunit <= 1) {
-			log->l_stripemask = 1;
-		} else {
-			log->l_stripemask = 1 <<
-				xfs_highbit32(mp->m_sb.sb_logsunit >> BBSHIFT);
-		}
-	}
 	if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) {
 		log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
 		ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
@@ -1235,7 +1227,7 @@ xlog_alloc_log(xfs_mount_t	*mp,
 			  kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
 		iclog = *iclogp;
 		iclog->hic_data = (xlog_in_core_2_t *)
-			  kmem_alloc(iclogsize, KM_SLEEP);
+			  kmem_zalloc(iclogsize, KM_SLEEP);
 
 		iclog->ic_prev = prev_iclog;
 		prev_iclog = iclog;
@@ -1401,45 +1393,35 @@ xlog_sync(xlog_t		*log,
 	xfs_caddr_t	dptr;		/* pointer to byte sized element */
 	xfs_buf_t	*bp;
 	int		i, ops;
-	uint		roundup;
 	uint		count;		/* byte count of bwrite */
+	uint		count_init;	/* initial count before roundup */
 	int		split = 0;	/* split write into two regions */
 	int		error;
 
 	XFS_STATS_INC(xs_log_writes);
 	ASSERT(iclog->ic_refcnt == 0);
 
+	/* Add for LR header */
+	count_init = log->l_iclog_hsize + iclog->ic_offset;
+
 	/* Round out the log write size */
-	if (iclog->ic_offset & BBMASK) {
-		/* count of 0 is already accounted for up in
-		 * xlog_state_sync_all().  Once in this routine,
-		 * operations on the iclog are single threaded.
-		 *
-		 * Difference between rounded up size and size
-		 */
-		count = iclog->ic_offset & BBMASK;
-		iclog->ic_roundoff += BBSIZE - count;
-	}
-	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-		unsigned sunit = BTOBB(log->l_mp->m_sb.sb_logsunit);
-		if (!sunit)
-			sunit = 1;
-
-		count = BTOBB(log->l_iclog_hsize + iclog->ic_offset);
-		if (count & (sunit - 1)) {
-			roundup = sunit - (count & (sunit - 1));
-		} else {
-			roundup = 0;
-		}
-		iclog->ic_offset += BBTOB(roundup);
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
+	    log->l_mp->m_sb.sb_logsunit > 1) {
+		/* we have a v2 stripe unit to use */
+		count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init));
+	} else {
+		count = BBTOB(BTOBB(count_init));
 	}
-
+	iclog->ic_roundoff = count - count_init;
 	log->l_roundoff += iclog->ic_roundoff;
 
 	xlog_pack_data(log, iclog);       /* put cycle number in every block */
 
 	/* real byte length */
-	INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+	INT_SET(iclog->ic_header.h_len, 
+		ARCH_CONVERT,
+		iclog->ic_offset + iclog->ic_roundoff);
+
 	/* put ops count in correct order */
 	ops = iclog->ic_header.h_num_logops;
 	INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops);
@@ -1449,12 +1431,6 @@ xlog_sync(xlog_t		*log,
 	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
 	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT));
 
-	/* Count is already rounded up to a BBSIZE above */
-	count = iclog->ic_offset + iclog->ic_roundoff;
-	ASSERT((count & BBMASK) == 0);
-
-	/* Add for LR header */
-	count += log->l_iclog_hsize;
 	XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
 
 	/* Do we need to split this write into 2 parts? */
@@ -2783,8 +2759,6 @@ xlog_state_switch_iclogs(xlog_t		*log,
 			 xlog_in_core_t *iclog,
 			 int		eventual_size)
 {
-	uint roundup;
-
 	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
 	if (!eventual_size)
 		eventual_size = iclog->ic_offset;
@@ -2797,14 +2771,10 @@ xlog_state_switch_iclogs(xlog_t		*log,
 	log->l_curr_block += BTOBB(eventual_size)+BTOBB(log->l_iclog_hsize);
 
 	/* Round up to next log-sunit */
-	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-		if (log->l_curr_block & (log->l_stripemask - 1)) {
-			roundup = log->l_stripemask -
-				(log->l_curr_block & (log->l_stripemask - 1));
-		} else {
-			roundup = 0;
-		}
-		log->l_curr_block += roundup;
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
+	    log->l_mp->m_sb.sb_logsunit > 1) {
+		__uint32_t sunit_bb = BTOBB(log->l_mp->m_sb.sb_logsunit);
+		log->l_curr_block = roundup(log->l_curr_block, sunit_bb);
 	}
 
 	if (log->l_curr_block >= log->l_logBBsize) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_log_priv.h linux-2.4.26-pre6/fs/xfs/xfs_log_priv.h
--- linux-2.4.25/fs/xfs/xfs_log_priv.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_log_priv.h	2004-03-25 00:18:29.000000000 +0000
@@ -63,6 +63,9 @@ int xlog_btolrbb(int b);
 #else
 #define XLOG_BTOLRBB(b)		(((b)+XLOG_RECORD_BSIZE-1) >> XLOG_RECORD_BSHIFT)
 #endif
+#define XLOG_BTOLSUNIT(log, b)  (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
+                                 (log)->l_mp->m_sb.sb_logsunit)
+#define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit)
 
 #define XLOG_HEADER_SIZE	512
 
@@ -531,7 +534,6 @@ typedef struct log {
 	uint			l_flags;
 	uint			l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
 	struct xfs_buf_cancel	**l_buf_cancel_table;
-	int			l_stripemask;	/* log stripe mask */
 	int			l_iclog_hsize;  /* size of iclog header */
 	int			l_iclog_heads;  /* # of iclog header sectors */
 	uint			l_sectbb_log;   /* log2 of sector size in BBs */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_log_recover.c linux-2.4.26-pre6/fs/xfs/xfs_log_recover.c
--- linux-2.4.25/fs/xfs/xfs_log_recover.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_log_recover.c	2004-03-25 00:21:54.000000000 +0000
@@ -3416,6 +3416,7 @@ xlog_unpack_data_checksum(
 {
 	uint			*up = (uint *)dp;
 	uint			chksum = 0;
+	int			i;
 
 	/* divide length by 4 to get # words */
 	for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) {
@@ -3476,7 +3477,7 @@ xlog_valid_rec_header(
 	xlog_rec_header_t	*rhead,
 	xfs_daddr_t		blkno)
 {
-	int			bblks;
+	int			hlen;
 
 	if (unlikely(
 	    (INT_GET(rhead->h_magicno, ARCH_CONVERT) !=
@@ -3495,8 +3496,8 @@ xlog_valid_rec_header(
 	}
 
 	/* LR body must have data or it wouldn't have been written */
-	bblks = INT_GET(rhead->h_len, ARCH_CONVERT);
-	if (unlikely( bblks <= 0 || bblks > INT_MAX )) {
+	hlen = INT_GET(rhead->h_len, ARCH_CONVERT);
+	if (unlikely( hlen <= 0 || hlen > INT_MAX )) {
 		XFS_ERROR_REPORT("xlog_valid_rec_header(2)",
 				XFS_ERRLEVEL_LOW, log->l_mp);
 		return XFS_ERROR(EFSCORRUPTED);
@@ -3658,7 +3659,7 @@ xlog_do_recovery_pass(
 				error = xlog_bread(log, 0, wrapped_hblks, hbp);
 				if (error)
 					goto bread_err2;
-				XFS_BUF_SET_PTR(hbp, bufaddr, hblks);
+				XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks));
 				if (!offset)
 					offset = xlog_align(log, 0,
 							wrapped_hblks, hbp);
@@ -3716,8 +3717,7 @@ xlog_do_recovery_pass(
 				if ((error = xlog_bread(log, wrapped_hblks,
 						bblks - split_bblks, dbp)))
 					goto bread_err2;
-				XFS_BUF_SET_PTR(dbp, bufaddr,
-						XLOG_BIG_RECORD_BSIZE);
+				XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
 				if (!offset)
 					offset = xlog_align(log, wrapped_hblks,
 						bblks - split_bblks, dbp);
@@ -4042,7 +4042,7 @@ xlog_recover_check_summary(
 				XFS_FSS_TO_BB(mp, 1), 0);
 		if (XFS_BUF_ISERROR(agibp)) {
 			xfs_ioerror_alert("xlog_recover_check_summary(agi)",
-					  log->l_mp, agibp, agidaddr);
+					  mp, agibp, agidaddr);
 		}
 		agip = XFS_BUF_TO_AGI(agibp);
 		ASSERT(XFS_AGI_MAGIC ==
@@ -4058,7 +4058,8 @@ xlog_recover_check_summary(
 
 	sbbp = xfs_getsb(mp, 0);
 #ifdef XFS_LOUD_RECOVERY
-	sbp = XFS_BUF_TO_SBP(sbbp);
+	sbp = &mp->m_sb;
+	xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, ARCH_CONVERT, XFS_SB_ALL_BITS);
 	cmn_err(CE_NOTE,
 		"xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
 		sbp->sb_icount, itotal);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_macros.c linux-2.4.26-pre6/fs/xfs/xfs_macros.c
--- linux-2.4.25/fs/xfs/xfs_macros.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_macros.c	2004-03-25 00:22:22.000000000 +0000
@@ -115,22 +115,6 @@ xfs_ag_daddr(xfs_mount_t *mp, xfs_agnumb
 }
 #endif
 
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_BEST_BLOCKS)
-xfs_extlen_t
-xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks)
-{
-	return XFS_AG_BEST_BLOCKS(bl, blks);
-}
-#endif
-
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MAX_BLOCKS)
-xfs_extlen_t
-xfs_ag_max_blocks(int bl)
-{
-	return XFS_AG_MAX_BLOCKS(bl);
-}
-#endif
-
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MAXLEVELS)
 int
 xfs_ag_maxlevels(xfs_mount_t *mp)
@@ -139,14 +123,6 @@ xfs_ag_maxlevels(xfs_mount_t *mp)
 }
 #endif
 
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MIN_BLOCKS)
-xfs_extlen_t
-xfs_ag_min_blocks(int bl)
-{
-	return XFS_AG_MIN_BLOCKS(bl);
-}
-#endif
-
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AGB_TO_DADDR)
 xfs_daddr_t
 xfs_agb_to_daddr(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_mount.c linux-2.4.26-pre6/fs/xfs/xfs_mount.c
--- linux-2.4.25/fs/xfs/xfs_mount.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_mount.c	2004-03-25 00:20:58.000000000 +0000
@@ -675,6 +675,7 @@ xfs_mountfs(
 				error = XFS_ERROR(EINVAL);
 				goto error1;
 			}
+			mp->m_dalign = mp->m_swidth = 0;
 		} else {
 			/*
 			 * Convert the stripe unit and width to FSBs.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_mount.h linux-2.4.26-pre6/fs/xfs/xfs_mount.h
--- linux-2.4.25/fs/xfs/xfs_mount.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_mount.h	2004-03-25 00:17:46.000000000 +0000
@@ -571,8 +571,8 @@ extern void	xfs_check_frozen(xfs_mount_t
 extern struct vfsops xfs_vfsops;
 extern struct vnodeops xfs_vnodeops;
 
-extern struct xfs_dmops xfs_dmcore_xfs;
-extern struct xfs_qmops xfs_qmcore_xfs;
+extern struct xfs_dmops xfs_dmcore_stub;
+extern struct xfs_qmops xfs_qmcore_stub;
 extern struct xfs_ioops xfs_iocore_xfs;
 
 extern int	xfs_init(void);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_qmops.c linux-2.4.26-pre6/fs/xfs/xfs_qmops.c
--- linux-2.4.25/fs/xfs/xfs_qmops.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_qmops.c	2004-03-25 00:17:16.000000000 +0000
@@ -54,7 +54,7 @@ xfs_dqvopchown_default(
 	return NULL;
 }
 
-xfs_qmops_t	xfs_qmcore_xfs = {
+xfs_qmops_t	xfs_qmcore_stub = {
 	.xfs_qminit		= (xfs_qminit_t) fs_noerr,
 	.xfs_qmdone		= (xfs_qmdone_t) fs_noerr,
 	.xfs_qmmount		= (xfs_qmmount_t) fs_noerr,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_quota.h linux-2.4.26-pre6/fs/xfs/xfs_quota.h
--- linux-2.4.25/fs/xfs/xfs_quota.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_quota.h	2004-03-25 00:19:56.000000000 +0000
@@ -347,9 +347,6 @@ extern int xfs_qm_dqcheck(xfs_disk_dquot
 
 extern struct bhv_vfsops xfs_qmops;
 
-extern void xfs_qm_init(void);
-extern void xfs_qm_exit(void);
-
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_QUOTA_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_vfsops.c linux-2.4.26-pre6/fs/xfs/xfs_vfsops.c
--- linux-2.4.25/fs/xfs/xfs_vfsops.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_vfsops.c	2004-03-25 00:20:38.000000000 +0000
@@ -451,9 +451,9 @@ xfs_mount(
 	 * Setup xfs_mount function vectors from available behaviors
 	 */
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
-	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_xfs;
+	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
-	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_xfs;
+	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
 	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/fs/xfs/xfs_vnodeops.c linux-2.4.26-pre6/fs/xfs/xfs_vnodeops.c
--- linux-2.4.25/fs/xfs/xfs_vnodeops.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/fs/xfs/xfs_vnodeops.c	2004-03-25 00:20:41.000000000 +0000
@@ -413,8 +413,9 @@ xfs_setattr(
 	} else {
 		if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) &&
 		    !(flags & ATTR_DMI)) {
+			int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
 			code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
-				vap->va_size, 0, AT_DELAY_FLAG(flags), NULL);
+				vap->va_size, 0, dmflags, NULL);
 			if (code) {
 				lock_flags = 0;
 				goto error_return;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acconfig.h linux-2.4.26-pre6/include/acpi/acconfig.h
--- linux-2.4.25/include/acpi/acconfig.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/acconfig.h	2004-03-25 00:18:10.000000000 +0000
@@ -64,7 +64,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20040116
+#define ACPI_CA_VERSION                 0x20040311
 
 /* Maximum objects in the various object caches */
 
@@ -185,6 +185,10 @@
 
 #define ACPI_SMBUS_BUFFER_SIZE          34
 
+/* Number of strings associated with the _OSI reserved method */
+
+#define ACPI_NUM_OSI_STRINGS            4
+
 
 /******************************************************************************
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acglobal.h linux-2.4.26-pre6/include/acpi/acglobal.h
--- linux-2.4.25/include/acpi/acglobal.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/acglobal.h	2004-03-25 00:16:47.000000000 +0000
@@ -57,6 +57,12 @@
 #define ACPI_EXTERN extern
 #endif
 
+/*
+ * Keep local copies of these FADT-based registers.  NOTE: These globals
+ * are first in this file for alignment reasons on 64-bit systems.
+ */
+ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
+ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
 
 /*****************************************************************************
  *
@@ -73,6 +79,14 @@ extern      u32                         
 
 extern      u32                                 acpi_gbl_nesting_level;
 
+/*****************************************************************************
+ *
+ * Runtime configuration
+ *
+ ****************************************************************************/
+
+ACPI_EXTERN u8                                  acpi_gbl_create_osi_method;
+ACPI_EXTERN u8                                  acpi_gbl_all_methods_serialized;
 
 /*****************************************************************************
  *
@@ -97,6 +111,11 @@ ACPI_EXTERN FADT_DESCRIPTOR            *
 ACPI_EXTERN struct acpi_table_header           *acpi_gbl_DSDT;
 ACPI_EXTERN FACS_DESCRIPTOR            *acpi_gbl_FACS;
 ACPI_EXTERN struct acpi_common_facs             acpi_gbl_common_fACS;
+/*
+ * Since there may be multiple SSDTs and PSDTS, a single pointer is not
+ * sufficient; Therefore, there isn't one!
+ */
+
 
 /*
  * Handle both ACPI 1.0 and ACPI 2.0 Integer widths
@@ -107,17 +126,6 @@ ACPI_EXTERN u8                          
 ACPI_EXTERN u8                                  acpi_gbl_integer_byte_width;
 ACPI_EXTERN u8                                  acpi_gbl_integer_nybble_width;
 
-/* Keep local copies of these FADT-based registers */
-
-ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
-ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
-
-/*
- * Since there may be multiple SSDTs and PSDTS, a single pointer is not
- * sufficient; Therefore, there isn't one!
- */
-
-
 /*
  * ACPI Table info arrays
  */
@@ -165,9 +173,11 @@ ACPI_EXTERN u8                          
 extern u8                                       acpi_gbl_shutdown;
 extern u32                                      acpi_gbl_startup_flags;
 extern const u8                                 acpi_gbl_decode_to8bit[8];
-extern const char                              *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT];
+extern const char                              *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
+extern const char                              *acpi_gbl_highest_dstate_names[4];
 extern const struct acpi_opcode_info            acpi_gbl_aml_op_info[AML_NUM_OPCODES];
 extern const char                              *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
+extern const char                              *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS];
 
 
 /*****************************************************************************
@@ -178,7 +188,7 @@ extern const char                       
 
 #define NUM_NS_TYPES                    ACPI_TYPE_INVALID+1
 
-#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
+#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
 #define NUM_PREDEFINED_NAMES            10
 #else
 #define NUM_PREDEFINED_NAMES            9
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acmacros.h linux-2.4.26-pre6/include/acpi/acmacros.h
--- linux-2.4.25/include/acpi/acmacros.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/acmacros.h	2004-03-25 00:20:14.000000000 +0000
@@ -681,7 +681,4 @@
 
 #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
 
-
-#define ACPI_GET_STACK_POINTER          _asm {mov eax, ebx}
-
 #endif /* ACMACROS_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acobject.h linux-2.4.26-pre6/include/acpi/acobject.h
--- linux-2.4.25/include/acpi/acobject.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/acobject.h	2004-03-25 00:17:35.000000000 +0000
@@ -180,7 +180,11 @@ struct acpi_object_event
 };
 
 
-#define INFINITE_CONCURRENCY        0xFF
+#define ACPI_INFINITE_CONCURRENCY   0xFF
+
+typedef
+acpi_status (*ACPI_INTERNAL_METHOD) (
+	struct acpi_walk_state          *walk_state);
 
 struct acpi_object_method
 {
@@ -190,6 +194,7 @@ struct acpi_object_method
 	u32                                     aml_length;
 	void                                    *semaphore;
 	u8                                      *aml_start;
+	ACPI_INTERNAL_METHOD            implementation;
 	u8                                      concurrency;
 	u8                                      thread_count;
 	acpi_owner_id                           owning_id;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acpi_bus.h linux-2.4.26-pre6/include/acpi/acpi_bus.h
--- linux-2.4.25/include/acpi/acpi_bus.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/acpi_bus.h	2004-03-25 00:21:48.000000000 +0000
@@ -35,8 +35,6 @@
 
 #include <acpi/acpi.h>
 
-extern int			acpi_disabled;
-
 /* TBD: Make dynamic */
 #define ACPI_MAX_HANDLES	10
 struct acpi_handle_list {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/actypes.h linux-2.4.26-pre6/include/acpi/actypes.h
--- linux-2.4.25/include/acpi/actypes.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/actypes.h	2004-03-25 00:20:27.000000000 +0000
@@ -349,7 +349,6 @@ typedef u64                             
 /*
  * Power state values
  */
-
 #define ACPI_STATE_UNKNOWN              (u8) 0xFF
 
 #define ACPI_STATE_S0                   (u8) 0
@@ -393,7 +392,6 @@ typedef u64                             
 #define ACPI_NOTIFY_BUS_MODE_MISMATCH   (u8) 6
 #define ACPI_NOTIFY_POWER_FAULT         (u8) 7
 
-
 /*
  *  Table types.  These values are passed to the table related APIs
  */
@@ -409,7 +407,6 @@ typedef u32                             
 #define ACPI_TABLE_MAX                  6
 #define NUM_ACPI_TABLE_TYPES            (ACPI_TABLE_MAX+1)
 
-
 /*
  * Types associated with ACPI names and objects.  The first group of
  * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition
@@ -794,7 +791,7 @@ acpi_status (*acpi_init_handler) (
 #define ACPI_INIT_DEVICE_INI        1
 
 
-/* Address Spaces (Operation Regions */
+/* Address Spaces (For Operation Regions) */
 
 typedef
 acpi_status (*acpi_adr_space_handler) (
@@ -880,7 +877,8 @@ struct acpi_device_info
 {
 	ACPI_COMMON_OBJ_INFO;
 
-	u32                                 valid;              /* Indicates which fields are valid */
+	u8                                  highest_dstates[4]; /* _sx_d values 0xFF indicates not valid */
+	u32                                 valid;              /* Indicates which fields below are valid */
 	u32                                 current_status;     /* _STA value */
 	acpi_integer                        address;            /* _ADR value if any */
 	struct acpi_device_id               hardware_id;        /* _HID value if any */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acutils.h linux-2.4.26-pre6/include/acpi/acutils.h
--- linux-2.4.25/include/acpi/acutils.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/acutils.h	2004-03-25 00:16:58.000000000 +0000
@@ -52,7 +52,6 @@ acpi_status (*acpi_pkg_callback) (
 	union acpi_generic_state        *state,
 	void                            *context);
 
-
 acpi_status
 acpi_ut_walk_package_tree (
 	union acpi_operand_object       *source_object,
@@ -60,7 +59,6 @@ acpi_ut_walk_package_tree (
 	acpi_pkg_callback               walk_callback,
 	void                            *context);
 
-
 struct acpi_pkg_info
 {
 	u8                              *free_space;
@@ -476,6 +474,10 @@ acpi_ut_delete_internal_object_list (
 
 
 acpi_status
+acpi_ut_osi_implementation (
+	struct acpi_walk_state          *walk_state);
+
+acpi_status
 acpi_ut_evaluate_object (
 	struct acpi_namespace_node      *prefix_node,
 	char                            *path,
@@ -508,6 +510,10 @@ acpi_ut_execute_UID (
 	struct acpi_namespace_node      *device_node,
 	struct acpi_device_id           *uid);
 
+acpi_status
+acpi_ut_execute_sxds (
+	struct acpi_namespace_node      *device_node,
+	u8                              *highest);
 
 /*
  * ut_mutex - mutual exclusion interfaces
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/amlcode.h linux-2.4.26-pre6/include/acpi/amlcode.h
--- linux-2.4.25/include/acpi/amlcode.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/acpi/amlcode.h	2004-03-25 00:20:45.000000000 +0000
@@ -496,11 +496,17 @@ typedef enum
 } AML_ACCESS_ATTRIBUTE;
 
 
-/* bit fields in method_flags byte */
+/* Bit fields in method_flags byte */
 
-#define METHOD_FLAGS_ARG_COUNT      0x07
-#define METHOD_FLAGS_SERIALIZED     0x08
-#define METHOD_FLAGS_SYNCH_LEVEL    0xF0
+#define AML_METHOD_ARG_COUNT        0x07
+#define AML_METHOD_SERIALIZED       0x08
+#define AML_METHOD_SYNCH_LEVEL      0xF0
+
+/* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */
+
+#define AML_METHOD_INTERNAL_ONLY    0x01
+#define AML_METHOD_RESERVED1        0x02
+#define AML_METHOD_RESERVED2        0x04
 
 
 #endif /* __AMLCODE_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-i386/acpi.h linux-2.4.26-pre6/include/asm-i386/acpi.h
--- linux-2.4.25/include/asm-i386/acpi.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-i386/acpi.h	2004-03-25 00:17:23.000000000 +0000
@@ -61,33 +61,36 @@
  *  Immediate values in the assembly are preceded by "$" as in "$0x1"
  *  The final asm parameter are the operation altered non-output registers.
  */
+
+static inline int
+__acpi_acquire_global_lock (unsigned int *lock)
+{
+	unsigned int old, new, val;
+	do {
+		old = *lock;
+		new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
+		val = cmpxchg(lock, old, new);
+	} while (unlikely (val != old));
+	return (new < 3) ? -1 : 0;
+}
+
+static inline int
+__acpi_release_global_lock (unsigned int *lock)
+{
+	unsigned int old, new, val;
+	do {
+		old = *lock;
+		new = old & ~0x3;
+		val = cmpxchg(lock, old, new);
+	} while (unlikely (val != old));
+	return old & 0x1;
+}
+
 #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
-    do { \
-        int dummy; \
-        asm("1:     movl (%1),%%eax;" \
-            "movl   %%eax,%%edx;" \
-            "andl   %2,%%edx;" \
-            "btsl   $0x1,%%edx;" \
-            "adcl   $0x0,%%edx;" \
-            "lock;  cmpxchgl %%edx,(%1);" \
-            "jnz    1b;" \
-            "cmpb   $0x3,%%dl;" \
-            "sbbl   %%eax,%%eax" \
-            :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \
-    } while(0)
+	((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr))
 
 #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \
-    do { \
-        int dummy; \
-        asm("1:     movl (%1),%%eax;" \
-            "movl   %%eax,%%edx;" \
-            "andl   %2,%%edx;" \
-            "lock;  cmpxchgl %%edx,(%1);" \
-            "jnz    1b;" \
-            "andl   $0x1,%%eax" \
-            :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \
-    } while(0)
-
+	((Acq) = __acpi_release_global_lock((unsigned int *) GLptr))
 
 /*
  * Math helper asm macros
@@ -110,6 +113,10 @@
 extern int acpi_lapic;
 extern int acpi_ioapic;
 extern int acpi_noirq;
+extern int acpi_strict;
+extern int acpi_disabled;
+extern int acpi_ht;
+static inline void disable_acpi(void) { acpi_disabled = 1; acpi_ht = 0; }
 
 /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
 #define FIX_ACPI_PAGES 4
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-i386/highmem.h linux-2.4.26-pre6/include/asm-i386/highmem.h
--- linux-2.4.25/include/asm-i386/highmem.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-i386/highmem.h	2004-03-25 00:17:28.000000000 +0000
@@ -46,7 +46,7 @@ extern void kmap_init(void) __init;
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
-#define PKMAP_BASE (0xfe000000UL)
+#define PKMAP_BASE (0xff800000UL)
 #ifdef CONFIG_X86_PAE
 #define LAST_PKMAP 512
 #else
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-i386/mpspec.h linux-2.4.26-pre6/include/asm-i386/mpspec.h
--- linux-2.4.25/include/asm-i386/mpspec.h	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-i386/mpspec.h	2004-03-25 00:16:50.000000000 +0000
@@ -227,10 +227,7 @@ extern void mp_register_lapic_address (u
 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_config_ioapic_for_sci(int irq);
 extern void mp_parse_prt (void);
-#else /*!CONFIG_X86_IO_APIC*/
-static inline void mp_config_ioapic_for_sci(int irq) { }
 #endif /*!CONFIG_X86_IO_APIC*/
 
 #endif /*CONFIG_ACPI_BOOT*/
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/a.out.h linux-2.4.26-pre6/include/asm-ia64/a.out.h
--- linux-2.4.25/include/asm-ia64/a.out.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/a.out.h	2004-03-25 00:21:29.000000000 +0000
@@ -7,8 +7,8 @@
  * probably would be better to clean up binfmt_elf.c so it does not
  * necessarily depend on there being a.out support.
  *
- * Copyright (C) 1998-2000, 2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2000, 2002
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
 #include <linux/types.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/acpi.h linux-2.4.26-pre6/include/asm-ia64/acpi.h
--- linux-2.4.25/include/asm-ia64/acpi.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/acpi.h	2004-03-25 00:22:05.000000000 +0000
@@ -96,6 +96,10 @@
 		:"=r"(Acq):"r"(GLptr):"r2","r29","r30","memory"); \
 	} while (0)
 
+#define acpi_disabled 0	/* ACPI always enabled */
+#define acpi_strict 1	/* no ACPI workarounds */
+static inline void disable_acpi(void) { }
+
 const char *acpi_get_sysname (void);
 int acpi_request_vector (u32 int_type);
 int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/bugs.h linux-2.4.26-pre6/include/asm-ia64/bugs.h
--- linux-2.4.25/include/asm-ia64/bugs.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/bugs.h	2004-03-25 00:22:04.000000000 +0000
@@ -4,8 +4,10 @@
  * Needs:
  *	void check_bugs(void);
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-alpha/bugs.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>,  Hewlett-Packard Co.
  */
 
 #include <asm/processor.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/byteorder.h linux-2.4.26-pre6/include/asm-ia64/byteorder.h
--- linux-2.4.25/include/asm-ia64/byteorder.h	2001-04-05 19:51:47.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/byteorder.h	2004-03-25 00:17:34.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_BYTEORDER_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
 #include <asm/types.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/checksum.h linux-2.4.26-pre6/include/asm-ia64/checksum.h
--- linux-2.4.25/include/asm-ia64/checksum.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/checksum.h	2004-03-25 00:16:52.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_CHECKSUM_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/current.h linux-2.4.26-pre6/include/asm-ia64/current.h
--- linux-2.4.25/include/asm-ia64/current.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/current.h	2004-03-25 00:21:25.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_CURRENT_H
 
 /*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 /* In kernel mode, thread pointer (r13) is used to point to the
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/errno.h linux-2.4.26-pre6/include/asm-ia64/errno.h
--- linux-2.4.25/include/asm-ia64/errno.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/errno.h	2004-03-25 00:19:05.000000000 +0000
@@ -2,10 +2,10 @@
 #define _ASM_IA64_ERRNO_H
 
 /*
- * This is derived from the Linux/x86 version.
+ * Based on <asm-i386/errno.h>.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define	EPERM		 1	/* Operation not permitted */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/fcntl.h linux-2.4.26-pre6/include/asm-ia64/fcntl.h
--- linux-2.4.25/include/asm-ia64/fcntl.h	2000-10-10 00:54:58.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/fcntl.h	2004-03-25 00:20:14.000000000 +0000
@@ -1,10 +1,10 @@
 #ifndef _ASM_IA64_FCNTL_H
 #define _ASM_IA64_FCNTL_H
 /*
- * This is mostly compatible with Linux/x86.
+ * Based on <asm-i386/fcntl.h>.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/ioctl.h linux-2.4.26-pre6/include/asm-ia64/ioctl.h
--- linux-2.4.25/include/asm-ia64/ioctl.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/ioctl.h	2004-03-25 00:19:32.000000000 +0000
@@ -2,10 +2,10 @@
 #define _ASM_IA64_IOCTL_H
 
 /*
- * This is mostly derived from the Linux/x86 version.
+ * Based on <asm-i386/ioctl.h>.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 /* ioctl command encoding: 32 bits total, command in lower 16 bits,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/ioctls.h linux-2.4.26-pre6/include/asm-ia64/ioctls.h
--- linux-2.4.25/include/asm-ia64/ioctls.h	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/ioctls.h	2004-03-25 00:17:44.000000000 +0000
@@ -2,8 +2,10 @@
 #define _ASM_IA64_IOCTLS_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/ioctls.h>
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/ioctl.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/mca.h linux-2.4.26-pre6/include/asm-ia64/mca.h
--- linux-2.4.25/include/asm-ia64/mca.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/mca.h	2004-03-25 00:18:12.000000000 +0000
@@ -2,7 +2,7 @@
  * File:	mca.h
  * Purpose:	Machine check handling specific defines
  *
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander (vijay@engr.sgi.com)
  * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
  */
@@ -17,23 +17,8 @@
 #include <asm/processor.h>
 #include <asm/mca_asm.h>
 
-/* These are the return codes from all the IA64_MCA specific interfaces */
-typedef	int ia64_mca_return_code_t;
-
-enum {
-	IA64_MCA_SUCCESS	=	0,
-	IA64_MCA_FAILURE	=	1
-};
-
 #define IA64_MCA_RENDEZ_TIMEOUT		(20 * 1000)	/* value in milliseconds - 20 seconds */
 
-#define IA64_CMC_INT_DISABLE		0
-#define IA64_CMC_INT_ENABLE		1
-
-
-typedef u32 int_vector_t;
-typedef u64 millisec_t;
-
 typedef union cmcv_reg_u {
 	u64	cmcv_regval;
 	struct	{
@@ -50,10 +35,6 @@ typedef union cmcv_reg_u {
 #define cmcv_mask		cmcv_reg_s.cmcr_mask
 #define cmcv_vector		cmcv_reg_s.cmcr_vector
 
-
-#define IA64_MCA_UCMC_HANDLER_SIZE	0x10
-#define IA64_INIT_HANDLER_SIZE		0x10
-
 enum {
 	IA64_MCA_RENDEZ_CHECKIN_NOTDONE	=	0x0,
 	IA64_MCA_RENDEZ_CHECKIN_DONE	=	0x1
@@ -82,16 +63,6 @@ typedef struct ia64_mc_info_s {
 
 } ia64_mc_info_t;
 
-/* Possible rendez states passed from SAL to OS during MCA
- * handoff
- */
-enum {
-	IA64_MCA_RENDEZ_NOT_RQD		=	0x0,
-	IA64_MCA_RENDEZ_DONE_WITHOUT_INIT	=	0x1,
-	IA64_MCA_RENDEZ_DONE_WITH_INIT		=	0x2,
-	IA64_MCA_RENDEZ_FAILURE			=	-1
-};
-
 typedef struct ia64_mca_sal_to_os_state_s {
 	u64		imsto_os_gp;		/* GP of the os registered with the SAL */
 	u64		imsto_pal_proc;		/* PAL_PROC entry point - physical addr */
@@ -133,41 +104,13 @@ typedef struct ia64_mca_os_to_sal_state_
 						 */
 } ia64_mca_os_to_sal_state_t;
 
-typedef int (*prfunc_t)(const char * fmt, ...);
-
 extern void ia64_mca_init(void);
 extern void ia64_os_mca_dispatch(void);
 extern void ia64_os_mca_dispatch_end(void);
 extern void ia64_mca_ucmc_handler(void);
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
-extern void ia64_mca_rendez_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cmc_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cmc_int_caller(int,void *,struct pt_regs *);
-extern void ia64_mca_cpe_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cpe_int_caller(int,void *,struct pt_regs *);
-extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
-extern int  ia64_mca_check_errors(void);
-
-#define PLATFORM_CALL(fn, args)	printk("Platform call TBD\n")
 
-#define platform_mem_dev_err_print ia64_log_prt_oem_data
-#define platform_pci_bus_err_print ia64_log_prt_oem_data
-#define platform_pci_comp_err_print ia64_log_prt_oem_data
-#define platform_plat_specific_err_print ia64_log_prt_oem_data
-#define platform_host_ctlr_err_print ia64_log_prt_oem_data
-#define platform_plat_bus_err_print ia64_log_prt_oem_data
-
-#undef	MCA_TEST
-
-#undef IA64_MCA_DEBUG_INFO
-
-#if defined(IA64_MCA_DEBUG_INFO)
-# define IA64_MCA_DEBUG(fmt...)	printk(fmt)
-#else
-# define IA64_MCA_DEBUG(fmt...)
-#endif
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_MCA_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/mman.h linux-2.4.26-pre6/include/asm-ia64/mman.h
--- linux-2.4.25/include/asm-ia64/mman.h	2001-01-04 20:50:17.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/mman.h	2004-03-25 00:19:58.000000000 +0000
@@ -2,8 +2,10 @@
 #define _ASM_IA64_MMAN_H
 
 /*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/mman.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define PROT_READ	0x1		/* page can be read */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/namei.h linux-2.4.26-pre6/include/asm-ia64/namei.h
--- linux-2.4.25/include/asm-ia64/namei.h	2001-11-09 22:26:17.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/namei.h	2004-03-25 00:21:23.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_NAMEI_H
 
 /*
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999, 2001
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/ptrace.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/page.h linux-2.4.26-pre6/include/asm-ia64/page.h
--- linux-2.4.25/include/asm-ia64/page.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/page.h	2004-03-25 00:17:36.000000000 +0000
@@ -120,7 +120,13 @@ extern int  is_invalid_hugepage_range(un
 #define is_invalid_hugepage_range(addr, len) 0
 #endif
 
-#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+# define ia64_abort()	__builtin_trap()
+#else
+# define ia64_abort()	(*(volatile int *) 0 = 0)
+#endif
+
+#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
 static __inline__ int
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/param.h linux-2.4.26-pre6/include/asm-ia64/param.h
--- linux-2.4.25/include/asm-ia64/param.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/param.h	2004-03-25 00:19:58.000000000 +0000
@@ -4,8 +4,10 @@
 /*
  * Fundamental kernel parameters.
  *
- * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/param.h>.
+ *
+ * Modified 1998, 1999, 2002-2003
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define EXEC_PAGESIZE	65536
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/poll.h linux-2.4.26-pre6/include/asm-ia64/poll.h
--- linux-2.4.25/include/asm-ia64/poll.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/poll.h	2004-03-25 00:20:32.000000000 +0000
@@ -2,10 +2,10 @@
 #define _ASM_IA64_POLL_H
 
 /*
- * poll(2) bit definitions.  Chosen to be compatible with Linux/x86.
+ * poll(2) bit definitions.  Based on <asm-i386/poll.h>.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define POLLIN		0x0001
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/posix_types.h linux-2.4.26-pre6/include/asm-ia64/posix_types.h
--- linux-2.4.25/include/asm-ia64/posix_types.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/posix_types.h	2004-03-25 00:18:49.000000000 +0000
@@ -6,8 +6,10 @@
  * be a little careful about namespace pollution etc.  Also, we cannot
  * assume GCC is being used.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-alpha/posix_types.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 typedef unsigned int	__kernel_dev_t;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/processor.h linux-2.4.26-pre6/include/asm-ia64/processor.h
--- linux-2.4.25/include/asm-ia64/processor.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/processor.h	2004-03-25 00:18:59.000000000 +0000
@@ -927,24 +927,13 @@ ia64_get_dbr (__u64 regnum)
 	return retval;
 }
 
-/* XXX remove the handcoded version once we have a sufficiently clever compiler... */
-#ifdef SMART_COMPILER
-# define ia64_rotr(w,n)				\
-  ({						\
-	__u64 _w = (w), _n = (n);		\
-						\
-	(_w >> _n) | (_w << (64 - _n));		\
-  })
-#else
-# define ia64_rotr(w,n)							\
-  ({									\
-	__u64 result;							\
-	asm ("shrp %0=%1,%1,%2" : "=r"(result) : "r"(w), "i"(n));	\
-	result;								\
-  })
-#endif
+static inline __u64
+ia64_rotr (__u64 w, __u64 n)
+{
+	return (w >> n) | (w << (64 - n));
+}
 
-#define ia64_rotl(w,n)	ia64_rotr((w),(64)-(n))
+#define ia64_rotl(w,n)	ia64_rotr((w), (64) - (n))
 
 static inline __u64
 ia64_thash (__u64 addr)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/resource.h linux-2.4.26-pre6/include/asm-ia64/resource.h
--- linux-2.4.25/include/asm-ia64/resource.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/resource.h	2004-03-25 00:21:13.000000000 +0000
@@ -4,8 +4,10 @@
 /*
  * Resource limits
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/resource.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/ustack.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/scatterlist.h linux-2.4.26-pre6/include/asm-ia64/scatterlist.h
--- linux-2.4.25/include/asm-ia64/scatterlist.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/scatterlist.h	2004-03-25 00:20:07.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_SCATTERLIST_H
 
 /*
- * Copyright (C) 1998-1999, 2001-2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-1999, 2001-2002
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 struct scatterlist {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/siginfo.h linux-2.4.26-pre6/include/asm-ia64/siginfo.h
--- linux-2.4.25/include/asm-ia64/siginfo.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/siginfo.h	2004-03-25 00:21:59.000000000 +0000
@@ -2,8 +2,10 @@
 #define _ASM_IA64_SIGINFO_H
 
 /*
- * Copyright (C) 1998-2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/siginfo.h>.
+ *
+ * Modified 1998-2002
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <linux/types.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/signal.h linux-2.4.26-pre6/include/asm-ia64/signal.h
--- linux-2.4.25/include/asm-ia64/signal.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/signal.h	2004-03-25 00:17:36.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_SIGNAL_H
 
 /*
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2001
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * Unfortunately, this file is being included by bits/signal.h in
  * glibc-2.x.  Hence the #ifdef __KERNEL__ ugliness.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/socket.h linux-2.4.26-pre6/include/asm-ia64/socket.h
--- linux-2.4.25/include/asm-ia64/socket.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/socket.h	2004-03-25 00:16:51.000000000 +0000
@@ -2,10 +2,12 @@
 #define _ASM_IA64_SOCKET_H
 
 /*
- * Socket related defines.  This mostly mirrors the Linux/x86 version.
+ * Socket related defines.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/socket.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/sockios.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/sockios.h linux-2.4.26-pre6/include/asm-ia64/sockios.h
--- linux-2.4.25/include/asm-ia64/sockios.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/sockios.h	2004-03-25 00:20:29.000000000 +0000
@@ -2,11 +2,12 @@
 #define _ASM_IA64_SOCKIOS_H
 
 /*
- * Socket-level I/O control calls.  This mostly mirrors the Linux/x86
- * version.
+ * Socket-level I/O control calls.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/sockios.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 #define FIOSETOWN 	0x8901
 #define SIOCSPGRP	0x8902
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/stat.h linux-2.4.26-pre6/include/asm-ia64/stat.h
--- linux-2.4.25/include/asm-ia64/stat.h	2000-06-22 14:09:45.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/stat.h	2004-03-25 00:19:01.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_STAT_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 struct stat {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/statfs.h linux-2.4.26-pre6/include/asm-ia64/statfs.h
--- linux-2.4.25/include/asm-ia64/statfs.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/statfs.h	2004-03-25 00:20:11.000000000 +0000
@@ -2,8 +2,10 @@
 #define _ASM_IA64_STATFS_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/statfs.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 # ifndef __KERNEL_STRICT_NAMES
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/termbits.h linux-2.4.26-pre6/include/asm-ia64/termbits.h
--- linux-2.4.25/include/asm-ia64/termbits.h	2000-02-07 02:42:40.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/termbits.h	2004-03-25 00:20:33.000000000 +0000
@@ -2,8 +2,10 @@
 #define _ASM_IA64_TERMBITS_H
 
 /*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/termbits.h>.
+ *
+ * Modified 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * 99/01/28	Added new baudrates
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/termios.h linux-2.4.26-pre6/include/asm-ia64/termios.h
--- linux-2.4.25/include/asm-ia64/termios.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/termios.h	2004-03-25 00:20:37.000000000 +0000
@@ -2,8 +2,8 @@
 #define _ASM_IA64_TERMIOS_H
 
 /*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * 99/01/28	Added N_IRDA and N_SMSBLOCK
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/types.h linux-2.4.26-pre6/include/asm-ia64/types.h
--- linux-2.4.25/include/asm-ia64/types.h	2000-04-21 22:21:24.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/types.h	2004-03-25 00:18:03.000000000 +0000
@@ -8,8 +8,10 @@
  * not a major issue.  However, for interoperability, libraries still
  * need to be careful to avoid a name clashes.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-alpha/types.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #ifdef __ASSEMBLY__
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/uaccess.h linux-2.4.26-pre6/include/asm-ia64/uaccess.h
--- linux-2.4.25/include/asm-ia64/uaccess.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/uaccess.h	2004-03-25 00:18:45.000000000 +0000
@@ -26,6 +26,8 @@
  * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
  * then resumes execution at the continuation point.
  *
+ * Based on <asm-alpha/uaccess.h>.
+ *
  * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/unaligned.h linux-2.4.26-pre6/include/asm-ia64/unaligned.h
--- linux-2.4.25/include/asm-ia64/unaligned.h	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/unaligned.h	2004-03-25 00:22:03.000000000 +0000
@@ -4,8 +4,9 @@
 #include <linux/types.h>
 
 /*
- * The main single-value unaligned transfer routines.  Derived from
- * the Linux/Alpha version.
+ * The main single-value unaligned transfer routines.
+ *
+ * Based on <asm-alpha/unaligned.h>.
  *
  * Copyright (C) 1998, 1999, 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/unwind.h linux-2.4.26-pre6/include/asm-ia64/unwind.h
--- linux-2.4.25/include/asm-ia64/unwind.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/unwind.h	2004-03-25 00:20:12.000000000 +0000
@@ -93,6 +93,12 @@ struct unw_frame_info {
  * The official API follows below:
  */
 
+struct unw_table_entry {
+	u64 start_offset;
+	u64 end_offset;
+	u64 info_offset;
+};
+
 /*
  * Initialize unwind support.
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ia64/user.h linux-2.4.26-pre6/include/asm-ia64/user.h
--- linux-2.4.25/include/asm-ia64/user.h	2001-11-09 22:26:17.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ia64/user.h	2004-03-25 00:21:09.000000000 +0000
@@ -24,8 +24,8 @@
  *	current->start_stack, so we round each of these in order to be able
  *	to write an integer number of pages.
  *
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999, 2001
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <linux/ptrace.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-m68k/keyboard.h linux-2.4.26-pre6/include/asm-m68k/keyboard.h
--- linux-2.4.25/include/asm-m68k/keyboard.h	2001-08-12 18:13:59.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-m68k/keyboard.h	2004-03-25 00:20:36.000000000 +0000
@@ -65,6 +65,11 @@ static __inline__ void kbd_leds(unsigned
 #define kbd_request_region()
 #define kbd_request_irq(handler)
 
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() in_8(KBD_DATA_REG)
+#define kbd_read_status() in_8(KBD_STATUS_REG)
+#define kbd_write_output(val) out_8(KBD_DATA_REG, val)
+#define kbd_write_command(val) out_8(KBD_CNTL_REG, val)
 extern unsigned int SYSRQ_KEY;
 
 #endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/cpm2.h linux-2.4.26-pre6/include/asm-ppc/cpm2.h
--- linux-2.4.25/include/asm-ppc/cpm2.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/cpm2.h	2004-03-25 00:19:39.000000000 +0000
@@ -0,0 +1,1037 @@
+/*
+ * Communication Processor Module v2.
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the CPM2 internal
+ * memory map.  See immap_cpm2.h for details.
+ */
+#ifdef __KERNEL__
+#ifndef __CPM2__
+#define __CPM2__
+
+#include <asm/immap_cpm2.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST	((uint)0x80000000)
+#define CPM_CR_PAGE	((uint)0x7c000000)
+#define CPM_CR_SBLOCK	((uint)0x03e00000)
+#define CPM_CR_FLG	((uint)0x00010000)
+#define CPM_CR_MCN	((uint)0x00003fc0)
+#define CPM_CR_OPCODE	((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK	(0x04)
+#define CPM_CR_SCC2_SBLOCK	(0x05)
+#define CPM_CR_SCC3_SBLOCK	(0x06)
+#define CPM_CR_SCC4_SBLOCK	(0x07)
+#define CPM_CR_SMC1_SBLOCK	(0x08)
+#define CPM_CR_SMC2_SBLOCK	(0x09)
+#define CPM_CR_SPI_SBLOCK	(0x0a)
+#define CPM_CR_I2C_SBLOCK	(0x0b)
+#define CPM_CR_TIMER_SBLOCK	(0x0f)
+#define CPM_CR_RAND_SBLOCK	(0x0e)
+#define CPM_CR_FCC1_SBLOCK	(0x10)
+#define CPM_CR_FCC2_SBLOCK	(0x11)
+#define CPM_CR_FCC3_SBLOCK	(0x12)
+#define CPM_CR_IDMA1_SBLOCK	(0x14)
+#define CPM_CR_IDMA2_SBLOCK	(0x15)
+#define CPM_CR_IDMA3_SBLOCK	(0x16)
+#define CPM_CR_IDMA4_SBLOCK	(0x17)
+#define CPM_CR_MCC1_SBLOCK	(0x1c)
+
+#define CPM_CR_SCC1_PAGE	(0x00)
+#define CPM_CR_SCC2_PAGE	(0x01)
+#define CPM_CR_SCC3_PAGE	(0x02)
+#define CPM_CR_SCC4_PAGE	(0x03)
+#define CPM_CR_SMC1_PAGE	(0x07)
+#define CPM_CR_SMC2_PAGE	(0x08)
+#define CPM_CR_SPI_PAGE		(0x09)
+#define CPM_CR_I2C_PAGE		(0x0a)
+#define CPM_CR_TIMER_PAGE	(0x0a)
+#define CPM_CR_RAND_PAGE	(0x0a)
+#define CPM_CR_FCC1_PAGE	(0x04)
+#define CPM_CR_FCC2_PAGE	(0x05)
+#define CPM_CR_FCC3_PAGE	(0x06)
+#define CPM_CR_IDMA1_PAGE	(0x07)
+#define CPM_CR_IDMA2_PAGE	(0x08)
+#define CPM_CR_IDMA3_PAGE	(0x09)
+#define CPM_CR_IDMA4_PAGE	(0x0a)
+#define CPM_CR_MCC1_PAGE	(0x07)
+#define CPM_CR_MCC2_PAGE	(0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX		((ushort)0x0000)
+#define CPM_CR_INIT_RX		((ushort)0x0001)
+#define CPM_CR_INIT_TX		((ushort)0x0002)
+#define CPM_CR_HUNT_MODE	((ushort)0x0003)
+#define CPM_CR_STOP_TX		((ushort)0x0004)
+#define CPM_CR_RESTART_TX	((ushort)0x0006)
+#define CPM_CR_SET_GADDR	((ushort)0x0008)
+#define CPM_CR_START_IDMA	((ushort)0x0009)
+#define CPM_CR_STOP_IDMA	((ushort)0x000b)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses.  The first 16K is available for almost
+ * any CPM use, so we put the BDs there.  The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that.  All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE	((uint)128)
+#define CPM_DP_NOSPACE		((uint)0x7fffffff)
+#ifdef CONFIG_8272
+#define CPM_DATAONLY_SIZE	((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x00009000)
+#else
+#define CPM_DATAONLY_SIZE	((uint)(16 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x0000b000)
+#endif
+
+/* The number of pages of host memory we allocate for CPM.  This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES	2
+
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+extern		cpm_cpm2_t	*cpmp;	 /* Pointer to comm processor */
+uint		cpm2_dpalloc(uint size, uint align);
+uint		cpm2_hostalloc(uint size, uint align);
+void		cpm2_setbrg(uint brg, uint rate);
+void		cpm2_fastbrg(uint brg, uint rate, int div16);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+	ushort	cbd_sc;		/* Status and Control */
+	ushort	cbd_datlen;	/* Data length in buffer */
+	uint	cbd_bufaddr;	/* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY	((ushort)0x8000)	/* Receive is empty */
+#define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
+#define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
+#define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
+#define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame */
+#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
+#define BD_SC_ID	((ushort)0x0100)	/* Rec'd too many idles */
+#define BD_SC_P		((ushort)0x0100)	/* xmt preamble */
+#define BD_SC_BR	((ushort)0x0020)	/* Break received */
+#define BD_SC_FR	((ushort)0x0010)	/* Framing error */
+#define BD_SC_PR	((ushort)0x0008)	/* Parity error */
+#define BD_SC_OV	((ushort)0x0002)	/* Overrun */
+#define BD_SC_CD	((ushort)0x0001)	/* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
+#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
+#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
+#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
+#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#define PROFF_SCC1		((uint)0x8000)
+#define PROFF_SCC2		((uint)0x8100)
+#define PROFF_SCC3		((uint)0x8200)
+#define PROFF_SCC4		((uint)0x8300)
+#define PROFF_FCC1		((uint)0x8400)
+#define PROFF_FCC2		((uint)0x8500)
+#define PROFF_FCC3		((uint)0x8600)
+#define PROFF_MCC1		((uint)0x8700)
+#define PROFF_SMC1_BASE		((uint)0x87fc)
+#define PROFF_IDMA1_BASE	((uint)0x87fe)
+#define PROFF_MCC2		((uint)0x8800)
+#define PROFF_SMC2_BASE		((uint)0x88fc)
+#define PROFF_IDMA2_BASE	((uint)0x88fe)
+#define PROFF_SPI_BASE		((uint)0x89fc)
+#define PROFF_IDMA3_BASE	((uint)0x89fe)
+#define PROFF_TIMERS		((uint)0x8ae0)
+#define PROFF_REVNUM		((uint)0x8af0)
+#define PROFF_RAND		((uint)0x8af8)
+#define PROFF_I2C_BASE		((uint)0x8afc)
+#define PROFF_IDMA4_BASE	((uint)0x8afe)
+
+/* The SMCs are relocated to any of the first eight DPRAM pages.
+ * We will fix these at the first locations of DPRAM, until we
+ * get some microcode patches :-).
+ * The parameter ram space for the SMCs is fifty-some bytes, and
+ * they are required to start on a 64 byte boundary.
+ */
+#define PROFF_SMC1	(0)
+#define PROFF_SMC2	(64)
+
+
+/* Define enough so I can at least use the serial port as a UART.
+ */
+typedef struct smc_uart {
+	ushort	smc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	smc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	smc_rfcr;	/* Rx function code */
+	u_char	smc_tfcr;	/* Tx function code */
+	ushort	smc_mrblr;	/* Max receive buffer length */
+	uint	smc_rstate;	/* Internal */
+	uint	smc_idp;	/* Internal */
+	ushort	smc_rbptr;	/* Internal */
+	ushort	smc_ibc;	/* Internal */
+	uint	smc_rxtmp;	/* Internal */
+	uint	smc_tstate;	/* Internal */
+	uint	smc_tdp;	/* Internal */
+	ushort	smc_tbptr;	/* Internal */
+	ushort	smc_tbc;	/* Internal */
+	uint	smc_txtmp;	/* Internal */
+	ushort	smc_maxidl;	/* Maximum idle characters */
+	ushort	smc_tmpidl;	/* Temporary idle counter */
+	ushort	smc_brklen;	/* Last received break length */
+	ushort	smc_brkec;	/* rcv'd break condition counter */
+	ushort	smc_brkcr;	/* xmt break count register */
+	ushort	smc_rmask;	/* Temporary bit mask */
+	uint	smc_stmp;	/* SDMA Temp */
+} smc_uart_t;
+
+/* SMC uart mode register (Internal memory map).
+*/
+#define SMCMR_REN	((ushort)0x0001)
+#define SMCMR_TEN	((ushort)0x0002)
+#define SMCMR_DM	((ushort)0x000c)
+#define SMCMR_SM_GCI	((ushort)0x0000)
+#define SMCMR_SM_UART	((ushort)0x0020)
+#define SMCMR_SM_TRANS	((ushort)0x0030)
+#define SMCMR_SM_MASK	((ushort)0x0030)
+#define SMCMR_PM_EVEN	((ushort)0x0100)	/* Even parity, else odd */
+#define SMCMR_REVD	SMCMR_PM_EVEN
+#define SMCMR_PEN	((ushort)0x0200)	/* Parity enable */
+#define SMCMR_BS	SMCMR_PEN
+#define SMCMR_SL	((ushort)0x0400)	/* Two stops, else one */
+#define SMCR_CLEN_MASK	((ushort)0x7800)	/* Character length */
+#define smcr_mk_clen(C)	(((C) << 11) & SMCR_CLEN_MASK)
+
+/* SMC Event and Mask register.
+*/
+#define SMCM_BRKE       ((unsigned char)0x40)   /* When in UART Mode */
+#define SMCM_BRK        ((unsigned char)0x10)   /* When in UART Mode */
+#define SMCM_TXE	((unsigned char)0x10)
+#define SMCM_BSY	((unsigned char)0x04)
+#define SMCM_TX		((unsigned char)0x02)
+#define SMCM_RX		((unsigned char)0x01)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST		((uint)0x00020000)
+#define CPM_BRG_EN		((uint)0x00010000)
+#define CPM_BRG_EXTC_INT	((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9	((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15	((uint)0x00008000)
+#define CPM_BRG_ATB		((uint)0x00002000)
+#define CPM_BRG_CD_MASK		((uint)0x00001ffe)
+#define CPM_BRG_DIV16		((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP		((uint)0x00040000)
+#define SCC_GSMRH_GDE		((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT	((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC	((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC	((uint)0x00000000)
+#define SCC_GSMRH_REVD		((uint)0x00002000)
+#define SCC_GSMRH_TRX		((uint)0x00001000)
+#define SCC_GSMRH_TTX		((uint)0x00000800)
+#define SCC_GSMRH_CDP		((uint)0x00000400)
+#define SCC_GSMRH_CTSP		((uint)0x00000200)
+#define SCC_GSMRH_CDS		((uint)0x00000100)
+#define SCC_GSMRH_CTSS		((uint)0x00000080)
+#define SCC_GSMRH_TFL		((uint)0x00000040)
+#define SCC_GSMRH_RFW		((uint)0x00000020)
+#define SCC_GSMRH_TXSY		((uint)0x00000010)
+#define SCC_GSMRH_SYNL16	((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8		((uint)0x00000008)
+#define SCC_GSMRH_SYNL4		((uint)0x00000004)
+#define SCC_GSMRH_RTSM		((uint)0x00000002)
+#define SCC_GSMRH_RSYN		((uint)0x00000001)
+
+#define SCC_GSMRL_SIR		((uint)0x80000000)	/* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE	((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG	((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS	((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH	((uint)0x00000000)
+#define SCC_GSMRL_TCI		((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3	((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4	((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14	((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF	((uint)0x00000000)
+#define SCC_GSMRL_RINV		((uint)0x02000000)
+#define SCC_GSMRL_TINV		((uint)0x01000000)
+#define SCC_GSMRL_TPL_128	((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64	((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48	((uint)0x00800000)
+#define SCC_GSMRL_TPL_32	((uint)0x00600000)
+#define SCC_GSMRL_TPL_16	((uint)0x00400000)
+#define SCC_GSMRL_TPL_8		((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE	((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1	((uint)0x00180000)
+#define SCC_GSMRL_TPP_01	((uint)0x00100000)
+#define SCC_GSMRL_TPP_10	((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS	((uint)0x00000000)
+#define SCC_GSMRL_TEND		((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32	((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16	((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8	((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32	((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16	((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8	((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN	((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH	((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0	((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI	((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN	((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH	((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0	((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI	((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE	((uint)0x000000c0)	/* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO	((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP	((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM	((uint)0x00000000)
+#define SCC_GSMRL_ENR		((uint)0x00000020)
+#define SCC_GSMRL_ENT		((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET	((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP	((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC	((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14	((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC	((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS	((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART	((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7	((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK	((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC	((uint)0x00000000)
+
+#define SCC_TODR_TOD		((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE	((unsigned char)0x10)
+#define SCCM_BSY	((unsigned char)0x04)
+#define SCCM_TX		((unsigned char)0x02)
+#define SCCM_RX		((unsigned char)0x01)
+
+typedef struct scc_param {
+	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	scc_rfcr;	/* Rx function code */
+	u_char	scc_tfcr;	/* Tx function code */
+	ushort	scc_mrblr;	/* Max receive buffer length */
+	uint	scc_rstate;	/* Internal */
+	uint	scc_idp;	/* Internal */
+	ushort	scc_rbptr;	/* Internal */
+	ushort	scc_ibc;	/* Internal */
+	uint	scc_rxtmp;	/* Internal */
+	uint	scc_tstate;	/* Internal */
+	uint	scc_tdp;	/* Internal */
+	ushort	scc_tbptr;	/* Internal */
+	ushort	scc_tbc;	/* Internal */
+	uint	scc_txtmp;	/* Internal */
+	uint	scc_rcrc;	/* Internal */
+	uint	scc_tcrc;	/* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+	sccp_t	sen_genscc;
+	uint	sen_cpres;	/* Preset CRC */
+	uint	sen_cmask;	/* Constant mask for CRC */
+	uint	sen_crcec;	/* CRC Error counter */
+	uint	sen_alec;	/* alignment error counter */
+	uint	sen_disfc;	/* discard frame counter */
+	ushort	sen_pads;	/* Tx short frame pad character */
+	ushort	sen_retlim;	/* Retry limit threshold */
+	ushort	sen_retcnt;	/* Retry limit counter */
+	ushort	sen_maxflr;	/* maximum frame length register */
+	ushort	sen_minflr;	/* minimum frame length register */
+	ushort	sen_maxd1;	/* maximum DMA1 length */
+	ushort	sen_maxd2;	/* maximum DMA2 length */
+	ushort	sen_maxd;	/* Rx max DMA */
+	ushort	sen_dmacnt;	/* Rx DMA counter */
+	ushort	sen_maxb;	/* Max BD byte count */
+	ushort	sen_gaddr1;	/* Group address filter */
+	ushort	sen_gaddr2;
+	ushort	sen_gaddr3;
+	ushort	sen_gaddr4;
+	uint	sen_tbuf0data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf0data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf0rba;	/* Internal */
+	uint	sen_tbuf0crc;	/* Internal */
+	ushort	sen_tbuf0bcnt;	/* Internal */
+	ushort	sen_paddrh;	/* physical address (MSB) */
+	ushort	sen_paddrm;
+	ushort	sen_paddrl;	/* physical address (LSB) */
+	ushort	sen_pper;	/* persistence */
+	ushort	sen_rfbdptr;	/* Rx first BD pointer */
+	ushort	sen_tfbdptr;	/* Tx first BD pointer */
+	ushort	sen_tlbdptr;	/* Tx last BD pointer */
+	uint	sen_tbuf1data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf1data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf1rba;	/* Internal */
+	uint	sen_tbuf1crc;	/* Internal */
+	ushort	sen_tbuf1bcnt;	/* Internal */
+	ushort	sen_txlen;	/* Tx Frame length counter */
+	ushort	sen_iaddr1;	/* Individual address filter */
+	ushort	sen_iaddr2;
+	ushort	sen_iaddr3;
+	ushort	sen_iaddr4;
+	ushort	sen_boffcnt;	/* Backoff counter */
+
+	/* NOTE: Some versions of the manual have the following items
+	 * incorrectly documented.  Below is the proper order.
+	 */
+	ushort	sen_taddrh;	/* temp address (MSB) */
+	ushort	sen_taddrm;
+	ushort	sen_taddrl;	/* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define SCCE_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define SCCE_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define SCCE_ENET_BSY	((ushort)0x0004)	/* All incoming buffers full */
+#define SCCE_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define SCCE_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC	((ushort)0x8000)	/* Enable heartbeat */
+#define SCC_PSMR_FC	((ushort)0x4000)	/* Force collision */
+#define SCC_PSMR_RSH	((ushort)0x2000)	/* Receive short frames */
+#define SCC_PSMR_IAM	((ushort)0x1000)	/* Check individual hash */
+#define SCC_PSMR_ENCRC	((ushort)0x0800)	/* Ethernet CRC mode */
+#define SCC_PSMR_PRO	((ushort)0x0200)	/* Promiscuous mode */
+#define SCC_PSMR_BRO	((ushort)0x0100)	/* Catch broadcast pkts */
+#define SCC_PSMR_SBT	((ushort)0x0080)	/* Special backoff timer */
+#define SCC_PSMR_LPB	((ushort)0x0040)	/* Set Loopback mode */
+#define SCC_PSMR_SIP	((ushort)0x0020)	/* Sample Input Pins */
+#define SCC_PSMR_LCW	((ushort)0x0010)	/* Late collision window */
+#define SCC_PSMR_NIB22	((ushort)0x000a)	/* Start frame search */
+#define SCC_PSMR_FDE	((ushort)0x0001)	/* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY	((ushort)0x8000)
+#define BD_ENET_RX_WRAP		((ushort)0x2000)
+#define BD_ENET_RX_INTR		((ushort)0x1000)
+#define BD_ENET_RX_LAST		((ushort)0x0800)
+#define BD_ENET_RX_FIRST	((ushort)0x0400)
+#define BD_ENET_RX_MISS		((ushort)0x0100)
+#define BD_ENET_RX_BC		((ushort)0x0080)	/* FCC Only */
+#define BD_ENET_RX_MC		((ushort)0x0040)	/* FCC Only */
+#define BD_ENET_RX_LG		((ushort)0x0020)
+#define BD_ENET_RX_NO		((ushort)0x0010)
+#define BD_ENET_RX_SH		((ushort)0x0008)
+#define BD_ENET_RX_CR		((ushort)0x0004)
+#define BD_ENET_RX_OV		((ushort)0x0002)
+#define BD_ENET_RX_CL		((ushort)0x0001)
+#define BD_ENET_RX_STATS	((ushort)0x01ff)	/* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY	((ushort)0x8000)
+#define BD_ENET_TX_PAD		((ushort)0x4000)
+#define BD_ENET_TX_WRAP		((ushort)0x2000)
+#define BD_ENET_TX_INTR		((ushort)0x1000)
+#define BD_ENET_TX_LAST		((ushort)0x0800)
+#define BD_ENET_TX_TC		((ushort)0x0400)
+#define BD_ENET_TX_DEF		((ushort)0x0200)
+#define BD_ENET_TX_HB		((ushort)0x0100)
+#define BD_ENET_TX_LC		((ushort)0x0080)
+#define BD_ENET_TX_RL		((ushort)0x0040)
+#define BD_ENET_TX_RCMASK	((ushort)0x003c)
+#define BD_ENET_TX_UN		((ushort)0x0002)
+#define BD_ENET_TX_CSL		((ushort)0x0001)
+#define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+	sccp_t	scc_genscc;
+	uint	scc_res1;	/* Reserved */
+	uint	scc_res2;	/* Reserved */
+	ushort	scc_maxidl;	/* Maximum idle chars */
+	ushort	scc_idlc;	/* temp idle counter */
+	ushort	scc_brkcr;	/* Break count register */
+	ushort	scc_parec;	/* receive parity error counter */
+	ushort	scc_frmec;	/* receive framing error counter */
+	ushort	scc_nosec;	/* receive noise counter */
+	ushort	scc_brkec;	/* receive break condition counter */
+	ushort	scc_brkln;	/* last received break length */
+	ushort	scc_uaddr1;	/* UART address character 1 */
+	ushort	scc_uaddr2;	/* UART address character 2 */
+	ushort	scc_rtemp;	/* Temp storage */
+	ushort	scc_toseq;	/* Transmit out of sequence char */
+	ushort	scc_char1;	/* control character 1 */
+	ushort	scc_char2;	/* control character 2 */
+	ushort	scc_char3;	/* control character 3 */
+	ushort	scc_char4;	/* control character 4 */
+	ushort	scc_char5;	/* control character 5 */
+	ushort	scc_char6;	/* control character 6 */
+	ushort	scc_char7;	/* control character 7 */
+	ushort	scc_char8;	/* control character 8 */
+	ushort	scc_rccm;	/* receive control character mask */
+	ushort	scc_rccr;	/* receive control character register */
+	ushort	scc_rlbc;	/* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR		((ushort)0x1000)
+#define UART_SCCM_GLT		((ushort)0x0800)
+#define UART_SCCM_AB		((ushort)0x0200)
+#define UART_SCCM_IDL		((ushort)0x0100)
+#define UART_SCCM_GRA		((ushort)0x0080)
+#define UART_SCCM_BRKE		((ushort)0x0040)
+#define UART_SCCM_BRKS		((ushort)0x0020)
+#define UART_SCCM_CCR		((ushort)0x0008)
+#define UART_SCCM_BSY		((ushort)0x0004)
+#define UART_SCCM_TX		((ushort)0x0002)
+#define UART_SCCM_RX		((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC		((ushort)0x8000)
+#define SCU_PSMR_SL		((ushort)0x4000)
+#define SCU_PSMR_CL		((ushort)0x3000)
+#define SCU_PSMR_UM		((ushort)0x0c00)
+#define SCU_PSMR_FRZ		((ushort)0x0200)
+#define SCU_PSMR_RZS		((ushort)0x0100)
+#define SCU_PSMR_SYN		((ushort)0x0080)
+#define SCU_PSMR_DRT		((ushort)0x0040)
+#define SCU_PSMR_PEN		((ushort)0x0010)
+#define SCU_PSMR_RPM		((ushort)0x000c)
+#define SCU_PSMR_REVP		((ushort)0x0008)
+#define SCU_PSMR_TPM		((ushort)0x0003)
+#define SCU_PSMR_TEVP		((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+	sccp_t	st_genscc;
+	uint	st_cpres;	/* Preset CRC */
+	uint	st_cmask;	/* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST		((ushort)0x0800)
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM	((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE	((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE	((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE	((uint)0xc0000000)
+#define FCC_GFMR_TCI		((uint)0x20000000)
+#define FCC_GFMR_TRX		((uint)0x10000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_CDP		((uint)0x04000000)
+#define FCC_GFMR_CTSP		((uint)0x02000000)
+#define FCC_GFMR_CDS		((uint)0x01000000)
+#define FCC_GFMR_CTSS		((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE	((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO	((uint)0x00004000)
+#define FCC_GFMR_SYNL_8		((uint)0x00008000)
+#define FCC_GFMR_SYNL_16	((uint)0x0000c000)
+#define FCC_GFMR_RTSM		((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI	((uint)0x00000800)
+#define FCC_GFMR_REVD		((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI	((uint)0x00000100)
+#define FCC_GFMR_TCRC_16	((uint)0x00000000)
+#define FCC_GFMR_TCRC_32	((uint)0x00000080)
+#define FCC_GFMR_ENR		((uint)0x00000020)
+#define FCC_GFMR_ENT		((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET	((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM	((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC	((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+	ushort	fcc_riptr;	/* Rx Internal temp pointer */
+	ushort	fcc_tiptr;	/* Tx Internal temp pointer */
+	ushort	fcc_res1;
+	ushort	fcc_mrblr;	/* Max receive buffer length, mod 32 bytes */
+	uint	fcc_rstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_rbase;	/* Receive BD base */
+	ushort	fcc_rbdstat;	/* RxBD status */
+	ushort	fcc_rbdlen;	/* RxBD down counter */
+	uint	fcc_rdptr;	/* RxBD internal data pointer */
+	uint	fcc_tstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_tbase;	/* Transmit BD base */
+	ushort	fcc_tbdstat;	/* TxBD status */
+	ushort	fcc_tbdlen;	/* TxBD down counter */
+	uint	fcc_tdptr;	/* TxBD internal data pointer */
+	uint	fcc_rbptr;	/* Rx BD Internal buf pointer */
+	uint	fcc_tbptr;	/* Tx BD Internal buf pointer */
+	uint	fcc_rcrc;	/* Rx temp CRC */
+	uint	fcc_res2;
+	uint	fcc_tcrc;	/* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+	fccp_t	fen_genfcc;
+	uint	fen_statbuf;	/* Internal status buffer */
+	uint	fen_camptr;	/* CAM address */
+	uint	fen_cmask;	/* Constant mask for CRC */
+	uint	fen_cpres;	/* Preset CRC */
+	uint	fen_crcec;	/* CRC Error counter */
+	uint	fen_alec;	/* alignment error counter */
+	uint	fen_disfc;	/* discard frame counter */
+	ushort	fen_retlim;	/* Retry limit */
+	ushort	fen_retcnt;	/* Retry counter */
+	ushort	fen_pper;	/* Persistence */
+	ushort	fen_boffcnt;	/* backoff counter */
+	uint	fen_gaddrh;	/* Group address filter, high 32-bits */
+	uint	fen_gaddrl;	/* Group address filter, low 32-bits */
+	ushort	fen_tfcstat;	/* out of sequence TxBD */
+	ushort	fen_tfclen;
+	uint	fen_tfcptr;
+	ushort	fen_mflr;	/* Maximum frame length (1518) */
+	ushort	fen_paddrh;	/* MAC address */
+	ushort	fen_paddrm;
+	ushort	fen_paddrl;
+	ushort	fen_ibdcount;	/* Internal BD counter */
+	ushort	fen_ibdstart;	/* Internal BD start pointer */
+	ushort	fen_ibdend;	/* Internal BD end pointer */
+	ushort	fen_txlen;	/* Internal Tx frame length counter */
+	uint	fen_ibdbase[8]; /* Internal use */
+	uint	fen_iaddrh;	/* Individual address filter */
+	uint	fen_iaddrl;
+	ushort	fen_minflr;	/* Minimum frame length (64) */
+	ushort	fen_taddrh;	/* Filter transfer MAC address */
+	ushort	fen_taddrm;
+	ushort	fen_taddrl;
+	ushort	fen_padptr;	/* Pointer to pad byte buffer */
+	ushort	fen_cftype;	/* control frame type */
+	ushort	fen_cfrange;	/* control frame range */
+	ushort	fen_maxb;	/* maximum BD count */
+	ushort	fen_maxd1;	/* Max DMA1 length (1520) */
+	ushort	fen_maxd2;	/* Max DMA2 length (1520) */
+	ushort	fen_maxd;	/* internal max DMA count */
+	ushort	fen_dmacnt;	/* internal DMA counter */
+	uint	fen_octc;	/* Total octect counter */
+	uint	fen_colc;	/* Total collision counter */
+	uint	fen_broc;	/* Total broadcast packet counter */
+	uint	fen_mulc;	/* Total multicast packet count */
+	uint	fen_uspc;	/* Total packets < 64 bytes */
+	uint	fen_frgc;	/* Total packets < 64 bytes with errors */
+	uint	fen_ospc;	/* Total packets > 1518 */
+	uint	fen_jbrc;	/* Total packets > 1518 with errors */
+	uint	fen_p64c;	/* Total packets == 64 bytes */
+	uint	fen_p65c;	/* Total packets 64 < bytes <= 127 */
+	uint	fen_p128c;	/* Total packets 127 < bytes <= 255 */
+	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
+	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
+	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
+	uint	fen_cambuf;	/* Internal CAM buffer poiner */
+	ushort	fen_rfthr;	/* Received frames threshold */
+	ushort	fen_rfcnt;	/* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define FCC_ENET_RXC	((ushort)0x0040)	/* Control Frame Received */
+#define FCC_ENET_TXC	((ushort)0x0020)	/* Out of seq. Tx sent */
+#define FCC_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define FCC_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define FCC_ENET_BSY	((ushort)0x0004)	/* Busy.  Rx Frame dropped */
+#define FCC_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define FCC_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC	((uint)0x80000000)	/* Enable heartbeat */
+#define FCC_PSMR_FC	((uint)0x40000000)	/* Force Collision */
+#define FCC_PSMR_SBT	((uint)0x20000000)	/* Stop backoff timer */
+#define FCC_PSMR_LPB	((uint)0x10000000)	/* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW	((uint)0x08000000)	/* Late collision select */
+#define FCC_PSMR_FDE	((uint)0x04000000)	/* Full Duplex Enable */
+#define FCC_PSMR_MON	((uint)0x02000000)	/* RMON Enable */
+#define FCC_PSMR_PRO	((uint)0x00400000)	/* Promiscuous Enable */
+#define FCC_PSMR_FCE	((uint)0x00200000)	/* Flow Control Enable */
+#define FCC_PSMR_RSH	((uint)0x00100000)	/* Receive Short Frames */
+#define FCC_PSMR_CAM	((uint)0x00000400)	/* CAM enable */
+#define FCC_PSMR_BRO	((uint)0x00000200)	/* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC	((uint)0x00000080)	/* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+	ushort	iic_rbase;	/* Rx Buffer descriptor base address */
+	ushort	iic_tbase;	/* Tx Buffer descriptor base address */
+	u_char	iic_rfcr;	/* Rx function code */
+	u_char	iic_tfcr;	/* Tx function code */
+	ushort	iic_mrblr;	/* Max receive buffer length */
+	uint	iic_rstate;	/* Internal */
+	uint	iic_rdp;	/* Internal */
+	ushort	iic_rbptr;	/* Internal */
+	ushort	iic_rbc;	/* Internal */
+	uint	iic_rxtmp;	/* Internal */
+	uint	iic_tstate;	/* Internal */
+	uint	iic_tdp;	/* Internal */
+	ushort	iic_tbptr;	/* Internal */
+	ushort	iic_tbc;	/* Internal */
+	uint	iic_txtmp;	/* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+	ushort	spi_rbase;	/* Rx Buffer descriptor base address */
+	ushort	spi_tbase;	/* Tx Buffer descriptor base address */
+	u_char	spi_rfcr;	/* Rx function code */
+	u_char	spi_tfcr;	/* Tx function code */
+	ushort	spi_mrblr;	/* Max receive buffer length */
+	uint	spi_rstate;	/* Internal */
+	uint	spi_rdp;	/* Internal */
+	ushort	spi_rbptr;	/* Internal */
+	ushort	spi_rbc;	/* Internal */
+	uint	spi_rxtmp;	/* Internal */
+	uint	spi_tstate;	/* Internal */
+	uint	spi_tdp;	/* Internal */
+	ushort	spi_tbptr;	/* Internal */
+	ushort	spi_tbc;	/* Internal */
+	uint	spi_txtmp;	/* Internal */
+	uint	spi_res;	/* Tx temp. */
+	uint	spi_res1[4];	/* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP	((ushort)0x4000)	/* Loopback */
+#define SPMODE_CI	((ushort)0x2000)	/* Clock Invert */
+#define SPMODE_CP	((ushort)0x1000)	/* Clock Phase */
+#define SPMODE_DIV16	((ushort)0x0800)	/* BRG/16 mode */
+#define SPMODE_REV	((ushort)0x0400)	/* Reversed Data */
+#define SPMODE_MSTR	((ushort)0x0200)	/* SPI Master */
+#define SPMODE_EN	((ushort)0x0100)	/* Enable */
+#define SPMODE_LENMSK	((ushort)0x00f0)	/* character length */
+#define SPMODE_PMMSK	((ushort)0x000f)	/* prescale modulus */
+
+#define SPMODE_LEN(x)	((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x)	((x) &0xF)
+
+#define SPI_EB		((u_char)0x10)		/* big endian byte order */
+
+#define BD_IIC_START		((ushort)0x0400)
+
+/* IDMA parameter RAM
+*/
+typedef struct idma {
+	ushort ibase;		/* IDMA buffer descriptor table base address */
+	ushort dcm;		/* DMA channel mode */
+	ushort ibdptr;		/* IDMA current buffer descriptor pointer */
+	ushort dpr_buf;		/* IDMA transfer buffer base address */
+	ushort buf_inv;		/* internal buffer inventory */
+	ushort ss_max;		/* steady-state maximum transfer size */
+	ushort dpr_in_ptr;	/* write pointer inside the internal buffer */
+	ushort sts;		/* source transfer size */
+	ushort dpr_out_ptr;	/* read pointer inside the internal buffer */
+	ushort seob;		/* source end of burst */
+	ushort deob;		/* destination end of burst */
+	ushort dts;		/* destination transfer size */
+	ushort ret_add;		/* return address when working in ERM=1 mode */
+	ushort res0;		/* reserved */
+	uint   bd_cnt;		/* internal byte count */
+	uint   s_ptr;		/* source internal data pointer */
+	uint   d_ptr;		/* destination internal data pointer */
+	uint   istate;		/* internal state */
+	u_char res1[20];	/* pad to 64-byte length */
+} idma_t;
+
+/* DMA channel mode bit fields
+*/
+#define IDMA_DCM_FB		((ushort)0x8000) /* fly-by mode */
+#define IDMA_DCM_LP		((ushort)0x4000) /* low priority */
+#define IDMA_DCM_TC2		((ushort)0x0400) /* value driven on TC[2] */
+#define IDMA_DCM_DMA_WRAP_MASK	((ushort)0x01c0) /* mask for DMA wrap */
+#define IDMA_DCM_DMA_WRAP_64	((ushort)0x0000) /* 64-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_128	((ushort)0x0040) /* 128-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_256	((ushort)0x0080) /* 256-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_512	((ushort)0x00c0) /* 512-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_1024	((ushort)0x0100) /* 1024-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_2048	((ushort)0x0140) /* 2048-byte DMA xfer buffer */
+#define IDMA_DCM_SINC		((ushort)0x0020) /* source inc addr */
+#define IDMA_DCM_DINC		((ushort)0x0010) /* destination inc addr */
+#define IDMA_DCM_ERM		((ushort)0x0008) /* external request mode */
+#define IDMA_DCM_DT		((ushort)0x0004) /* DONE treatment */
+#define IDMA_DCM_SD_MASK	((ushort)0x0003) /* mask for SD bit field */
+#define IDMA_DCM_SD_MEM2MEM	((ushort)0x0000) /* memory-to-memory xfer */
+#define IDMA_DCM_SD_PER2MEM	((ushort)0x0002) /* peripheral-to-memory xfer */
+#define IDMA_DCM_SD_MEM2PER	((ushort)0x0001) /* memory-to-peripheral xfer */
+
+/* IDMA Buffer Descriptors
+*/
+typedef struct idma_bd {
+	uint flags;
+	uint len;	/* data length */
+	uint src;	/* source data buffer pointer */
+	uint dst;	/* destination data buffer pointer */
+} idma_bd_t;
+
+/* IDMA buffer descriptor flag bit fields
+*/
+#define IDMA_BD_V	((uint)0x80000000)	/* valid */
+#define IDMA_BD_W	((uint)0x20000000)	/* wrap */
+#define IDMA_BD_I	((uint)0x10000000)	/* interrupt */
+#define IDMA_BD_L	((uint)0x08000000)	/* last */
+#define IDMA_BD_CM	((uint)0x02000000)	/* continuous mode */
+#define IDMA_BD_SDN	((uint)0x00400000)	/* source done */
+#define IDMA_BD_DDN	((uint)0x00200000)	/* destination done */
+#define IDMA_BD_DGBL	((uint)0x00100000)	/* destination global */
+#define IDMA_BD_DBO_LE	((uint)0x00040000)	/* little-end dest byte order */
+#define IDMA_BD_DBO_BE	((uint)0x00080000)	/* big-end dest byte order */
+#define IDMA_BD_DDTB	((uint)0x00010000)	/* destination data bus */
+#define IDMA_BD_SGBL	((uint)0x00002000)	/* source global */
+#define IDMA_BD_SBO_LE	((uint)0x00000800)	/* little-end src byte order */
+#define IDMA_BD_SBO_BE	((uint)0x00001000)	/* big-end src byte order */
+#define IDMA_BD_SDTB	((uint)0x00000200)	/* source data bus */
+
+/* per-channel IDMA registers
+*/
+typedef struct im_idma {
+	u_char idsr;			/* IDMAn event status register */
+	u_char res0[3];
+	u_char idmr;			/* IDMAn event mask register */
+	u_char res1[3];
+} im_idma_t;
+
+/* IDMA event register bit fields
+*/
+#define IDMA_EVENT_SC	((unsigned char)0x08)	/* stop completed */
+#define IDMA_EVENT_OB	((unsigned char)0x04)	/* out of buffers */
+#define IDMA_EVENT_EDN	((unsigned char)0x02)	/* external DONE asserted */
+#define IDMA_EVENT_BC	((unsigned char)0x01)	/* buffer descriptor complete */
+
+/* RISC Controller Configuration Register (RCCR) bit fields
+*/
+#define RCCR_TIME	((uint)0x80000000) /* timer enable */
+#define RCCR_TIMEP_MASK	((uint)0x3f000000) /* mask for timer period bit field */
+#define RCCR_DR0M	((uint)0x00800000) /* IDMA0 request mode */
+#define RCCR_DR1M	((uint)0x00400000) /* IDMA1 request mode */
+#define RCCR_DR2M	((uint)0x00000080) /* IDMA2 request mode */
+#define RCCR_DR3M	((uint)0x00000040) /* IDMA3 request mode */
+#define RCCR_DR0QP_MASK	((uint)0x00300000) /* mask for IDMA0 req priority */
+#define RCCR_DR0QP_HIGH ((uint)0x00000000) /* IDMA0 has high req priority */
+#define RCCR_DR0QP_MED	((uint)0x00100000) /* IDMA0 has medium req priority */
+#define RCCR_DR0QP_LOW	((uint)0x00200000) /* IDMA0 has low req priority */
+#define RCCR_DR1QP_MASK	((uint)0x00030000) /* mask for IDMA1 req priority */
+#define RCCR_DR1QP_HIGH ((uint)0x00000000) /* IDMA1 has high req priority */
+#define RCCR_DR1QP_MED	((uint)0x00010000) /* IDMA1 has medium req priority */
+#define RCCR_DR1QP_LOW	((uint)0x00020000) /* IDMA1 has low req priority */
+#define RCCR_DR2QP_MASK	((uint)0x00000030) /* mask for IDMA2 req priority */
+#define RCCR_DR2QP_HIGH ((uint)0x00000000) /* IDMA2 has high req priority */
+#define RCCR_DR2QP_MED	((uint)0x00000010) /* IDMA2 has medium req priority */
+#define RCCR_DR2QP_LOW	((uint)0x00000020) /* IDMA2 has low req priority */
+#define RCCR_DR3QP_MASK	((uint)0x00000003) /* mask for IDMA3 req priority */
+#define RCCR_DR3QP_HIGH ((uint)0x00000000) /* IDMA3 has high req priority */
+#define RCCR_DR3QP_MED	((uint)0x00000001) /* IDMA3 has medium req priority */
+#define RCCR_DR3QP_LOW	((uint)0x00000002) /* IDMA3 has low req priority */
+#define RCCR_EIE	((uint)0x00080000) /* external interrupt enable */
+#define RCCR_SCD	((uint)0x00040000) /* scheduler configuration */
+#define RCCR_ERAM_MASK	((uint)0x0000e000) /* mask for enable RAM microcode */
+#define RCCR_ERAM_0KB	((uint)0x00000000) /* use 0KB of dpram for microcode */
+#define RCCR_ERAM_2KB	((uint)0x00002000) /* use 2KB of dpram for microcode */
+#define RCCR_ERAM_4KB	((uint)0x00004000) /* use 4KB of dpram for microcode */
+#define RCCR_ERAM_6KB	((uint)0x00006000) /* use 6KB of dpram for microcode */
+#define RCCR_ERAM_8KB	((uint)0x00008000) /* use 8KB of dpram for microcode */
+#define RCCR_ERAM_10KB	((uint)0x0000a000) /* use 10KB of dpram for microcode */
+#define RCCR_ERAM_12KB	((uint)0x0000c000) /* use 12KB of dpram for microcode */
+#define RCCR_EDM0	((uint)0x00000800) /* DREQ0 edge detect mode */
+#define RCCR_EDM1	((uint)0x00000400) /* DREQ1 edge detect mode */
+#define RCCR_EDM2	((uint)0x00000200) /* DREQ2 edge detect mode */
+#define RCCR_EDM3	((uint)0x00000100) /* DREQ3 edge detect mode */
+#define RCCR_DEM01	((uint)0x00000008) /* DONE0/DONE1 edge detect mode */
+#define RCCR_DEM23	((uint)0x00000004) /* DONE2/DONE3 edge detect mode */
+
+/*-----------------------------------------------------------------------
+ * CMXFCR - CMX FCC Clock Route Register
+ */
+#define CMXFCR_FC1         0x40000000   /* FCC1 connection              */
+#define CMXFCR_RF1CS_MSK   0x38000000   /* Receive FCC1 Clock Source Mask */
+#define CMXFCR_TF1CS_MSK   0x07000000   /* Transmit FCC1 Clock Source Mask */
+#define CMXFCR_FC2         0x00400000   /* FCC2 connection              */
+#define CMXFCR_RF2CS_MSK   0x00380000   /* Receive FCC2 Clock Source Mask */
+#define CMXFCR_TF2CS_MSK   0x00070000   /* Transmit FCC2 Clock Source Mask */
+#define CMXFCR_FC3         0x00004000   /* FCC3 connection              */
+#define CMXFCR_RF3CS_MSK   0x00003800   /* Receive FCC3 Clock Source Mask */
+#define CMXFCR_TF3CS_MSK   0x00000700   /* Transmit FCC3 Clock Source Mask */
+
+#define CMXFCR_RF1CS_BRG5  0x00000000   /* Receive FCC1 Clock Source is BRG5 */
+#define CMXFCR_RF1CS_BRG6  0x08000000   /* Receive FCC1 Clock Source is BRG6 */
+#define CMXFCR_RF1CS_BRG7  0x10000000   /* Receive FCC1 Clock Source is BRG7 */
+#define CMXFCR_RF1CS_BRG8  0x18000000   /* Receive FCC1 Clock Source is BRG8 */
+#define CMXFCR_RF1CS_CLK9  0x20000000   /* Receive FCC1 Clock Source is CLK9 */
+#define CMXFCR_RF1CS_CLK10 0x28000000   /* Receive FCC1 Clock Source is CLK10 */
+#define CMXFCR_RF1CS_CLK11 0x30000000   /* Receive FCC1 Clock Source is CLK11 */
+#define CMXFCR_RF1CS_CLK12 0x38000000   /* Receive FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_TF1CS_BRG5  0x00000000   /* Transmit FCC1 Clock Source is BRG5 */
+#define CMXFCR_TF1CS_BRG6  0x01000000   /* Transmit FCC1 Clock Source is BRG6 */
+#define CMXFCR_TF1CS_BRG7  0x02000000   /* Transmit FCC1 Clock Source is BRG7 */
+#define CMXFCR_TF1CS_BRG8  0x03000000   /* Transmit FCC1 Clock Source is BRG8 */
+#define CMXFCR_TF1CS_CLK9  0x04000000   /* Transmit FCC1 Clock Source is CLK9 */
+#define CMXFCR_TF1CS_CLK10 0x05000000   /* Transmit FCC1 Clock Source is CLK10 */
+#define CMXFCR_TF1CS_CLK11 0x06000000   /* Transmit FCC1 Clock Source is CLK11 */
+#define CMXFCR_TF1CS_CLK12 0x07000000   /* Transmit FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_RF2CS_BRG5  0x00000000   /* Receive FCC2 Clock Source is BRG5 */
+#define CMXFCR_RF2CS_BRG6  0x00080000   /* Receive FCC2 Clock Source is BRG6 */
+#define CMXFCR_RF2CS_BRG7  0x00100000   /* Receive FCC2 Clock Source is BRG7 */
+#define CMXFCR_RF2CS_BRG8  0x00180000   /* Receive FCC2 Clock Source is BRG8 */
+#define CMXFCR_RF2CS_CLK13 0x00200000   /* Receive FCC2 Clock Source is CLK13 */
+#define CMXFCR_RF2CS_CLK14 0x00280000   /* Receive FCC2 Clock Source is CLK14 */
+#define CMXFCR_RF2CS_CLK15 0x00300000   /* Receive FCC2 Clock Source is CLK15 */
+#define CMXFCR_RF2CS_CLK16 0x00380000   /* Receive FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_TF2CS_BRG5  0x00000000   /* Transmit FCC2 Clock Source is BRG5 */
+#define CMXFCR_TF2CS_BRG6  0x00010000   /* Transmit FCC2 Clock Source is BRG6 */
+#define CMXFCR_TF2CS_BRG7  0x00020000   /* Transmit FCC2 Clock Source is BRG7 */
+#define CMXFCR_TF2CS_BRG8  0x00030000   /* Transmit FCC2 Clock Source is BRG8 */
+#define CMXFCR_TF2CS_CLK13 0x00040000   /* Transmit FCC2 Clock Source is CLK13 */
+#define CMXFCR_TF2CS_CLK14 0x00050000   /* Transmit FCC2 Clock Source is CLK14 */
+#define CMXFCR_TF2CS_CLK15 0x00060000   /* Transmit FCC2 Clock Source is CLK15 */
+#define CMXFCR_TF2CS_CLK16 0x00070000   /* Transmit FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_RF3CS_BRG5  0x00000000   /* Receive FCC3 Clock Source is BRG5 */
+#define CMXFCR_RF3CS_BRG6  0x00000800   /* Receive FCC3 Clock Source is BRG6 */
+#define CMXFCR_RF3CS_BRG7  0x00001000   /* Receive FCC3 Clock Source is BRG7 */
+#define CMXFCR_RF3CS_BRG8  0x00001800   /* Receive FCC3 Clock Source is BRG8 */
+#define CMXFCR_RF3CS_CLK13 0x00002000   /* Receive FCC3 Clock Source is CLK13 */
+#define CMXFCR_RF3CS_CLK14 0x00002800   /* Receive FCC3 Clock Source is CLK14 */
+#define CMXFCR_RF3CS_CLK15 0x00003000   /* Receive FCC3 Clock Source is CLK15 */
+#define CMXFCR_RF3CS_CLK16 0x00003800   /* Receive FCC3 Clock Source is CLK16 */
+
+#define CMXFCR_TF3CS_BRG5  0x00000000   /* Transmit FCC3 Clock Source is BRG5 */
+#define CMXFCR_TF3CS_BRG6  0x00000100   /* Transmit FCC3 Clock Source is BRG6 */
+#define CMXFCR_TF3CS_BRG7  0x00000200   /* Transmit FCC3 Clock Source is BRG7 */
+#define CMXFCR_TF3CS_BRG8  0x00000300   /* Transmit FCC3 Clock Source is BRG8 */
+#define CMXFCR_TF3CS_CLK13 0x00000400   /* Transmit FCC3 Clock Source is CLK13 */
+#define CMXFCR_TF3CS_CLK14 0x00000500   /* Transmit FCC3 Clock Source is CLK14 */
+#define CMXFCR_TF3CS_CLK15 0x00000600   /* Transmit FCC3 Clock Source is CLK15 */
+#define CMXFCR_TF3CS_CLK16 0x00000700   /* Transmit FCC3 Clock Source is CLK16 */
+
+/*-----------------------------------------------------------------------
+ * CMXSCR - CMX SCC Clock Route Register
+ */
+#define CMXSCR_GR1         0x80000000   /* Grant Support of SCC1        */
+#define CMXSCR_SC1         0x40000000   /* SCC1 connection              */
+#define CMXSCR_RS1CS_MSK   0x38000000   /* Receive SCC1 Clock Source Mask */
+#define CMXSCR_TS1CS_MSK   0x07000000   /* Transmit SCC1 Clock Source Mask */
+#define CMXSCR_GR2         0x00800000   /* Grant Support of SCC2        */
+#define CMXSCR_SC2         0x00400000   /* SCC2 connection              */
+#define CMXSCR_RS2CS_MSK   0x00380000   /* Receive SCC2 Clock Source Mask */
+#define CMXSCR_TS2CS_MSK   0x00070000   /* Transmit SCC2 Clock Source Mask */
+#define CMXSCR_GR3         0x00008000   /* Grant Support of SCC3        */
+#define CMXSCR_SC3         0x00004000   /* SCC3 connection              */
+#define CMXSCR_RS3CS_MSK   0x00003800   /* Receive SCC3 Clock Source Mask */
+#define CMXSCR_TS3CS_MSK   0x00000700   /* Transmit SCC3 Clock Source Mask */
+#define CMXSCR_GR4         0x00000080   /* Grant Support of SCC4        */
+#define CMXSCR_SC4         0x00000040   /* SCC4 connection              */
+#define CMXSCR_RS4CS_MSK   0x00000038   /* Receive SCC4 Clock Source Mask */
+#define CMXSCR_TS4CS_MSK   0x00000007   /* Transmit SCC4 Clock Source Mask */
+
+#define CMXSCR_RS1CS_BRG1  0x00000000   /* SCC1 Rx Clock Source is BRG1 */
+#define CMXSCR_RS1CS_BRG2  0x08000000   /* SCC1 Rx Clock Source is BRG2 */
+#define CMXSCR_RS1CS_BRG3  0x10000000   /* SCC1 Rx Clock Source is BRG3 */
+#define CMXSCR_RS1CS_BRG4  0x18000000   /* SCC1 Rx Clock Source is BRG4 */
+#define CMXSCR_RS1CS_CLK11 0x20000000   /* SCC1 Rx Clock Source is CLK11 */
+#define CMXSCR_RS1CS_CLK12 0x28000000   /* SCC1 Rx Clock Source is CLK12 */
+#define CMXSCR_RS1CS_CLK3  0x30000000   /* SCC1 Rx Clock Source is CLK3 */
+#define CMXSCR_RS1CS_CLK4  0x38000000   /* SCC1 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS1CS_BRG1  0x00000000   /* SCC1 Tx Clock Source is BRG1 */
+#define CMXSCR_TS1CS_BRG2  0x01000000   /* SCC1 Tx Clock Source is BRG2 */
+#define CMXSCR_TS1CS_BRG3  0x02000000   /* SCC1 Tx Clock Source is BRG3 */
+#define CMXSCR_TS1CS_BRG4  0x03000000   /* SCC1 Tx Clock Source is BRG4 */
+#define CMXSCR_TS1CS_CLK11 0x04000000   /* SCC1 Tx Clock Source is CLK11 */
+#define CMXSCR_TS1CS_CLK12 0x05000000   /* SCC1 Tx Clock Source is CLK12 */
+#define CMXSCR_TS1CS_CLK3  0x06000000   /* SCC1 Tx Clock Source is CLK3 */
+#define CMXSCR_TS1CS_CLK4  0x07000000   /* SCC1 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS2CS_BRG1  0x00000000   /* SCC2 Rx Clock Source is BRG1 */
+#define CMXSCR_RS2CS_BRG2  0x00080000   /* SCC2 Rx Clock Source is BRG2 */
+#define CMXSCR_RS2CS_BRG3  0x00100000   /* SCC2 Rx Clock Source is BRG3 */
+#define CMXSCR_RS2CS_BRG4  0x00180000   /* SCC2 Rx Clock Source is BRG4 */
+#define CMXSCR_RS2CS_CLK11 0x00200000   /* SCC2 Rx Clock Source is CLK11 */
+#define CMXSCR_RS2CS_CLK12 0x00280000   /* SCC2 Rx Clock Source is CLK12 */
+#define CMXSCR_RS2CS_CLK3  0x00300000   /* SCC2 Rx Clock Source is CLK3 */
+#define CMXSCR_RS2CS_CLK4  0x00380000   /* SCC2 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS2CS_BRG1  0x00000000   /* SCC2 Tx Clock Source is BRG1 */
+#define CMXSCR_TS2CS_BRG2  0x00010000   /* SCC2 Tx Clock Source is BRG2 */
+#define CMXSCR_TS2CS_BRG3  0x00020000   /* SCC2 Tx Clock Source is BRG3 */
+#define CMXSCR_TS2CS_BRG4  0x00030000   /* SCC2 Tx Clock Source is BRG4 */
+#define CMXSCR_TS2CS_CLK11 0x00040000   /* SCC2 Tx Clock Source is CLK11 */
+#define CMXSCR_TS2CS_CLK12 0x00050000   /* SCC2 Tx Clock Source is CLK12 */
+#define CMXSCR_TS2CS_CLK3  0x00060000   /* SCC2 Tx Clock Source is CLK3 */
+#define CMXSCR_TS2CS_CLK4  0x00070000   /* SCC2 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS3CS_BRG1  0x00000000   /* SCC3 Rx Clock Source is BRG1 */
+#define CMXSCR_RS3CS_BRG2  0x00000800   /* SCC3 Rx Clock Source is BRG2 */
+#define CMXSCR_RS3CS_BRG3  0x00001000   /* SCC3 Rx Clock Source is BRG3 */
+#define CMXSCR_RS3CS_BRG4  0x00001800   /* SCC3 Rx Clock Source is BRG4 */
+#define CMXSCR_RS3CS_CLK5  0x00002000   /* SCC3 Rx Clock Source is CLK5 */
+#define CMXSCR_RS3CS_CLK6  0x00002800   /* SCC3 Rx Clock Source is CLK6 */
+#define CMXSCR_RS3CS_CLK7  0x00003000   /* SCC3 Rx Clock Source is CLK7 */
+#define CMXSCR_RS3CS_CLK8  0x00003800   /* SCC3 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS3CS_BRG1  0x00000000   /* SCC3 Tx Clock Source is BRG1 */
+#define CMXSCR_TS3CS_BRG2  0x00000100   /* SCC3 Tx Clock Source is BRG2 */
+#define CMXSCR_TS3CS_BRG3  0x00000200   /* SCC3 Tx Clock Source is BRG3 */
+#define CMXSCR_TS3CS_BRG4  0x00000300   /* SCC3 Tx Clock Source is BRG4 */
+#define CMXSCR_TS3CS_CLK5  0x00000400   /* SCC3 Tx Clock Source is CLK5 */
+#define CMXSCR_TS3CS_CLK6  0x00000500   /* SCC3 Tx Clock Source is CLK6 */
+#define CMXSCR_TS3CS_CLK7  0x00000600   /* SCC3 Tx Clock Source is CLK7 */
+#define CMXSCR_TS3CS_CLK8  0x00000700   /* SCC3 Tx Clock Source is CLK8 */
+
+#define CMXSCR_RS4CS_BRG1  0x00000000   /* SCC4 Rx Clock Source is BRG1 */
+#define CMXSCR_RS4CS_BRG2  0x00000008   /* SCC4 Rx Clock Source is BRG2 */
+#define CMXSCR_RS4CS_BRG3  0x00000010   /* SCC4 Rx Clock Source is BRG3 */
+#define CMXSCR_RS4CS_BRG4  0x00000018   /* SCC4 Rx Clock Source is BRG4 */
+#define CMXSCR_RS4CS_CLK5  0x00000020   /* SCC4 Rx Clock Source is CLK5 */
+#define CMXSCR_RS4CS_CLK6  0x00000028   /* SCC4 Rx Clock Source is CLK6 */
+#define CMXSCR_RS4CS_CLK7  0x00000030   /* SCC4 Rx Clock Source is CLK7 */
+#define CMXSCR_RS4CS_CLK8  0x00000038   /* SCC4 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS4CS_BRG1  0x00000000   /* SCC4 Tx Clock Source is BRG1 */
+#define CMXSCR_TS4CS_BRG2  0x00000001   /* SCC4 Tx Clock Source is BRG2 */
+#define CMXSCR_TS4CS_BRG3  0x00000002   /* SCC4 Tx Clock Source is BRG3 */
+#define CMXSCR_TS4CS_BRG4  0x00000003   /* SCC4 Tx Clock Source is BRG4 */
+#define CMXSCR_TS4CS_CLK5  0x00000004   /* SCC4 Tx Clock Source is CLK5 */
+#define CMXSCR_TS4CS_CLK6  0x00000005   /* SCC4 Tx Clock Source is CLK6 */
+#define CMXSCR_TS4CS_CLK7  0x00000006   /* SCC4 Tx Clock Source is CLK7 */
+#define CMXSCR_TS4CS_CLK8  0x00000007   /* SCC4 Tx Clock Source is CLK8 */
+
+#endif /* __CPM2__ */
+#endif /* __KERNEL__ */
+
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/cpm_8260.h linux-2.4.26-pre6/include/asm-ppc/cpm_8260.h
--- linux-2.4.25/include/asm-ppc/cpm_8260.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/cpm_8260.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,702 +0,0 @@
-/*
- * MPC8260 Communication Processor Module.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- *
- * This file contains structures and information for the communication
- * processor channels found in the dual port RAM or parameter RAM.
- * All CPM control and status is available through the MPC8260 internal
- * memory map.  See immap.h for details.
- */
-#ifdef __KERNEL__
-#ifndef __CPM_82XX__
-#define __CPM_82XX__
-
-#include <asm/immap_8260.h>
-
-/* CPM Command register.
-*/
-#define CPM_CR_RST	((uint)0x80000000)
-#define CPM_CR_PAGE	((uint)0x7c000000)
-#define CPM_CR_SBLOCK	((uint)0x03e00000)
-#define CPM_CR_FLG	((uint)0x00010000)
-#define CPM_CR_MCN	((uint)0x00003fc0)
-#define CPM_CR_OPCODE	((uint)0x0000000f)
-
-/* Device sub-block and page codes.
-*/
-#define CPM_CR_SCC1_SBLOCK	(0x04)
-#define CPM_CR_SCC2_SBLOCK	(0x05)
-#define CPM_CR_SCC3_SBLOCK	(0x06)
-#define CPM_CR_SCC4_SBLOCK	(0x07)
-#define CPM_CR_SMC1_SBLOCK	(0x08)
-#define CPM_CR_SMC2_SBLOCK	(0x09)
-#define CPM_CR_SPI_SBLOCK	(0x0a)
-#define CPM_CR_I2C_SBLOCK	(0x0b)
-#define CPM_CR_TIMER_SBLOCK	(0x0f)
-#define CPM_CR_RAND_SBLOCK	(0x0e)
-#define CPM_CR_FCC1_SBLOCK	(0x10)
-#define CPM_CR_FCC2_SBLOCK	(0x11)
-#define CPM_CR_FCC3_SBLOCK	(0x12)
-#define CPM_CR_IDMA1_SBLOCK	(0x14)
-#define CPM_CR_IDMA2_SBLOCK	(0x15)
-#define CPM_CR_IDMA3_SBLOCK	(0x16)
-#define CPM_CR_IDMA4_SBLOCK	(0x17)
-#define CPM_CR_MCC1_SBLOCK	(0x1c)
-
-#define CPM_CR_SCC1_PAGE	(0x00)
-#define CPM_CR_SCC2_PAGE	(0x01)
-#define CPM_CR_SCC3_PAGE	(0x02)
-#define CPM_CR_SCC4_PAGE	(0x03)
-#define CPM_CR_SMC1_PAGE	(0x07)
-#define CPM_CR_SMC2_PAGE	(0x08)
-#define CPM_CR_SPI_PAGE		(0x09)
-#define CPM_CR_I2C_PAGE		(0x0a)
-#define CPM_CR_TIMER_PAGE	(0x0a)
-#define CPM_CR_RAND_PAGE	(0x0a)
-#define CPM_CR_FCC1_PAGE	(0x04)
-#define CPM_CR_FCC2_PAGE	(0x05)
-#define CPM_CR_FCC3_PAGE	(0x06)
-#define CPM_CR_IDMA1_PAGE	(0x07)
-#define CPM_CR_IDMA2_PAGE	(0x08)
-#define CPM_CR_IDMA3_PAGE	(0x09)
-#define CPM_CR_IDMA4_PAGE	(0x0a)
-#define CPM_CR_MCC1_PAGE	(0x07)
-#define CPM_CR_MCC2_PAGE	(0x08)
-
-/* Some opcodes (there are more...later)
-*/
-#define CPM_CR_INIT_TRX		((ushort)0x0000)
-#define CPM_CR_INIT_RX		((ushort)0x0001)
-#define CPM_CR_INIT_TX		((ushort)0x0002)
-#define CPM_CR_HUNT_MODE	((ushort)0x0003)
-#define CPM_CR_STOP_TX		((ushort)0x0004)
-#define CPM_CR_RESTART_TX	((ushort)0x0006)
-#define CPM_CR_SET_GADDR	((ushort)0x0008)
-
-#define mk_cr_cmd(PG, SBC, MCN, OP) \
-	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
-
-/* Dual Port RAM addresses.  The first 16K is available for almost
- * any CPM use, so we put the BDs there.  The first 128 bytes are
- * used for SMC1 and SMC2 parameter RAM, so we start allocating
- * BDs above that.  All of this must change when we start
- * downloading RAM microcode.
- */
-#define CPM_DATAONLY_BASE	((uint)128)
-#define CPM_DATAONLY_SIZE	((uint)(16 * 1024) - CPM_DATAONLY_BASE)
-#define CPM_DP_NOSPACE		((uint)0x7fffffff)
-#define CPM_FCC_SPECIAL_BASE	((uint)0x0000b000)
-
-/* The number of pages of host memory we allocate for CPM.  This is
- * done early in kernel initialization to get physically contiguous
- * pages.
- */
-#define NUM_CPM_HOST_PAGES	2
-
-
-/* Export the base address of the communication processor registers
- * and dual port ram.
- */
-extern	cpm8260_t	*cpmp;		/* Pointer to comm processor */
-uint		m8260_cpm_dpalloc(uint size, uint align);
-uint		m8260_cpm_hostalloc(uint size, uint align);
-void		m8260_cpm_setbrg(uint brg, uint rate);
-void		m8260_cpm_fastbrg(uint brg, uint rate, int div16);
-
-/* Buffer descriptors used by many of the CPM protocols.
-*/
-typedef struct cpm_buf_desc {
-	ushort	cbd_sc;		/* Status and Control */
-	ushort	cbd_datlen;	/* Data length in buffer */
-	uint	cbd_bufaddr;	/* Buffer address in host memory */
-} cbd_t;
-
-#define BD_SC_EMPTY	((ushort)0x8000)	/* Receive is empty */
-#define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
-#define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
-#define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
-#define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame */
-#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
-#define BD_SC_ID	((ushort)0x0100)	/* Rec'd too many idles */
-#define BD_SC_P		((ushort)0x0100)	/* xmt preamble */
-#define BD_SC_BR	((ushort)0x0020)	/* Break received */
-#define BD_SC_FR	((ushort)0x0010)	/* Framing error */
-#define BD_SC_PR	((ushort)0x0008)	/* Parity error */
-#define BD_SC_OV	((ushort)0x0002)	/* Overrun */
-#define BD_SC_CD	((ushort)0x0001)	/* ?? */
-
-/* Function code bits, usually generic to devices.
-*/
-#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
-#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
-#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
-#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
-#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
-
-/* Parameter RAM offsets from the base.
-*/
-#define PROFF_SCC1		((uint)0x8000)
-#define PROFF_SCC2		((uint)0x8100)
-#define PROFF_SCC3		((uint)0x8200)
-#define PROFF_SCC4		((uint)0x8300)
-#define PROFF_FCC1		((uint)0x8400)
-#define PROFF_FCC2		((uint)0x8500)
-#define PROFF_FCC3		((uint)0x8600)
-#define PROFF_MCC1		((uint)0x8700)
-#define PROFF_SMC1_BASE		((uint)0x87fc)
-#define PROFF_IDMA1_BASE	((uint)0x87fe)
-#define PROFF_MCC2		((uint)0x8800)
-#define PROFF_SMC2_BASE		((uint)0x88fc)
-#define PROFF_IDMA2_BASE	((uint)0x88fe)
-#define PROFF_SPI_BASE		((uint)0x89fc)
-#define PROFF_IDMA3_BASE	((uint)0x89fe)
-#define PROFF_TIMERS		((uint)0x8ae0)
-#define PROFF_REVNUM		((uint)0x8af0)
-#define PROFF_RAND		((uint)0x8af8)
-#define PROFF_I2C_BASE		((uint)0x8afc)
-#define PROFF_IDMA4_BASE	((uint)0x8afe)
-
-/* The SMCs are relocated to any of the first eight DPRAM pages.
- * We will fix these at the first locations of DPRAM, until we
- * get some microcode patches :-).
- * The parameter ram space for the SMCs is fifty-some bytes, and
- * they are required to start on a 64 byte boundary.
- */
-#define PROFF_SMC1	(0)
-#define PROFF_SMC2	(64)
-
-
-/* Define enough so I can at least use the serial port as a UART.
- */
-typedef struct smc_uart {
-	ushort	smc_rbase;	/* Rx Buffer descriptor base address */
-	ushort	smc_tbase;	/* Tx Buffer descriptor base address */
-	u_char	smc_rfcr;	/* Rx function code */
-	u_char	smc_tfcr;	/* Tx function code */
-	ushort	smc_mrblr;	/* Max receive buffer length */
-	uint	smc_rstate;	/* Internal */
-	uint	smc_idp;	/* Internal */
-	ushort	smc_rbptr;	/* Internal */
-	ushort	smc_ibc;	/* Internal */
-	uint	smc_rxtmp;	/* Internal */
-	uint	smc_tstate;	/* Internal */
-	uint	smc_tdp;	/* Internal */
-	ushort	smc_tbptr;	/* Internal */
-	ushort	smc_tbc;	/* Internal */
-	uint	smc_txtmp;	/* Internal */
-	ushort	smc_maxidl;	/* Maximum idle characters */
-	ushort	smc_tmpidl;	/* Temporary idle counter */
-	ushort	smc_brklen;	/* Last received break length */
-	ushort	smc_brkec;	/* rcv'd break condition counter */
-	ushort	smc_brkcr;	/* xmt break count register */
-	ushort	smc_rmask;	/* Temporary bit mask */
-	uint	smc_stmp;	/* SDMA Temp */
-} smc_uart_t;
-
-/* SMC uart mode register (Internal memory map).
-*/
-#define SMCMR_REN	((ushort)0x0001)
-#define SMCMR_TEN	((ushort)0x0002)
-#define SMCMR_DM	((ushort)0x000c)
-#define SMCMR_SM_GCI	((ushort)0x0000)
-#define SMCMR_SM_UART	((ushort)0x0020)
-#define SMCMR_SM_TRANS	((ushort)0x0030)
-#define SMCMR_SM_MASK	((ushort)0x0030)
-#define SMCMR_PM_EVEN	((ushort)0x0100)	/* Even parity, else odd */
-#define SMCMR_REVD	SMCMR_PM_EVEN
-#define SMCMR_PEN	((ushort)0x0200)	/* Parity enable */
-#define SMCMR_BS	SMCMR_PEN
-#define SMCMR_SL	((ushort)0x0400)	/* Two stops, else one */
-#define SMCR_CLEN_MASK	((ushort)0x7800)	/* Character length */
-#define smcr_mk_clen(C)	(((C) << 11) & SMCR_CLEN_MASK)
-
-/* SMC Event and Mask register.
-*/
-#define SMCM_BRKE       ((unsigned char)0x40)   /* When in UART Mode */
-#define SMCM_BRK        ((unsigned char)0x10)   /* When in UART Mode */
-#define SMCM_TXE	((unsigned char)0x10)
-#define SMCM_BSY	((unsigned char)0x04)
-#define SMCM_TX		((unsigned char)0x02)
-#define SMCM_RX		((unsigned char)0x01)
-
-/* Baud rate generators.
-*/
-#define CPM_BRG_RST		((uint)0x00020000)
-#define CPM_BRG_EN		((uint)0x00010000)
-#define CPM_BRG_EXTC_INT	((uint)0x00000000)
-#define CPM_BRG_EXTC_CLK3_9	((uint)0x00004000)
-#define CPM_BRG_EXTC_CLK5_15	((uint)0x00008000)
-#define CPM_BRG_ATB		((uint)0x00002000)
-#define CPM_BRG_CD_MASK		((uint)0x00001ffe)
-#define CPM_BRG_DIV16		((uint)0x00000001)
-
-/* SCCs.
-*/
-#define SCC_GSMRH_IRP		((uint)0x00040000)
-#define SCC_GSMRH_GDE		((uint)0x00010000)
-#define SCC_GSMRH_TCRC_CCITT	((uint)0x00008000)
-#define SCC_GSMRH_TCRC_BISYNC	((uint)0x00004000)
-#define SCC_GSMRH_TCRC_HDLC	((uint)0x00000000)
-#define SCC_GSMRH_REVD		((uint)0x00002000)
-#define SCC_GSMRH_TRX		((uint)0x00001000)
-#define SCC_GSMRH_TTX		((uint)0x00000800)
-#define SCC_GSMRH_CDP		((uint)0x00000400)
-#define SCC_GSMRH_CTSP		((uint)0x00000200)
-#define SCC_GSMRH_CDS		((uint)0x00000100)
-#define SCC_GSMRH_CTSS		((uint)0x00000080)
-#define SCC_GSMRH_TFL		((uint)0x00000040)
-#define SCC_GSMRH_RFW		((uint)0x00000020)
-#define SCC_GSMRH_TXSY		((uint)0x00000010)
-#define SCC_GSMRH_SYNL16	((uint)0x0000000c)
-#define SCC_GSMRH_SYNL8		((uint)0x00000008)
-#define SCC_GSMRH_SYNL4		((uint)0x00000004)
-#define SCC_GSMRH_RTSM		((uint)0x00000002)
-#define SCC_GSMRH_RSYN		((uint)0x00000001)
-
-#define SCC_GSMRL_SIR		((uint)0x80000000)	/* SCC2 only */
-#define SCC_GSMRL_EDGE_NONE	((uint)0x60000000)
-#define SCC_GSMRL_EDGE_NEG	((uint)0x40000000)
-#define SCC_GSMRL_EDGE_POS	((uint)0x20000000)
-#define SCC_GSMRL_EDGE_BOTH	((uint)0x00000000)
-#define SCC_GSMRL_TCI		((uint)0x10000000)
-#define SCC_GSMRL_TSNC_3	((uint)0x0c000000)
-#define SCC_GSMRL_TSNC_4	((uint)0x08000000)
-#define SCC_GSMRL_TSNC_14	((uint)0x04000000)
-#define SCC_GSMRL_TSNC_INF	((uint)0x00000000)
-#define SCC_GSMRL_RINV		((uint)0x02000000)
-#define SCC_GSMRL_TINV		((uint)0x01000000)
-#define SCC_GSMRL_TPL_128	((uint)0x00c00000)
-#define SCC_GSMRL_TPL_64	((uint)0x00a00000)
-#define SCC_GSMRL_TPL_48	((uint)0x00800000)
-#define SCC_GSMRL_TPL_32	((uint)0x00600000)
-#define SCC_GSMRL_TPL_16	((uint)0x00400000)
-#define SCC_GSMRL_TPL_8		((uint)0x00200000)
-#define SCC_GSMRL_TPL_NONE	((uint)0x00000000)
-#define SCC_GSMRL_TPP_ALL1	((uint)0x00180000)
-#define SCC_GSMRL_TPP_01	((uint)0x00100000)
-#define SCC_GSMRL_TPP_10	((uint)0x00080000)
-#define SCC_GSMRL_TPP_ZEROS	((uint)0x00000000)
-#define SCC_GSMRL_TEND		((uint)0x00040000)
-#define SCC_GSMRL_TDCR_32	((uint)0x00030000)
-#define SCC_GSMRL_TDCR_16	((uint)0x00020000)
-#define SCC_GSMRL_TDCR_8	((uint)0x00010000)
-#define SCC_GSMRL_TDCR_1	((uint)0x00000000)
-#define SCC_GSMRL_RDCR_32	((uint)0x0000c000)
-#define SCC_GSMRL_RDCR_16	((uint)0x00008000)
-#define SCC_GSMRL_RDCR_8	((uint)0x00004000)
-#define SCC_GSMRL_RDCR_1	((uint)0x00000000)
-#define SCC_GSMRL_RENC_DFMAN	((uint)0x00003000)
-#define SCC_GSMRL_RENC_MANCH	((uint)0x00002000)
-#define SCC_GSMRL_RENC_FM0	((uint)0x00001000)
-#define SCC_GSMRL_RENC_NRZI	((uint)0x00000800)
-#define SCC_GSMRL_RENC_NRZ	((uint)0x00000000)
-#define SCC_GSMRL_TENC_DFMAN	((uint)0x00000600)
-#define SCC_GSMRL_TENC_MANCH	((uint)0x00000400)
-#define SCC_GSMRL_TENC_FM0	((uint)0x00000200)
-#define SCC_GSMRL_TENC_NRZI	((uint)0x00000100)
-#define SCC_GSMRL_TENC_NRZ	((uint)0x00000000)
-#define SCC_GSMRL_DIAG_LE	((uint)0x000000c0)	/* Loop and echo */
-#define SCC_GSMRL_DIAG_ECHO	((uint)0x00000080)
-#define SCC_GSMRL_DIAG_LOOP	((uint)0x00000040)
-#define SCC_GSMRL_DIAG_NORM	((uint)0x00000000)
-#define SCC_GSMRL_ENR		((uint)0x00000020)
-#define SCC_GSMRL_ENT		((uint)0x00000010)
-#define SCC_GSMRL_MODE_ENET	((uint)0x0000000c)
-#define SCC_GSMRL_MODE_DDCMP	((uint)0x00000009)
-#define SCC_GSMRL_MODE_BISYNC	((uint)0x00000008)
-#define SCC_GSMRL_MODE_V14	((uint)0x00000007)
-#define SCC_GSMRL_MODE_AHDLC	((uint)0x00000006)
-#define SCC_GSMRL_MODE_PROFIBUS	((uint)0x00000005)
-#define SCC_GSMRL_MODE_UART	((uint)0x00000004)
-#define SCC_GSMRL_MODE_SS7	((uint)0x00000003)
-#define SCC_GSMRL_MODE_ATALK	((uint)0x00000002)
-#define SCC_GSMRL_MODE_HDLC	((uint)0x00000000)
-
-#define SCC_TODR_TOD		((ushort)0x8000)
-
-/* SCC Event and Mask register.
-*/
-#define SCCM_TXE	((unsigned char)0x10)
-#define SCCM_BSY	((unsigned char)0x04)
-#define SCCM_TX		((unsigned char)0x02)
-#define SCCM_RX		((unsigned char)0x01)
-
-typedef struct scc_param {
-	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
-	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
-	u_char	scc_rfcr;	/* Rx function code */
-	u_char	scc_tfcr;	/* Tx function code */
-	ushort	scc_mrblr;	/* Max receive buffer length */
-	uint	scc_rstate;	/* Internal */
-	uint	scc_idp;	/* Internal */
-	ushort	scc_rbptr;	/* Internal */
-	ushort	scc_ibc;	/* Internal */
-	uint	scc_rxtmp;	/* Internal */
-	uint	scc_tstate;	/* Internal */
-	uint	scc_tdp;	/* Internal */
-	ushort	scc_tbptr;	/* Internal */
-	ushort	scc_tbc;	/* Internal */
-	uint	scc_txtmp;	/* Internal */
-	uint	scc_rcrc;	/* Internal */
-	uint	scc_tcrc;	/* Internal */
-} sccp_t;
-
-/* CPM Ethernet through SCC1.
- */
-typedef struct scc_enet {
-	sccp_t	sen_genscc;
-	uint	sen_cpres;	/* Preset CRC */
-	uint	sen_cmask;	/* Constant mask for CRC */
-	uint	sen_crcec;	/* CRC Error counter */
-	uint	sen_alec;	/* alignment error counter */
-	uint	sen_disfc;	/* discard frame counter */
-	ushort	sen_pads;	/* Tx short frame pad character */
-	ushort	sen_retlim;	/* Retry limit threshold */
-	ushort	sen_retcnt;	/* Retry limit counter */
-	ushort	sen_maxflr;	/* maximum frame length register */
-	ushort	sen_minflr;	/* minimum frame length register */
-	ushort	sen_maxd1;	/* maximum DMA1 length */
-	ushort	sen_maxd2;	/* maximum DMA2 length */
-	ushort	sen_maxd;	/* Rx max DMA */
-	ushort	sen_dmacnt;	/* Rx DMA counter */
-	ushort	sen_maxb;	/* Max BD byte count */
-	ushort	sen_gaddr1;	/* Group address filter */
-	ushort	sen_gaddr2;
-	ushort	sen_gaddr3;
-	ushort	sen_gaddr4;
-	uint	sen_tbuf0data0;	/* Save area 0 - current frame */
-	uint	sen_tbuf0data1;	/* Save area 1 - current frame */
-	uint	sen_tbuf0rba;	/* Internal */
-	uint	sen_tbuf0crc;	/* Internal */
-	ushort	sen_tbuf0bcnt;	/* Internal */
-	ushort	sen_paddrh;	/* physical address (MSB) */
-	ushort	sen_paddrm;
-	ushort	sen_paddrl;	/* physical address (LSB) */
-	ushort	sen_pper;	/* persistence */
-	ushort	sen_rfbdptr;	/* Rx first BD pointer */
-	ushort	sen_tfbdptr;	/* Tx first BD pointer */
-	ushort	sen_tlbdptr;	/* Tx last BD pointer */
-	uint	sen_tbuf1data0;	/* Save area 0 - current frame */
-	uint	sen_tbuf1data1;	/* Save area 1 - current frame */
-	uint	sen_tbuf1rba;	/* Internal */
-	uint	sen_tbuf1crc;	/* Internal */
-	ushort	sen_tbuf1bcnt;	/* Internal */
-	ushort	sen_txlen;	/* Tx Frame length counter */
-	ushort	sen_iaddr1;	/* Individual address filter */
-	ushort	sen_iaddr2;
-	ushort	sen_iaddr3;
-	ushort	sen_iaddr4;
-	ushort	sen_boffcnt;	/* Backoff counter */
-
-	/* NOTE: Some versions of the manual have the following items
-	 * incorrectly documented.  Below is the proper order.
-	 */
-	ushort	sen_taddrh;	/* temp address (MSB) */
-	ushort	sen_taddrm;
-	ushort	sen_taddrl;	/* temp address (LSB) */
-} scc_enet_t;
-
-
-/* SCC Event register as used by Ethernet.
-*/
-#define SCCE_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
-#define SCCE_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
-#define SCCE_ENET_RXF	((ushort)0x0008)	/* Full frame received */
-#define SCCE_ENET_BSY	((ushort)0x0004)	/* All incoming buffers full */
-#define SCCE_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
-#define SCCE_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
-
-/* SCC Mode Register (PSMR) as used by Ethernet.
-*/
-#define SCC_PSMR_HBC	((ushort)0x8000)	/* Enable heartbeat */
-#define SCC_PSMR_FC	((ushort)0x4000)	/* Force collision */
-#define SCC_PSMR_RSH	((ushort)0x2000)	/* Receive short frames */
-#define SCC_PSMR_IAM	((ushort)0x1000)	/* Check individual hash */
-#define SCC_PSMR_ENCRC	((ushort)0x0800)	/* Ethernet CRC mode */
-#define SCC_PSMR_PRO	((ushort)0x0200)	/* Promiscuous mode */
-#define SCC_PSMR_BRO	((ushort)0x0100)	/* Catch broadcast pkts */
-#define SCC_PSMR_SBT	((ushort)0x0080)	/* Special backoff timer */
-#define SCC_PSMR_LPB	((ushort)0x0040)	/* Set Loopback mode */
-#define SCC_PSMR_SIP	((ushort)0x0020)	/* Sample Input Pins */
-#define SCC_PSMR_LCW	((ushort)0x0010)	/* Late collision window */
-#define SCC_PSMR_NIB22	((ushort)0x000a)	/* Start frame search */
-#define SCC_PSMR_FDE	((ushort)0x0001)	/* Full duplex enable */
-
-/* Buffer descriptor control/status used by Ethernet receive.
- * Common to SCC and FCC.
- */
-#define BD_ENET_RX_EMPTY	((ushort)0x8000)
-#define BD_ENET_RX_WRAP		((ushort)0x2000)
-#define BD_ENET_RX_INTR		((ushort)0x1000)
-#define BD_ENET_RX_LAST		((ushort)0x0800)
-#define BD_ENET_RX_FIRST	((ushort)0x0400)
-#define BD_ENET_RX_MISS		((ushort)0x0100)
-#define BD_ENET_RX_BC		((ushort)0x0080)	/* FCC Only */
-#define BD_ENET_RX_MC		((ushort)0x0040)	/* FCC Only */
-#define BD_ENET_RX_LG		((ushort)0x0020)
-#define BD_ENET_RX_NO		((ushort)0x0010)
-#define BD_ENET_RX_SH		((ushort)0x0008)
-#define BD_ENET_RX_CR		((ushort)0x0004)
-#define BD_ENET_RX_OV		((ushort)0x0002)
-#define BD_ENET_RX_CL		((ushort)0x0001)
-#define BD_ENET_RX_STATS	((ushort)0x01ff)	/* All status bits */
-
-/* Buffer descriptor control/status used by Ethernet transmit.
- * Common to SCC and FCC.
- */
-#define BD_ENET_TX_READY	((ushort)0x8000)
-#define BD_ENET_TX_PAD		((ushort)0x4000)
-#define BD_ENET_TX_WRAP		((ushort)0x2000)
-#define BD_ENET_TX_INTR		((ushort)0x1000)
-#define BD_ENET_TX_LAST		((ushort)0x0800)
-#define BD_ENET_TX_TC		((ushort)0x0400)
-#define BD_ENET_TX_DEF		((ushort)0x0200)
-#define BD_ENET_TX_HB		((ushort)0x0100)
-#define BD_ENET_TX_LC		((ushort)0x0080)
-#define BD_ENET_TX_RL		((ushort)0x0040)
-#define BD_ENET_TX_RCMASK	((ushort)0x003c)
-#define BD_ENET_TX_UN		((ushort)0x0002)
-#define BD_ENET_TX_CSL		((ushort)0x0001)
-#define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
-
-/* SCC as UART
-*/
-typedef struct scc_uart {
-	sccp_t	scc_genscc;
-	uint	scc_res1;	/* Reserved */
-	uint	scc_res2;	/* Reserved */
-	ushort	scc_maxidl;	/* Maximum idle chars */
-	ushort	scc_idlc;	/* temp idle counter */
-	ushort	scc_brkcr;	/* Break count register */
-	ushort	scc_parec;	/* receive parity error counter */
-	ushort	scc_frmec;	/* receive framing error counter */
-	ushort	scc_nosec;	/* receive noise counter */
-	ushort	scc_brkec;	/* receive break condition counter */
-	ushort	scc_brkln;	/* last received break length */
-	ushort	scc_uaddr1;	/* UART address character 1 */
-	ushort	scc_uaddr2;	/* UART address character 2 */
-	ushort	scc_rtemp;	/* Temp storage */
-	ushort	scc_toseq;	/* Transmit out of sequence char */
-	ushort	scc_char1;	/* control character 1 */
-	ushort	scc_char2;	/* control character 2 */
-	ushort	scc_char3;	/* control character 3 */
-	ushort	scc_char4;	/* control character 4 */
-	ushort	scc_char5;	/* control character 5 */
-	ushort	scc_char6;	/* control character 6 */
-	ushort	scc_char7;	/* control character 7 */
-	ushort	scc_char8;	/* control character 8 */
-	ushort	scc_rccm;	/* receive control character mask */
-	ushort	scc_rccr;	/* receive control character register */
-	ushort	scc_rlbc;	/* receive last break character */
-} scc_uart_t;
-
-/* SCC Event and Mask registers when it is used as a UART.
-*/
-#define UART_SCCM_GLR		((ushort)0x1000)
-#define UART_SCCM_GLT		((ushort)0x0800)
-#define UART_SCCM_AB		((ushort)0x0200)
-#define UART_SCCM_IDL		((ushort)0x0100)
-#define UART_SCCM_GRA		((ushort)0x0080)
-#define UART_SCCM_BRKE		((ushort)0x0040)
-#define UART_SCCM_BRKS		((ushort)0x0020)
-#define UART_SCCM_CCR		((ushort)0x0008)
-#define UART_SCCM_BSY		((ushort)0x0004)
-#define UART_SCCM_TX		((ushort)0x0002)
-#define UART_SCCM_RX		((ushort)0x0001)
-
-/* The SCC PMSR when used as a UART.
-*/
-#define SCU_PMSR_FLC		((ushort)0x8000)
-#define SCU_PMSR_SL		((ushort)0x4000)
-#define SCU_PMSR_CL		((ushort)0x3000)
-#define SCU_PMSR_UM		((ushort)0x0c00)
-#define SCU_PMSR_FRZ		((ushort)0x0200)
-#define SCU_PMSR_RZS		((ushort)0x0100)
-#define SCU_PMSR_SYN		((ushort)0x0080)
-#define SCU_PMSR_DRT		((ushort)0x0040)
-#define SCU_PMSR_PEN		((ushort)0x0010)
-#define SCU_PMSR_RPM		((ushort)0x000c)
-#define SCU_PMSR_REVP		((ushort)0x0008)
-#define SCU_PMSR_TPM		((ushort)0x0003)
-#define SCU_PMSR_TEVP		((ushort)0x0003)
-
-/* CPM Transparent mode SCC.
- */
-typedef struct scc_trans {
-	sccp_t	st_genscc;
-	uint	st_cpres;	/* Preset CRC */
-	uint	st_cmask;	/* Constant mask for CRC */
-} scc_trans_t;
-
-#define BD_SCC_TX_LAST		((ushort)0x0800)
-
-/* How about some FCCs.....
-*/
-#define FCC_GFMR_DIAG_NORM	((uint)0x00000000)
-#define FCC_GFMR_DIAG_LE	((uint)0x40000000)
-#define FCC_GFMR_DIAG_AE	((uint)0x80000000)
-#define FCC_GFMR_DIAG_ALE	((uint)0xc0000000)
-#define FCC_GFMR_TCI		((uint)0x20000000)
-#define FCC_GFMR_TRX		((uint)0x10000000)
-#define FCC_GFMR_TTX		((uint)0x08000000)
-#define FCC_GFMR_TTX		((uint)0x08000000)
-#define FCC_GFMR_CDP		((uint)0x04000000)
-#define FCC_GFMR_CTSP		((uint)0x02000000)
-#define FCC_GFMR_CDS		((uint)0x01000000)
-#define FCC_GFMR_CTSS		((uint)0x00800000)
-#define FCC_GFMR_SYNL_NONE	((uint)0x00000000)
-#define FCC_GFMR_SYNL_AUTO	((uint)0x00004000)
-#define FCC_GFMR_SYNL_8		((uint)0x00008000)
-#define FCC_GFMR_SYNL_16	((uint)0x0000c000)
-#define FCC_GFMR_RTSM		((uint)0x00002000)
-#define FCC_GFMR_RENC_NRZ	((uint)0x00000000)
-#define FCC_GFMR_RENC_NRZI	((uint)0x00000800)
-#define FCC_GFMR_REVD		((uint)0x00000400)
-#define FCC_GFMR_TENC_NRZ	((uint)0x00000000)
-#define FCC_GFMR_TENC_NRZI	((uint)0x00000100)
-#define FCC_GFMR_TCRC_16	((uint)0x00000000)
-#define FCC_GFMR_TCRC_32	((uint)0x00000080)
-#define FCC_GFMR_ENR		((uint)0x00000020)
-#define FCC_GFMR_ENT		((uint)0x00000010)
-#define FCC_GFMR_MODE_ENET	((uint)0x0000000c)
-#define FCC_GFMR_MODE_ATM	((uint)0x0000000a)
-#define FCC_GFMR_MODE_HDLC	((uint)0x00000000)
-
-/* Generic FCC parameter ram.
-*/
-typedef struct fcc_param {
-	ushort	fcc_riptr;	/* Rx Internal temp pointer */
-	ushort	fcc_tiptr;	/* Tx Internal temp pointer */
-	ushort	fcc_res1;
-	ushort	fcc_mrblr;	/* Max receive buffer length, mod 32 bytes */
-	uint	fcc_rstate;	/* Upper byte is Func code, must be set */
-	uint	fcc_rbase;	/* Receive BD base */
-	ushort	fcc_rbdstat;	/* RxBD status */
-	ushort	fcc_rbdlen;	/* RxBD down counter */
-	uint	fcc_rdptr;	/* RxBD internal data pointer */
-	uint	fcc_tstate;	/* Upper byte is Func code, must be set */
-	uint	fcc_tbase;	/* Transmit BD base */
-	ushort	fcc_tbdstat;	/* TxBD status */
-	ushort	fcc_tbdlen;	/* TxBD down counter */
-	uint	fcc_tdptr;	/* TxBD internal data pointer */
-	uint	fcc_rbptr;	/* Rx BD Internal buf pointer */
-	uint	fcc_tbptr;	/* Tx BD Internal buf pointer */
-	uint	fcc_rcrc;	/* Rx temp CRC */
-	uint	fcc_res2;
-	uint	fcc_tcrc;	/* Tx temp CRC */
-} fccp_t;
-
-
-/* Ethernet controller through FCC.
-*/
-typedef struct fcc_enet {
-	fccp_t	fen_genfcc;
-	uint	fen_statbuf;	/* Internal status buffer */
-	uint	fen_camptr;	/* CAM address */
-	uint	fen_cmask;	/* Constant mask for CRC */
-	uint	fen_cpres;	/* Preset CRC */
-	uint	fen_crcec;	/* CRC Error counter */
-	uint	fen_alec;	/* alignment error counter */
-	uint	fen_disfc;	/* discard frame counter */
-	ushort	fen_retlim;	/* Retry limit */
-	ushort	fen_retcnt;	/* Retry counter */
-	ushort	fen_pper;	/* Persistence */
-	ushort	fen_boffcnt;	/* backoff counter */
-	uint	fen_gaddrh;	/* Group address filter, high 32-bits */
-	uint	fen_gaddrl;	/* Group address filter, low 32-bits */
-	ushort	fen_tfcstat;	/* out of sequence TxBD */
-	ushort	fen_tfclen;
-	uint	fen_tfcptr;
-	ushort	fen_mflr;	/* Maximum frame length (1518) */
-	ushort	fen_paddrh;	/* MAC address */
-	ushort	fen_paddrm;
-	ushort	fen_paddrl;
-	ushort	fen_ibdcount;	/* Internal BD counter */
-	ushort	fen_idbstart;	/* Internal BD start pointer */
-	ushort	fen_ibdend;	/* Internal BD end pointer */
-	ushort	fen_txlen;	/* Internal Tx frame length counter */
-	uint	fen_ibdbase[8]; /* Internal use */
-	uint	fen_iaddrh;	/* Individual address filter */
-	uint	fen_iaddrl;
-	ushort	fen_minflr;	/* Minimum frame length (64) */
-	ushort	fen_taddrh;	/* Filter transfer MAC address */
-	ushort	fen_taddrm;
-	ushort	fen_taddrl;
-	ushort	fen_padptr;	/* Pointer to pad byte buffer */
-	ushort	fen_cftype;	/* control frame type */
-	ushort	fen_cfrange;	/* control frame range */
-	ushort	fen_maxb;	/* maximum BD count */
-	ushort	fen_maxd1;	/* Max DMA1 length (1520) */
-	ushort	fen_maxd2;	/* Max DMA2 length (1520) */
-	ushort	fen_maxd;	/* internal max DMA count */
-	ushort	fen_dmacnt;	/* internal DMA counter */
-	uint	fen_octc;	/* Total octect counter */
-	uint	fen_colc;	/* Total collision counter */
-	uint	fen_broc;	/* Total broadcast packet counter */
-	uint	fen_mulc;	/* Total multicast packet count */
-	uint	fen_uspc;	/* Total packets < 64 bytes */
-	uint	fen_frgc;	/* Total packets < 64 bytes with errors */
-	uint	fen_ospc;	/* Total packets > 1518 */
-	uint	fen_jbrc;	/* Total packets > 1518 with errors */
-	uint	fen_p64c;	/* Total packets == 64 bytes */
-	uint	fen_p65c;	/* Total packets 64 < bytes <= 127 */
-	uint	fen_p128c;	/* Total packets 127 < bytes <= 255 */
-	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
-	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
-	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
-	uint	fen_cambuf;	/* Internal CAM buffer poiner */
-	ushort	fen_rfthr;	/* Received frames threshold */
-	ushort	fen_rfcnt;	/* Received frames count */
-} fcc_enet_t;
-
-/* FCC Event/Mask register as used by Ethernet.
-*/
-#define FCC_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
-#define FCC_ENET_RXC	((ushort)0x0040)	/* Control Frame Received */
-#define FCC_ENET_TXC	((ushort)0x0020)	/* Out of seq. Tx sent */
-#define FCC_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
-#define FCC_ENET_RXF	((ushort)0x0008)	/* Full frame received */
-#define FCC_ENET_BSY	((ushort)0x0004)	/* Busy.  Rx Frame dropped */
-#define FCC_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
-#define FCC_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
-
-/* FCC Mode Register (FPSMR) as used by Ethernet.
-*/
-#define FCC_PSMR_HBC	((uint)0x80000000)	/* Enable heartbeat */
-#define FCC_PSMR_FC	((uint)0x40000000)	/* Force Collision */
-#define FCC_PSMR_SBT	((uint)0x20000000)	/* Stop backoff timer */
-#define FCC_PSMR_LPB	((uint)0x10000000)	/* Local protect. 1 = FDX */
-#define FCC_PSMR_LCW	((uint)0x08000000)	/* Late collision select */
-#define FCC_PSMR_FDE	((uint)0x04000000)	/* Full Duplex Enable */
-#define FCC_PSMR_MON	((uint)0x02000000)	/* RMON Enable */
-#define FCC_PSMR_PRO	((uint)0x00400000)	/* Promiscuous Enable */
-#define FCC_PSMR_FCE	((uint)0x00200000)	/* Flow Control Enable */
-#define FCC_PSMR_RSH	((uint)0x00100000)	/* Receive Short Frames */
-#define FCC_PSMR_CAM	((uint)0x00000400)	/* CAM enable */
-#define FCC_PSMR_BRO	((uint)0x00000200)	/* Broadcast pkt discard */
-#define FCC_PSMR_ENCRC	((uint)0x00000080)	/* Use 32-bit CRC */
-
-/* IIC parameter RAM.
-*/
-typedef struct iic {
-	ushort	iic_rbase;	/* Rx Buffer descriptor base address */
-	ushort	iic_tbase;	/* Tx Buffer descriptor base address */
-	u_char	iic_rfcr;	/* Rx function code */
-	u_char	iic_tfcr;	/* Tx function code */
-	ushort	iic_mrblr;	/* Max receive buffer length */
-	uint	iic_rstate;	/* Internal */
-	uint	iic_rdp;	/* Internal */
-	ushort	iic_rbptr;	/* Internal */
-	ushort	iic_rbc;	/* Internal */
-	uint	iic_rxtmp;	/* Internal */
-	uint	iic_tstate;	/* Internal */
-	uint	iic_tdp;	/* Internal */
-	ushort	iic_tbptr;	/* Internal */
-	ushort	iic_tbc;	/* Internal */
-	uint	iic_txtmp;	/* Internal */
-} iic_t;
-
-#define BD_IIC_START		((ushort)0x0400)
-
-#endif /* __CPM_82XX__ */
-#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/ibm4xx.h linux-2.4.26-pre6/include/asm-ppc/ibm4xx.h
--- linux-2.4.25/include/asm-ppc/ibm4xx.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/ibm4xx.h	2004-03-25 00:20:02.000000000 +0000
@@ -62,10 +62,22 @@ do {						\
 #include <platforms/cpci405.h>
 #endif
 
+#if defined(CONFIG_EP405)
+#include <platforms/ep405.h>
+#endif
+
 #if defined(CONFIG_OAK)
 #include <platforms/oak.h>
 #endif
 
+#if defined(CONFIG_REDWOOD_5)
+#include <platforms/redwood5.h>
+#endif
+
+#if defined(CONFIG_REDWOOD_6)
+#include <platforms/redwood6.h>
+#endif
+
 #if defined(CONFIG_WALNUT)
 #include <platforms/walnut.h>
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/immap_8260.h linux-2.4.26-pre6/include/asm-ppc/immap_8260.h
--- linux-2.4.25/include/asm-ppc/immap_8260.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/immap_8260.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,433 +0,0 @@
-/*
- * MPC8260 Internal Memory Map
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- *
- * The Internal Memory Map of the 8260.  I don't know how generic
- * this will be, as I don't have any knowledge of the subsequent
- * parts at this time.  I copied this from the 8xx_immap.h.
- */
-#ifdef __KERNEL__
-#ifndef __IMMAP_82XX__
-#define __IMMAP_82XX__
-
-/* System configuration registers.
-*/
-typedef	struct sys_conf {
-	uint	sc_siumcr;
-	uint	sc_sypcr;
-	char	res1[6];
-	ushort	sc_swsr;
-	char	res2[20];
-	uint	sc_bcr;
-	u_char	sc_ppc_acr;
-	char	res3[3];
-	uint	sc_ppc_alrh;
-	uint	sc_ppc_alrl;
-	u_char	sc_lcl_acr;
-	char	res4[3];
-	uint	sc_lcl_alrh;
-	uint	sc_lcl_alrl;
-	uint	sc_tescr1;
-	uint	sc_tescr2;
-	uint	sc_ltescr1;
-	uint	sc_ltescr2;
-	uint	sc_pdtea;
-	u_char	sc_pdtem;
-	char	res5[3];
-	uint	sc_ldtea;
-	u_char	sc_ldtem;
-	char	res6[163];
-} sysconf8260_t;
-
-
-/* Memory controller registers.
-*/
-typedef struct	mem_ctlr {
-	uint	memc_br0;
-	uint	memc_or0;
-	uint	memc_br1;
-	uint	memc_or1;
-	uint	memc_br2;
-	uint	memc_or2;
-	uint	memc_br3;
-	uint	memc_or3;
-	uint	memc_br4;
-	uint	memc_or4;
-	uint	memc_br5;
-	uint	memc_or5;
-	uint	memc_br6;
-	uint	memc_or6;
-	uint	memc_br7;
-	uint	memc_or7;
-	uint	memc_br8;
-	uint	memc_or8;
-	uint	memc_br9;
-	uint	memc_or9;
-	uint	memc_br10;
-	uint	memc_or10;
-	uint	memc_br11;
-	uint	memc_or11;
-	char	res1[8];
-	uint	memc_mar;
-	char	res2[4];
-	uint	memc_mamr;
-	uint	memc_mbmr;
-	uint	memc_mcmr;
-	char	res3[8];
-	ushort	memc_mptpr;
-	char	res4[2];
-	uint	memc_mdr;
-	char	res5[4];
-	uint	memc_psdmr;
-	uint	memc_lsdmr;
-	u_char	memc_purt;
-	char	res6[3];
-	u_char	memc_psrt;
-	char	res7[3];
-	u_char	memc_lurt;
-	char	res8[3];
-	u_char	memc_lsrt;
-	char	res9[3];
-	uint	memc_immr;
-	char	res10[84];
-} memctl8260_t;
-
-/* System Integration Timers.
-*/
-typedef struct	sys_int_timers {
-	char	res1[32];
-	ushort	sit_tmcntsc;
-	char	res2[2];
-	uint	sit_tmcnt;
-	char	res3[4];
-	uint	sit_tmcntal;
-	char	res4[16];
-	ushort	sit_piscr;
-	char	res5[2];
-	uint	sit_pitc;
-	uint	sit_pitr;
-	char	res6[94];
-	char	res7[2390];
-} sit8260_t;
-
-#define PISCR_PIRQ_MASK		((ushort)0xff00)
-#define PISCR_PS		((ushort)0x0080)
-#define PISCR_PIE		((ushort)0x0004)
-#define PISCR_PTF		((ushort)0x0002)
-#define PISCR_PTE		((ushort)0x0001)
-
-/* Interrupt Controller.
-*/
-typedef struct interrupt_controller {
-	ushort	ic_sicr;
-	char	res1[2];
-	uint	ic_sivec;
-	uint	ic_sipnrh;
-	uint	ic_sipnrl;
-	uint	ic_siprr;
-	uint	ic_scprrh;
-	uint	ic_scprrl;
-	uint	ic_simrh;
-	uint	ic_simrl;
-	uint	ic_siexr;
-	char	res2[88];
-} intctl8260_t;
-
-/* Clocks and Reset.
-*/
-typedef struct clk_and_reset {
-	uint	car_sccr;
-	char	res1[4];
-	uint	car_scmr;
-	char	res2[4];
-	uint	car_rsr;
-	uint	car_rmr;
-	char	res[104];
-} car8260_t;
-
-/* Input/Output Port control/status registers.
- * Names consistent with processor manual, although they are different
- * from the original 8xx names.......
- */
-typedef struct io_port {
-	uint	iop_pdira;
-	uint	iop_ppara;
-	uint	iop_psora;
-	uint	iop_podra;
-	uint	iop_pdata;
-	char	res1[12];
-	uint	iop_pdirb;
-	uint	iop_pparb;
-	uint	iop_psorb;
-	uint	iop_podrb;
-	uint	iop_pdatb;
-	char	res2[12];
-	uint	iop_pdirc;
-	uint	iop_pparc;
-	uint	iop_psorc;
-	uint	iop_podrc;
-	uint	iop_pdatc;
-	char	res3[12];
-	uint	iop_pdird;
-	uint	iop_ppard;
-	uint	iop_psord;
-	uint	iop_podrd;
-	uint	iop_pdatd;
-	char	res4[12];
-} iop8260_t;
-
-/* Communication Processor Module Timers
-*/
-typedef struct cpm_timers {
-	u_char	cpmt_tgcr1;
-	char	res1[3];
-	u_char	cpmt_tgcr2;
-	char	res2[11];
-	ushort	cpmt_tmr1;
-	ushort	cpmt_tmr2;
-	ushort	cpmt_trr1;
-	ushort	cpmt_trr2;
-	ushort	cpmt_tcr1;
-	ushort	cpmt_tcr2;
-	ushort	cpmt_tcn1;
-	ushort	cpmt_tcn2;
-	ushort	cpmt_tmr3;
-	ushort	cpmt_tmr4;
-	ushort	cpmt_trr3;
-	ushort	cpmt_trr4;
-	ushort	cpmt_tcr3;
-	ushort	cpmt_tcr4;
-	ushort	cpmt_tcn3;
-	ushort	cpmt_tcn4;
-	ushort	cpmt_ter1;
-	ushort	cpmt_ter2;
-	ushort	cpmt_ter3;
-	ushort	cpmt_ter4;
-	char	res3[584];
-} cpmtimer8260_t;
-
-/* DMA control/status registers.
-*/
-typedef struct sdma_csr {
-	char	res0[24];
-	u_char	sdma_sdsr;
-	char	res1[3];
-	u_char	sdma_sdmr;
-	char	res2[3];
-	u_char	sdma_idsr1;
-	char	res3[3];
-	u_char	sdma_idmr1;
-	char	res4[3];
-	u_char	sdma_idsr2;
-	char	res5[3];
-	u_char	sdma_idmr2;
-	char	res6[3];
-	u_char	sdma_idsr3;
-	char	res7[3];
-	u_char	sdma_idmr3;
-	char	res8[3];
-	u_char	sdma_idsr4;
-	char	res9[3];
-	u_char	sdma_idmr4;
-	char	res10[707];
-} sdma8260_t;
-
-/* Fast controllers
-*/
-typedef struct fcc {
-	uint	fcc_gfmr;
-	uint	fcc_fpsmr;
-	ushort	fcc_ftodr;
-	char	res1[2];
-	ushort	fcc_fdsr;
-	char	res2[2];
-	ushort	fcc_fcce;
-	char	res3[2];
-	ushort	fcc_fccm;
-	char	res4[2];
-	u_char	fcc_fccs;
-	char	res5[3];
-	u_char	fcc_ftirr_phy[4];
-} fcc_t;
-
-/* I2C
-*/
-typedef struct i2c {
-	u_char	i2c_i2mod;
-	char	res1[3];
-	u_char	i2c_i2add;
-	char	res2[3];
-	u_char	i2c_i2brg;
-	char	res3[3];
-	u_char	i2c_i2com;
-	char	res4[3];
-	u_char	i2c_i2cer;
-	char	res5[3];
-	u_char	i2c_i2cmr;
-	char	res6[331];
-} i2c8260_t;
-
-typedef struct scc {		/* Serial communication channels */
-	uint	scc_gsmrl;
-	uint	scc_gsmrh;
-	ushort	scc_pmsr;
-	char	res1[2];
-	ushort	scc_todr;
-	ushort	scc_dsr;
-	ushort	scc_scce;
-	char	res2[2];
-	ushort	scc_sccm;
-	char	res3;
-	u_char	scc_sccs;
-	char	res4[8];
-} scc_t;
-
-typedef struct smc {		/* Serial management channels */
-	char	res1[2];
-	ushort	smc_smcmr;
-	char	res2[2];
-	u_char	smc_smce;
-	char	res3[3];
-	u_char	smc_smcm;
-	char	res4[5];
-} smc_t;
-
-/* Serial Peripheral Interface.
-*/
-typedef struct spi {
-	ushort	spi_spmode;
-	char	res1[4];
-	u_char	spi_spie;
-	char	res2[3];
-	u_char	spi_spim;
-	char	res3[2];
-	u_char	spi_spcom;
-	char	res4[82];
-} spi_t;
-
-/* CPM Mux.
-*/
-typedef struct cpmux {
-	u_char	cmx_si1cr;
-	char	res1;
-	u_char	cmx_si2cr;
-	char	res2;
-	uint	cmx_fcr;
-	uint	cmx_scr;
-	u_char	cmx_smr;
-	char	res3;
-	ushort	cmx_uar;
-	char	res4[16];
-} cpmux_t;
-
-/* SIRAM control
-*/
-typedef struct siram {
-	ushort	si_amr;
-	ushort	si_bmr;
-	ushort	si_cmr;
-	ushort	si_dmr;
-	u_char	si_gmr;
-	char	res1;
-	u_char	si_cmdr;
-	char	res2;
-	u_char	si_str;
-	char	res3;
-	ushort	si_rsr;
-} siramctl_t;
-
-typedef struct mcc {
-	ushort	mcc_mcce;
-	char	res1[2];
-	ushort	mcc_mccm;
-	char	res2[2];
-	u_char	mcc_mccf;
-	char	res3[7];
-} mcc_t;
-
-typedef struct comm_proc {
-	uint	cp_cpcr;
-	uint	cp_rccr;
-	char	res1[14];
-	ushort	cp_rter;
-	char	res2[2];
-	ushort	cp_rtmr;
-	ushort	cp_rtscr;
-	char	res3[2];
-	uint	cp_rtsr;
-	char	res4[12];
-} cpm8260_t;
-
-/* ...and the whole thing wrapped up....
-*/
-typedef struct immap {
-	/* Some references are into the unique and known dpram spaces,
-	 * others are from the generic base.
-	 */
-#define im_dprambase	im_dpram1
-	u_char		im_dpram1[16*1024];
-	char		res1[16*1024];
-	u_char		im_dpram2[4*1024];
-	char		res2[8*1024];
-	u_char		im_dpram3[4*1024];
-	char		res3[16*1024];
-
-	sysconf8260_t	im_siu_conf;	/* SIU Configuration */
-	memctl8260_t	im_memctl;	/* Memory Controller */
-	sit8260_t	im_sit;		/* System Integration Timers */
-	intctl8260_t	im_intctl;	/* Interrupt Controller */
-	car8260_t	im_clkrst;	/* Clocks and reset */
-	iop8260_t	im_ioport;	/* IO Port control/status */
-	cpmtimer8260_t	im_cpmtimer;	/* CPM timers */
-	sdma8260_t	im_sdma;	/* SDMA control/status */
-
-	fcc_t		im_fcc[3];	/* Three FCCs */
-
-	char		res4[159];
-
-	/* First set of baud rate generators.
-	*/
-	char		res4a[496];
-	uint		im_brgc5;
-	uint		im_brgc6;
-	uint		im_brgc7;
-	uint		im_brgc8;
-
-	char		res5[608];
-
-	i2c8260_t	im_i2c;		/* I2C control/status */
-	cpm8260_t	im_cpm;		/* Communication processor */
-
-	/* Second set of baud rate generators.
-	*/
-	uint		im_brgc1;
-	uint		im_brgc2;
-	uint		im_brgc3;
-	uint		im_brgc4;
-
-	scc_t		im_scc[4];	/* Four SCCs */
-	smc_t		im_smc[2];	/* Couple of SMCs */
-	spi_t		im_spi;		/* A SPI */
-	cpmux_t		im_cpmux;	/* CPM clock route mux */
-	siramctl_t	im_siramctl1;	/* First SI RAM Control */
-	mcc_t		im_mcc1;	/* First MCC */
-	siramctl_t	im_siramctl2;	/* Second SI RAM Control */
-	mcc_t		im_mcc2;	/* Second MCC */
-
-	char		res6[1184];
-
-	ushort		im_si1txram[256];
-	char		res7[512];
-	ushort		im_si1rxram[256];
-	char		res8[512];
-	ushort		im_si2txram[256];
-	char		res9[512];
-	ushort		im_si2rxram[256];
-	char		res10[512];
-	char		res11[4096];
-} immap_t;
-
-extern immap_t	*immr;
-
-#endif /* __IMMAP_82XX__ */
-#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/immap_cpm2.h linux-2.4.26-pre6/include/asm-ppc/immap_cpm2.h
--- linux-2.4.25/include/asm-ppc/immap_cpm2.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/immap_cpm2.h	2004-03-25 00:19:57.000000000 +0000
@@ -0,0 +1,648 @@
+/*
+ * CPM2 Internal Memory Map
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * The Internal Memory Map for devices with CPM2 on them.  This
+ * is the superset of all CPM2 devices (8260, 8266, 8280, 8272,
+ * 8560). 
+ */
+#ifdef __KERNEL__
+#ifndef __IMMAP_CPM2__
+#define __IMMAP_CPM2__
+
+/* System configuration registers.
+*/
+typedef	struct sys_82xx_conf {
+	u32	sc_siumcr;
+	u32	sc_sypcr;
+	u8	res1[6];
+	u16	sc_swsr;
+	u8	res2[20];
+	u32	sc_bcr;
+	u8	sc_ppc_acr;
+	u8	res3[3];
+	u32	sc_ppc_alrh;
+	u32	sc_ppc_alrl;
+	u8	sc_lcl_acr;
+	u8	res4[3];
+	u32	sc_lcl_alrh;
+	u32	sc_lcl_alrl;
+	u32	sc_tescr1;
+	u32	sc_tescr2;
+	u32	sc_ltescr1;
+	u32	sc_ltescr2;
+	u32	sc_pdtea;
+	u8	sc_pdtem;
+	u8	res5[3];
+	u32	sc_ldtea;
+	u8	sc_ldtem;
+	u8	res6[163];
+} sysconf_82xx_cpm2_t;
+
+typedef	struct sys_85xx_conf {
+	u32	sc_cear;
+	u16	sc_ceer;
+	u16	sc_cemr;
+	u8	res1[70];
+	u32	sc_smaer;
+	u8	res2[4];
+	u32	sc_smevr;
+	u32	sc_smctr;
+	u32	sc_lmaer;
+	u8	res3[4];
+	u32	sc_lmevr;
+	u32	sc_lmctr;
+	u8	res4[144];
+} sysconf_85xx_cpm2_t;
+
+typedef union sys_conf {
+	sysconf_82xx_cpm2_t	siu_82xx;
+	sysconf_85xx_cpm2_t	siu_85xx;
+} sysconf_cpm2_t;
+
+
+
+/* Memory controller registers.
+*/
+typedef struct	mem_ctlr {
+	u32	memc_br0;
+	u32	memc_or0;
+	u32	memc_br1;
+	u32	memc_or1;
+	u32	memc_br2;
+	u32	memc_or2;
+	u32	memc_br3;
+	u32	memc_or3;
+	u32	memc_br4;
+	u32	memc_or4;
+	u32	memc_br5;
+	u32	memc_or5;
+	u32	memc_br6;
+	u32	memc_or6;
+	u32	memc_br7;
+	u32	memc_or7;
+	u32	memc_br8;
+	u32	memc_or8;
+	u32	memc_br9;
+	u32	memc_or9;
+	u32	memc_br10;
+	u32	memc_or10;
+	u32	memc_br11;
+	u32	memc_or11;
+	u8	res1[8];
+	u32	memc_mar;
+	u8	res2[4];
+	u32	memc_mamr;
+	u32	memc_mbmr;
+	u32	memc_mcmr;
+	u8	res3[8];
+	u16	memc_mptpr;
+	u8	res4[2];
+	u32	memc_mdr;
+	u8	res5[4];
+	u32	memc_psdmr;
+	u32	memc_lsdmr;
+	u8	memc_purt;
+	u8	res6[3];
+	u8	memc_psrt;
+	u8	res7[3];
+	u8	memc_lurt;
+	u8	res8[3];
+	u8	memc_lsrt;
+	u8	res9[3];
+	u32	memc_immr;
+	u32	memc_pcibr0;
+	u32	memc_pcibr1;
+	u8	res10[16];
+	u32	memc_pcimsk0;
+	u32	memc_pcimsk1;
+	u8	res11[52];
+} memctl_cpm2_t;
+
+/* System Integration Timers.
+*/
+typedef struct	sys_int_timers {
+	u8	res1[32];
+	u16	sit_tmcntsc;
+	u8	res2[2];
+	u32	sit_tmcnt;
+	u8	res3[4];
+	u32	sit_tmcntal;
+	u8	res4[16];
+	u16	sit_piscr;
+	u8	res5[2];
+	u32	sit_pitc;
+	u32	sit_pitr;
+	u8	res6[92];
+	u8	res7[390];
+} sit_cpm2_t;
+
+#define PISCR_PIRQ_MASK		((u16)0xff00)
+#define PISCR_PS		((u16)0x0080)
+#define PISCR_PIE		((u16)0x0004)
+#define PISCR_PTF		((u16)0x0002)
+#define PISCR_PTE		((u16)0x0001)
+
+/* PCI Controller.
+*/
+typedef struct pci_ctlr {
+	u32	pci_omisr;
+	u32	pci_omimr;
+	u8	res1[8];
+	u32	pci_ifqpr;
+	u32	pci_ofqpr;
+	u8	res2[8];
+	u32	pci_imr0;
+	u32	pci_imr1;
+	u32	pci_omr0;
+	u32	pci_omr1;
+	u32	pci_odr;
+	u8	res3[4];
+	u32	pci_idr;
+	u8	res4[20];
+	u32	pci_imisr;
+	u32	pci_imimr;
+	u8	res5[24];
+	u32	pci_ifhpr;
+	u8	res6[4];
+	u32	pci_iftpr;
+	u8	res7[4];
+	u32	pci_iphpr;
+	u8	res8[4];
+	u32	pci_iptpr;
+	u8	res9[4];
+	u32	pci_ofhpr;
+	u8	res10[4];
+	u32	pci_oftpr;
+	u8	res11[4];
+	u32	pci_ophpr;
+	u8	res12[4];
+	u32	pci_optpr;
+	u8	res13[8];
+	u32	pci_mucr;
+	u8	res14[8];
+	u32	pci_qbar;
+	u8	res15[12];
+	u32	pci_dmamr0;
+	u32	pci_dmasr0;
+	u32	pci_dmacdar0;
+	u8	res16[4];
+	u32	pci_dmasar0;
+	u8	res17[4];
+	u32	pci_dmadar0;
+	u8	res18[4];
+	u32	pci_dmabcr0;
+	u32	pci_dmandar0;
+	u8	res19[86];
+	u32	pci_dmamr1;
+	u32	pci_dmasr1;
+	u32	pci_dmacdar1;
+	u8	res20[4];
+	u32	pci_dmasar1;
+	u8	res21[4];
+	u32	pci_dmadar1;
+	u8	res22[4];
+	u32	pci_dmabcr1;
+	u32	pci_dmandar1;
+	u8	res23[88];
+	u32	pci_dmamr2;
+	u32	pci_dmasr2;
+	u32	pci_dmacdar2;
+	u8	res24[4];
+	u32	pci_dmasar2;
+	u8	res25[4];
+	u32	pci_dmadar2;
+	u8	res26[4];
+	u32	pci_dmabcr2;
+	u32	pci_dmandar2;
+	u8	res27[88];
+	u32	pci_dmamr3;
+	u32	pci_dmasr3;
+	u32	pci_dmacdar3;
+	u8	res28[4];
+	u32	pci_dmasar3;
+	u8	res29[4];
+	u32	pci_dmadar3;
+	u8	res30[4];
+	u32	pci_dmabcr3;
+	u32	pci_dmandar3;
+	u8	res31[344];
+	u32	pci_potar0;
+	u8	res32[4];
+	u32	pci_pobar0;
+	u8	res33[4];
+	u32	pci_pocmr0;
+	u8	res34[4];
+	u32	pci_potar1;
+	u8	res35[4];
+	u32	pci_pobar1;
+	u8	res36[4];
+	u32	pci_pocmr1;
+	u8	res37[4];
+	u32	pci_potar2;
+	u8	res38[4];
+	u32	pci_pobar2;
+	u8	res39[4];
+	u32	pci_pocmr2;
+	u8	res40[50];
+	u32	pci_ptcr;
+	u32	pci_gpcr;
+	u32	pci_gcr;
+	u32	pci_esr;
+	u32	pci_emr;
+	u32	pci_ecr;
+	u32	pci_eacr;
+	u8	res41[4];
+	u32	pci_edcr;
+	u8	res42[4];
+	u32	pci_eccr;
+	u8	res43[44];
+	u32	pci_pitar1;
+	u8	res44[4];
+	u32	pci_pibar1;
+	u8	res45[4];
+	u32	pci_picmr1;
+	u8	res46[4];
+	u32	pci_pitar0;
+	u8	res47[4];
+	u32	pci_pibar0;
+	u8	res48[4];
+	u32	pci_picmr0;
+	u8	res49[4];
+	u32	pci_cfg_addr;
+	u32	pci_cfg_data;
+	u32	pci_int_ack;
+	u8	res50[756];
+} pci_cpm2_t;
+
+/* Interrupt Controller.
+*/
+typedef struct interrupt_controller {
+	u16	ic_sicr;
+	u8	res1[2];
+	u32	ic_sivec;
+	u32	ic_sipnrh;
+	u32	ic_sipnrl;
+	u32	ic_siprr;
+	u32	ic_scprrh;
+	u32	ic_scprrl;
+	u32	ic_simrh;
+	u32	ic_simrl;
+	u32	ic_siexr;
+	u8	res2[88];
+} intctl_cpm2_t;
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+	u32	car_sccr;
+	u8	res1[4];
+	u32	car_scmr;
+	u8	res2[4];
+	u32	car_rsr;
+	u32	car_rmr;
+	u8	res[104];
+} car_cpm2_t;
+
+/* Input/Output Port control/status registers.
+ * Names consistent with processor manual, although they are different
+ * from the original 8xx names.......
+ */
+typedef struct io_port {
+	u32	iop_pdira;
+	u32	iop_ppara;
+	u32	iop_psora;
+	u32	iop_podra;
+	u32	iop_pdata;
+	u8	res1[12];
+	u32	iop_pdirb;
+	u32	iop_pparb;
+	u32	iop_psorb;
+	u32	iop_podrb;
+	u32	iop_pdatb;
+	u8	res2[12];
+	u32	iop_pdirc;
+	u32	iop_pparc;
+	u32	iop_psorc;
+	u32	iop_podrc;
+	u32	iop_pdatc;
+	u8	res3[12];
+	u32	iop_pdird;
+	u32	iop_ppard;
+	u32	iop_psord;
+	u32	iop_podrd;
+	u32	iop_pdatd;
+	u8	res4[12];
+} iop_cpm2_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+	u8	cpmt_tgcr1;
+	u8	res1[3];
+	u8	cpmt_tgcr2;
+	u8	res2[11];
+	u16	cpmt_tmr1;
+	u16	cpmt_tmr2;
+	u16	cpmt_trr1;
+	u16	cpmt_trr2;
+	u16	cpmt_tcr1;
+	u16	cpmt_tcr2;
+	u16	cpmt_tcn1;
+	u16	cpmt_tcn2;
+	u16	cpmt_tmr3;
+	u16	cpmt_tmr4;
+	u16	cpmt_trr3;
+	u16	cpmt_trr4;
+	u16	cpmt_tcr3;
+	u16	cpmt_tcr4;
+	u16	cpmt_tcn3;
+	u16	cpmt_tcn4;
+	u16	cpmt_ter1;
+	u16	cpmt_ter2;
+	u16	cpmt_ter3;
+	u16	cpmt_ter4;
+	u8	res3[584];
+} cpmtimer_cpm2_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+	u8	res0[24];
+	u8	sdma_sdsr;
+	u8	res1[3];
+	u8	sdma_sdmr;
+	u8	res2[3];
+	u8	sdma_idsr1;
+	u8	res3[3];
+	u8	sdma_idmr1;
+	u8	res4[3];
+	u8	sdma_idsr2;
+	u8	res5[3];
+	u8	sdma_idmr2;
+	u8	res6[3];
+	u8	sdma_idsr3;
+	u8	res7[3];
+	u8	sdma_idmr3;
+	u8	res8[3];
+	u8	sdma_idsr4;
+	u8	res9[3];
+	u8	sdma_idmr4;
+	u8	res10[707];
+} sdma_cpm2_t;
+
+/* Fast controllers
+*/
+typedef struct fcc {
+	u32	fcc_gfmr;
+	u32	fcc_fpsmr;
+	u16	fcc_ftodr;
+	u8	res1[2];
+	u16	fcc_fdsr;
+	u8	res2[2];
+	u16	fcc_fcce;
+	u8	res3[2];
+	u16	fcc_fccm;
+	u8	res4[2];
+	u8	fcc_fccs;
+	u8	res5[3];
+	u8	fcc_ftirr_phy[4];
+} fcc_t;
+
+/* Fast controllers continued
+ */
+typedef struct fcc_c {
+	u32	fcc_firper;
+	u32	fcc_firer;
+	u32	fcc_firsr_hi;
+	u32	fcc_firsr_lo;
+	u8	fcc_gfemr;
+	u8	res1[15];
+} fcc_c_t;
+
+/* TC Layer
+ */
+typedef struct tclayer {
+	u16	tc_tcmode;
+	u16	tc_cdsmr;
+	u16	tc_tcer;
+	u16	tc_rcc;
+	u16	tc_tcmr;
+	u16	tc_fcc;
+	u16	tc_ccc;
+	u16	tc_icc;
+	u16	tc_tcc;
+	u16	tc_ecc;
+	u8	res1[12];
+} tclayer_t;
+
+
+/* I2C
+*/
+typedef struct i2c {
+	u8	i2c_i2mod;
+	u8	res1[3];
+	u8	i2c_i2add;
+	u8	res2[3];
+	u8	i2c_i2brg;
+	u8	res3[3];
+	u8	i2c_i2com;
+	u8	res4[3];
+	u8	i2c_i2cer;
+	u8	res5[3];
+	u8	i2c_i2cmr;
+	u8	res6[331];
+} i2c_cpm2_t;
+
+typedef struct scc {		/* Serial communication channels */
+	u32	scc_gsmrl;
+	u32	scc_gsmrh;
+	u16	scc_psmr;
+	u8	res1[2];
+	u16	scc_todr;
+	u16	scc_dsr;
+	u16	scc_scce;
+	u8	res2[2];
+	u16	scc_sccm;
+	u8	res3;
+	u8	scc_sccs;
+	u8	res4[8];
+} scc_t;
+
+typedef struct smc {		/* Serial management channels */
+	u8	res1[2];
+	u16	smc_smcmr;
+	u8	res2[2];
+	u8	smc_smce;
+	u8	res3[3];
+	u8	smc_smcm;
+	u8	res4[5];
+} smc_t;
+
+/* Serial Peripheral Interface.
+*/
+typedef struct spi_ctrl {
+	u16	spi_spmode;
+	u8	res1[4];
+	u8	spi_spie;
+	u8	res2[3];
+	u8	spi_spim;
+	u8	res3[2];
+	u8	spi_spcom;
+	u8	res4[82];
+} spictl_cpm2_t;
+
+/* CPM Mux.
+*/
+typedef struct cpmux {
+	u8	cmx_si1cr;
+	u8	res1;
+	u8	cmx_si2cr;
+	u8	res2;
+	u32	cmx_fcr;
+	u32	cmx_scr;
+	u8	cmx_smr;
+	u8	res3;
+	u16	cmx_uar;
+	u8	res4[16];
+} cpmux_t;
+
+/* SIRAM control
+*/
+typedef struct siram {
+	u16	si_amr;
+	u16	si_bmr;
+	u16	si_cmr;
+	u16	si_dmr;
+	u8	si_gmr;
+	u8	res1;
+	u8	si_cmdr;
+	u8	res2;
+	u8	si_str;
+	u8	res3;
+	u16	si_rsr;
+} siramctl_t;
+
+typedef struct mcc {
+	u16	mcc_mcce;
+	u8	res1[2];
+	u16	mcc_mccm;
+	u8	res2[2];
+	u8	mcc_mccf;
+	u8	res3[7];
+} mcc_t;
+
+typedef struct comm_proc {
+	u32	cp_cpcr;
+	u32	cp_rccr;
+	u8	res1[14];
+	u16	cp_rter;
+	u8	res2[2];
+	u16	cp_rtmr;
+	u16	cp_rtscr;
+	u8	res3[2];
+	u32	cp_rtsr;
+	u8	res4[12];
+} cpm_cpm2_t;
+
+/* USB Controller.
+*/
+typedef struct usb_ctlr {
+	u8	usb_usmod;
+	u8	usb_usadr;
+	u8	usb_uscom;
+	u8	res1[1];
+	u16	usb_usep1;
+	u16	usb_usep2;
+	u16	usb_usep3;
+	u16	usb_usep4;
+	u8	res2[4];
+	u16	usb_usber;
+	u8	res3[2];
+	u16	usb_usbmr;
+	u8	usb_usbs;
+	u8	res4[7];
+} usb_cpm2_t;
+
+/* ...and the whole thing wrapped up....
+*/
+
+typedef struct immap {
+	/* Some references are into the unique and known dpram spaces,
+	 * others are from the generic base.
+	 */
+#define im_dprambase	im_dpram1
+	u8		im_dpram1[16*1024];
+	u8		res1[16*1024];
+	u8		im_dpram2[4*1024];
+	u8		res2[8*1024];
+	u8		im_dpram3[4*1024];
+	u8		res3[16*1024];
+
+	sysconf_cpm2_t	im_siu_conf;	/* SIU Configuration */
+	memctl_cpm2_t	im_memctl;	/* Memory Controller */
+	sit_cpm2_t	im_sit;		/* System Integration Timers */
+	pci_cpm2_t	im_pci;		/* PCI Controller */
+	intctl_cpm2_t	im_intctl;	/* Interrupt Controller */
+	car_cpm2_t	im_clkrst;	/* Clocks and reset */
+	iop_cpm2_t	im_ioport;	/* IO Port control/status */
+	cpmtimer_cpm2_t	im_cpmtimer;	/* CPM timers */
+	sdma_cpm2_t	im_sdma;	/* SDMA control/status */
+
+	fcc_t		im_fcc[3];	/* Three FCCs */
+	u8		res4z[32];
+	fcc_c_t		im_fcc_c[3];	/* Continued FCCs */
+
+	u8		res4[32];
+
+	tclayer_t	im_tclayer[8];	/* Eight TCLayers */
+	u16		tc_tcgsr;
+	u16		tc_tcger;
+	
+	/* First set of baud rate generators.
+	*/
+	u8		res[236];
+	u32		im_brgc5;
+	u32		im_brgc6;
+	u32		im_brgc7;
+	u32		im_brgc8;
+
+	u8		res5[608];
+
+	i2c_cpm2_t	im_i2c;		/* I2C control/status */
+	cpm_cpm2_t	im_cpm;		/* Communication processor */
+
+	/* Second set of baud rate generators.
+	*/
+	u32		im_brgc1;
+	u32		im_brgc2;
+	u32		im_brgc3;
+	u32		im_brgc4;
+
+	scc_t		im_scc[4];	/* Four SCCs */
+	smc_t		im_smc[2];	/* Couple of SMCs */
+	spictl_cpm2_t	im_spi;		/* A SPI */
+	cpmux_t		im_cpmux;	/* CPM clock route mux */
+	siramctl_t	im_siramctl1;	/* First SI RAM Control */
+	mcc_t		im_mcc1;	/* First MCC */
+	siramctl_t	im_siramctl2;	/* Second SI RAM Control */
+	mcc_t		im_mcc2;	/* Second MCC */
+	usb_cpm2_t	im_usb;		/* USB Controller */
+
+	u8		res6[1153];
+
+	u16		im_si1txram[256];
+	u8		res7[512];
+	u16		im_si1rxram[256];
+	u8		res8[512];
+	u16		im_si2txram[256];
+	u8		res9[512];
+	u16		im_si2rxram[256];
+	u8		res10[512];
+	u8		res11[4096];
+} cpm2_map_t;
+
+extern cpm2_map_t	*cpm2_immr;
+
+#endif /* __IMMAP_CPM2__ */
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/mpc8260.h linux-2.4.26-pre6/include/asm-ppc/mpc8260.h
--- linux-2.4.25/include/asm-ppc/mpc8260.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/mpc8260.h	2004-03-25 00:16:52.000000000 +0000
@@ -12,10 +12,18 @@
 
 #ifdef CONFIG_8260
 
+#ifdef CONFIG_RPX6
+#include <platforms/rpx8260.h>
+#endif
+
 #ifdef CONFIG_EST8260
 #include <platforms/est8260.h>
 #endif
 
+#ifdef CONFIG_PQ2ADS
+#include <platforms/pq2ads.h>
+#endif
+
 /* I don't yet have the ISA or PCI stuff done....no 8260 with
  * such thing.....
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/ocp.h linux-2.4.26-pre6/include/asm-ppc/ocp.h
--- linux-2.4.25/include/asm-ppc/ocp.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/ocp.h	2004-03-25 00:18:50.000000000 +0000
@@ -4,7 +4,7 @@
  *      (c) Benjamin Herrenschmidt (benh@kernel.crashing.org)
  *          Mipsys - France
  *
- "          Derived from work (c) Armin Kuster akuster@pacbell.net
+ *          Derived from work (c) Armin Kuster akuster@pacbell.net
  *
  * 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
@@ -36,6 +36,7 @@
 #ifndef __OCP_H__
 #define __OCP_H__
 
+#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/config.h>
 #include <linux/devfs_fs_kernel.h>
@@ -49,6 +50,10 @@
 #include <platforms/ibm_ocp.h>
 #endif
 
+#if defined(CONFIG_MPC_OCP)
+#include <asm/mpc_ocp.h>
+#endif
+
 #define OCP_MAX_IRQS	7
 #define MAX_EMACS	4
 #define OCP_IRQ_NA	-1	/* used when ocp device does not have an irq */
@@ -115,7 +120,7 @@ struct ocp_def {
 struct ocp_device {
 	struct list_head	link;
 	char			name[80];	/* device name */
-	const struct ocp_def	*def;		/* device definition */
+	struct ocp_def		*def;		/* device definition */
 	void			*drvdata;	/* driver data for this device */
 	struct ocp_driver	*driver;
 	u32			current_state;	/* Current operating state. In ACPI-speak,
@@ -180,12 +185,23 @@ ocp_force_power_on(struct ocp_device *od
 extern int ocp_register_driver(struct ocp_driver *drv);
 extern void ocp_unregister_driver(struct ocp_driver *drv);
 
-/* Initialize the OCP management layer */
-extern int ocp_init(void);
+/* Build list of devices */
+extern int ocp_early_init(void) __init;
+
+/* Initialize the driver portion of OCP management layer */
+extern int ocp_driver_init(void);
 
 /* Find a device by index */
 extern struct ocp_device *ocp_find_device(unsigned int vendor, unsigned int function, int index);
 
+/* Get a def by index */
+extern struct ocp_def *ocp_get_one_device(unsigned int vendor, unsigned int function, int index);
+
+/* Add a device by index */
+extern int ocp_add_one_device(struct ocp_def *def);
+
+/* Remove a device by index */
+extern int ocp_remove_one_device(unsigned int vendor, unsigned int function, int index);
 
 #endif				/* __OCP_H__ */
 #endif				/* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/ocp_ids.h linux-2.4.26-pre6/include/asm-ppc/ocp_ids.h
--- linux-2.4.25/include/asm-ppc/ocp_ids.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/ocp_ids.h	2004-03-25 00:20:43.000000000 +0000
@@ -52,26 +52,17 @@
 #define OCP_FUNC_INVALID	0x0000
 
 /* system 0x0001 - 0x001F */
-#define	OCP_FUNC_UIC		0x0001
 
 /* Timers 0x0020 - 0x002F */
-#define OCP_FUNC_GPT		0x0020 	/* General purpose timers */
-#define OCP_FUNC_RTC		0x0021
 
 /* Serial 0x0030 - 0x006F*/
 #define OCP_FUNC_16550		0x0031
-#define OCP_FUNC_SSP		0x0032 /* sync serial port */
-#define OCP_FUNC_SCP		0x0033 	/* serial controller port */
-#define OCP_FUNC_SCC		0x0034 	/* serial contoller */
-#define OCP_FUNC_SCI		0x0035 	/* Smart card */
-#define OCP_FUNC_IIC		0x0040
-#define OCP_FUNC_USB		0x0050
-#define OCP_FUNC_IR		0x0060
+#define OCP_FUNC_IIC		0x0032
+#define OCP_FUNC_USB		0x0033
 
 /* Memory devices 0x0090 - 0x009F */
-#define	OCP_FUNC_SDRAM		0x0091
-#define OCP_FUNC_DMA		0x0092
-#define OCP_FUNC_MAL		0x0093
+#define OCP_FUNC_MAL		0x0090
+#define OCP_FUNC_DMA		0x0091
 
 	/* Additional data */
 	struct ocp_func_mal_data {
@@ -80,12 +71,8 @@
 	};
 
 /* Display 0x00A0 - 0x00AF */
-#define OCP_FUNC_VIDEO		0x00A0
-#define OCP_FUNC_LED		0x00A1
-#define	OCP_FUNC_LCD		0x00A2
 
 /* Sound 0x00B0 - 0x00BF */
-#define OCP_FUNC_AUDIO		0x00B0
 
 /* Mass Storage 0x00C0 - 0xxCF */
 #define OCP_FUNC_IDE		0x00C0
@@ -93,9 +80,11 @@
 /* Misc 0x00D0 - 0x00DF*/
 #define OCP_FUNC_GPIO		0x00D0
 #define OCP_FUNC_ZMII		0x00D1
+#define OCP_FUNC_PERFMON	0x00D2	/* Performance Monitor */
 
 /* Network 0x0200 - 0x02FF */
 #define OCP_FUNC_EMAC		0x0200
+#define OCP_FUNC_GFAR		0x0201	/* TSEC & FEC */
 
 	/* Additional data
 	 *
@@ -115,12 +104,6 @@
 	};
 
 /* Bridge devices 0xE00 - 0xEFF */
-#define OCP_FUNC_HOST		0x0E00
-#define OCP_FUNC_DCR		0x0E01
-#define OCP_FUNC_OPB		0x0E02
-#define OCP_FUNC_PHY		0x0E03
-#define OCP_FUNC_EXT		0x0E04
-#define	OCP_FUNC_PCI		0x0E05
-#define	OCP_FUNC_PLB		0x0E06
+#define OCP_FUNC_OPB		0x0E00
 
 #define OCP_FUNC_UNKNOWN	0xFFFF
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/ppcboot.h linux-2.4.26-pre6/include/asm-ppc/ppcboot.h
--- linux-2.4.25/include/asm-ppc/ppcboot.h	2001-11-03 01:43:54.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/ppcboot.h	2004-03-25 00:21:54.000000000 +0000
@@ -52,7 +52,7 @@ typedef struct bd_info {
 	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
 	unsigned long	bi_sramstart;	/* start of SRAM memory */
 	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
-#if defined(CONFIG_8xx) || defined(CONFIG_8260)
+#if defined(CONFIG_8xx) || defined(CONFIG_CPM2)
 	unsigned long	bi_immr_base;	/* base of IMMR register */
 #endif
 	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
@@ -61,7 +61,7 @@ typedef struct bd_info {
 	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
 	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
 	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
-#if defined(CONFIG_8260)
+#if defined(CONFIG_CPM2)
 	unsigned long	bi_cpmfreq;	/* CPM_CLK Freq, in MHz */
 	unsigned long	bi_brgfreq;	/* BRG_CLK Freq, in MHz */
 	unsigned long	bi_sccfreq;	/* SCC_CLK Freq, in MHz */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-ppc/processor.h linux-2.4.26-pre6/include/asm-ppc/processor.h
--- linux-2.4.25/include/asm-ppc/processor.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-ppc/processor.h	2004-03-25 00:16:55.000000000 +0000
@@ -714,6 +714,7 @@
 #define _CHRP_IBM      0x05  /* IBM chrp, the longtrail and longtrail 2 */
 
 #define _GLOBAL(n)\
+        .stabs __stringify(n:F-1),N_FUN,0,0,n;\
 	.globl n;\
 n:
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/acpi.h linux-2.4.26-pre6/include/asm-x86_64/acpi.h
--- linux-2.4.25/include/asm-x86_64/acpi.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/acpi.h	2004-03-25 00:20:47.000000000 +0000
@@ -52,40 +52,35 @@
 #define ACPI_ENABLE_IRQS()  __sti()
 #define ACPI_FLUSH_CPU_CACHE()	wbinvd()
 
-/*
- * A brief explanation as GNU inline assembly is a bit hairy
- *  %0 is the output parameter in RAX ("=a")
- *  %1 and %2 are the input parameters in RCX ("c")
- *  and an immediate value ("i") respectively
- *  All actual register references are preceded with "%%" as in "%%edx"
- *  Immediate values in the assembly are preceded by "$" as in "$0x1"
- *  The final asm parameter are the operation altered non-output registers.
- */
+static inline int
+__acpi_acquire_global_lock (unsigned int *lock)
+{
+	unsigned int old, new, val;
+	do {
+		old = *lock;
+		new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
+		val = cmpxchg(lock, old, new);
+	} while (unlikely (val != old));
+	return (new < 3) ? -1 : 0;
+}
+
+static inline int
+__acpi_release_global_lock (unsigned int *lock)
+{
+	unsigned int old, new, val;
+	do {
+		old = *lock;
+		new = old & ~0x3;
+		val = cmpxchg(lock, old, new);
+	} while (unlikely (val != old));
+	return old & 0x1;
+}
+
 #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
-	do { \
-		unsigned long dummy; \
-		asm("1:     movl (%2),%%eax;" \
-			"movl   %%eax,%%edx;" \
-			"andq   %2,%%rdx;" \
-			"btsl   $0x1,%%edx;" \
-			"adcl   $0x0,%%edx;" \
-			"lock;  cmpxchgl %%edx,(%1);" \
-			"jnz    1b;" \
-			"cmpb   $0x3,%%dl;" \
-			"sbbl   %%eax,%%eax" \
-			:"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \
-	} while(0)
+	((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr))
+
 #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \
-	do { \
-		unsigned long dummy; \
-		asm("1:     movl (%2),%%eax;" \
-			"movl   %%eax,%%edx;" \
-			"andq   %2,%%rdx;" \
-			"lock;  cmpxchgl %%edx,(%1);" \
-			"jnz    1b;" \
-			"andl   $0x1,%%eax" \
-			:"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \
-	} while(0)
+	((Acq) = __acpi_release_global_lock((unsigned int *) GLptr))
 
 /*
  * Math helper asm macros
@@ -108,6 +103,10 @@
 extern int acpi_lapic;
 extern int acpi_ioapic;
 extern int acpi_noirq;
+extern int acpi_strict;
+extern int acpi_disabled;
+extern int acpi_ht;
+static inline void disable_acpi(void) { acpi_disabled = 1; acpi_ht = 0; }
 
 /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
 #define FIX_ACPI_PAGES 4
@@ -142,8 +141,6 @@ extern void acpi_reserve_bootmem(void);
 
 #define boot_cpu_physical_apicid boot_cpu_id
 
-extern void mp_config_ioapic_for_sci(int irq);
-
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/cpufeature.h linux-2.4.26-pre6/include/asm-x86_64/cpufeature.h
--- linux-2.4.25/include/asm-x86_64/cpufeature.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/cpufeature.h	2004-03-25 00:22:22.000000000 +0000
@@ -10,7 +10,7 @@
 /* Sample usage: CPU_FEATURE_P(cpu.x86_capability, FPU) */
 #define CPU_FEATURE_P(CAP, FEATURE) test_bit(CAP, X86_FEATURE_##FEATURE ##_BIT)
 
-#define NCAPINTS	4	/* Currently we have 4 32-bit words worth of info */
+#define NCAPINTS	5	/* Currently we have 5 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -40,8 +40,10 @@
 #define X86_FEATURE_XMM		(0*32+25) /* Streaming SIMD Extensions */
 #define X86_FEATURE_XMM2	(0*32+26) /* Streaming SIMD Extensions-2 */
 #define X86_FEATURE_SELFSNOOP	(0*32+27) /* CPU self snoop */
+#define X86_FEATURE_HT 		(0*32+28) /* Hyper-Threading */
 #define X86_FEATURE_ACC		(0*32+29) /* Automatic clock control */
 #define X86_FEATURE_IA64	(0*32+30) /* IA-64 processor */
+#define X86_FEATURE_PBE	(0*32+31) /* Pending Break Enable */
 
 /* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
 /* Don't duplicate feature flags which are redundant with Intel! */
@@ -62,6 +64,24 @@
 #define X86_FEATURE_K6_MTRR	(3*32+ 1) /* AMD K6 nonstandard MTRRs */
 #define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
 #define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
+/* cpu types for specific tunings: */
+#define X86_FEATURE_K8          (3*32+ 4) /* Opteron, Athlon64 */
+#define X86_FEATURE_K7          (3*32+ 5) /* Athlon */
+#define X86_FEATURE_P3          (3*32+ 6) /* P3 */
+#define X86_FEATURE_P4          (3*32+ 7) /* P4 */
+
+
+/* Intel-defined CPU features, CPUID level 0x00000001, ecx, word 4 */
+#define X86_FEATURE_PNI		(4*32+ 0) /* Streaming SIMD Extensions 3 */
+#define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor-Mwait Support */
+#define X86_FEATURE_DS_CPL	(4*32+ 4) /* CPL qualified debug store */
+#define X86_FEATURE_EST	(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2	(4*32+ 8) /* Thermal monitor 2 */
+#define X86_FEATURE_CNXT_ID	(4*32+ 10) /* L1 Context ID */
+
+#define boot_cpu_has(bit)  test_bit(bit, boot_cpu_data.x86_capability)
+#define cpu_has(c, bit)            test_bit(bit, (c)->x86_capability)
+
 
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
@@ -75,7 +95,7 @@
 #define cpu_has_fxsr 1
 #define cpu_has_xmm 1
 #define cpu_has_apic 		boot_cpu_has(X86_FEATURE_APIC)
-#define cpu_has_ht 0 
+#define cpu_has_ht 		boot_cpu_has(X86_FEATURE_HT) 
 #define cpu_has_mp             boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_k6_mtrr 0
 #define cpu_has_cyrix_arr 0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/mpspec.h linux-2.4.26-pre6/include/asm-x86_64/mpspec.h
--- linux-2.4.25/include/asm-x86_64/mpspec.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/mpspec.h	2004-03-25 00:19:36.000000000 +0000
@@ -196,7 +196,6 @@ extern void mp_register_lapic_address (u
 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_config_ioapic_for_sci(int irq);
 extern void mp_parse_prt (void);
 #endif /*CONFIG_X86_IO_APIC*/
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/pci-direct.h linux-2.4.26-pre6/include/asm-x86_64/pci-direct.h
--- linux-2.4.25/include/asm-x86_64/pci-direct.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/pci-direct.h	2004-03-25 00:17:25.000000000 +0000
@@ -28,7 +28,7 @@ static inline u8 read_pci_config_byte(u8
 	return v;
 }
 
-static inline u8 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
+static inline u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
 {
 	u16 v; 
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/pci.h linux-2.4.26-pre6/include/asm-x86_64/pci.h
--- linux-2.4.25/include/asm-x86_64/pci.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/pci.h	2004-03-25 00:22:21.000000000 +0000
@@ -65,6 +65,18 @@ extern void *pci_alloc_consistent(struct
 extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
 				void *vaddr, dma_addr_t dma_handle);
 
+#ifdef CONFIG_SWIOTLB
+extern int swiotlb; 
+extern dma_addr_t swiotlb_map_single (struct pci_dev *hwdev, void *ptr, size_t size, 
+                                     int dir);
+extern void swiotlb_unmap_single (struct pci_dev *hwdev, dma_addr_t dev_addr,
+                                 size_t size, int dir);
+extern void swiotlb_sync_single (struct pci_dev *hwdev, dma_addr_t dev_addr, 
+                                size_t size, int dir);
+extern void swiotlb_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, 
+                            int dir);
+#endif
+
 #ifdef CONFIG_GART_IOMMU
 
 /* Map a single buffer of the indicated size for DMA in streaming mode.
@@ -105,6 +117,10 @@ static inline void pci_dma_sync_single(s
 				       dma_addr_t dma_handle,
 				       size_t size, int direction)
 {
+#ifdef CONFIG_SWIOTLB
+       if (swiotlb)
+               return swiotlb_sync_single(hwdev,dma_handle,size,direction);
+#endif
 	BUG_ON(direction == PCI_DMA_NONE); 
 } 
 
@@ -113,6 +129,10 @@ static inline void pci_dma_sync_sg(struc
 				   int nelems, int direction)
 { 
 	BUG_ON(direction == PCI_DMA_NONE); 
+#ifdef CONFIG_SWIOTLB
+       if (swiotlb)
+               return swiotlb_sync_sg(hwdev,sg,nelems,direction);
+#endif
 } 
 
 /* The PCI address space does equal the physical memory
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/pgtable.h linux-2.4.26-pre6/include/asm-x86_64/pgtable.h
--- linux-2.4.25/include/asm-x86_64/pgtable.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/pgtable.h	2004-03-25 00:19:35.000000000 +0000
@@ -79,7 +79,7 @@ extern void paging_init(void);
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern unsigned long empty_zero_page[1024];
+extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
 #endif /* !__ASSEMBLY__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/processor.h linux-2.4.26-pre6/include/asm-x86_64/processor.h
--- linux-2.4.25/include/asm-x86_64/processor.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/processor.h	2004-03-25 00:22:21.000000000 +0000
@@ -400,13 +400,40 @@ extern inline void sync_core(void)
 } 
 
 #define ARCH_HAS_PREFETCH
-#define ARCH_HAS_PREFETCHW
 #define ARCH_HAS_SPINLOCK_PREFETCH
 
-#define prefetch(x) __builtin_prefetch((x),0)
+#ifdef CONFIG_MK8
+#define ARCH_HAS_PREFETCHW
 #define prefetchw(x) __builtin_prefetch((x),1)
 #define spin_lock_prefetch(x)  prefetchw(x)
+#else
+#define spin_lock_prefetch(x)  prefetch(x)
+#endif
+
+#define prefetch(x) __builtin_prefetch((x),0)
+
 #define cpu_relax()   rep_nop()
 
 
+static __inline__ void __monitor(const void *eax, unsigned long ecx,
+               unsigned long edx)
+{
+       /* "monitor %eax,%ecx,%edx;" */
+       asm volatile(
+               ".byte 0x0f,0x01,0xc8;"
+               : :"a" (eax), "c" (ecx), "d"(edx));
+}
+
+static __inline__ void __mwait(unsigned long eax, unsigned long ecx)
+{
+       /* "mwait %eax,%ecx;" */
+       asm volatile(
+               ".byte 0x0f,0x01,0xc9;"
+               : :"a" (eax), "c" (ecx));
+}
+
+#define ARCH_HAS_SMP_BALANCE 1
+
 #endif /* __ASM_X86_64_PROCESSOR_H */
+
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/proto.h linux-2.4.26-pre6/include/asm-x86_64/proto.h
--- linux-2.4.25/include/asm-x86_64/proto.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/proto.h	2004-03-25 00:17:14.000000000 +0000
@@ -25,6 +25,8 @@ extern void syscall_init(void);
 
 extern void do_softirq_thunk(void);
 
+extern void swiotlb_init(void);
+
 extern int setup_early_printk(char *); 
 extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
 
@@ -36,7 +38,10 @@ extern unsigned long numa_free_all_bootm
 extern void reserve_bootmem_generic(unsigned long phys, unsigned len);
 extern void free_bootmem_generic(unsigned long phys, unsigned len);
 
+extern void check_efer(void);
+
 extern unsigned long start_pfn, end_pfn, end_pfn_map; 
+extern int iommu_aperture;
 
 extern void show_stack(unsigned long * rsp);
 extern void show_trace(unsigned long *stack);
@@ -44,7 +49,6 @@ extern void __show_regs(struct pt_regs *
 extern void show_regs(struct pt_regs * regs);
 
 extern int apic_disabled;
-extern int acpi_disabled;
 
 #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
 #define round_down(x,y) ((x) & ~((y)-1))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/scatterlist.h linux-2.4.26-pre6/include/asm-x86_64/scatterlist.h
--- linux-2.4.25/include/asm-x86_64/scatterlist.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/scatterlist.h	2004-03-25 00:17:20.000000000 +0000
@@ -9,6 +9,7 @@ struct scatterlist {
 
     unsigned int length;
     dma_addr_t dma_address;
+    unsigned int dma_length;
 };
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/smp.h linux-2.4.26-pre6/include/asm-x86_64/smp.h
--- linux-2.4.25/include/asm-x86_64/smp.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/smp.h	2004-03-25 00:22:19.000000000 +0000
@@ -36,6 +36,9 @@ extern unsigned long phys_cpu_present_ma
 extern unsigned long cpu_online_map;
 extern volatile unsigned long smp_invalidate_needed;
 extern int pic_mode;
+extern int smp_num_siblings;
+extern int cpu_sibling_map[];
+
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
 extern void smp_send_reschedule(int cpu);
@@ -89,8 +92,8 @@ extern __inline int hard_smp_processor_i
 	return GET_APIC_ID(*(unsigned *)(APIC_BASE+APIC_ID));
 }
 
-/* Assume apicid == cpuid */
-#define safe_smp_processor_id() (cpuid_ebx(1) >> 24) 
+extern int apic_disabled;
+#define safe_smp_processor_id() (apic_disabled ? 0 : x86_apicid_to_cpu[hard_smp_processor_id()])
 
 #endif /* !ASSEMBLY */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-x86_64/uaccess.h linux-2.4.26-pre6/include/asm-x86_64/uaccess.h
--- linux-2.4.25/include/asm-x86_64/uaccess.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/asm-x86_64/uaccess.h	2004-03-25 00:20:00.000000000 +0000
@@ -236,6 +236,7 @@ extern unsigned long copy_user_generic(v
 
 extern unsigned long copy_to_user(void *to, const void *from, unsigned len); 
 extern unsigned long copy_from_user(void *to, const void *from, unsigned len); 
+extern unsigned long copy_in_user(void *to, const void *from, unsigned len); 
 
 static inline int __copy_from_user(void *dst, const void *src, unsigned size) 
 { 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/hiddev.h linux-2.4.26-pre6/include/linux/hiddev.h
--- linux-2.4.25/include/linux/hiddev.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/hiddev.h	2004-03-25 00:18:26.000000000 +0000
@@ -39,33 +39,33 @@ struct hiddev_event {
 };
 
 struct hiddev_devinfo {
-	unsigned int bustype;
-	unsigned int busnum;
-	unsigned int devnum;
-	unsigned int ifnum;
-	short vendor;
-	short product;
-	short version;
-	unsigned num_applications;
+	__u32 bustype;
+	__u32 busnum;
+	__u32 devnum;
+	__u32 ifnum;
+	__s16 vendor;
+	__s16 product;
+	__s16 version;
+	__u32 num_applications;
 };
 
 struct hiddev_collection_info {
-	unsigned index;
-	unsigned type;
-	unsigned usage;
-	unsigned level;
+	__u32 index;
+	__u32 type;
+	__u32 usage;
+	__u32 level;
 };
 
 #define HID_STRING_SIZE 256
 struct hiddev_string_descriptor {
-	int index;
+	__s32 index;
 	char value[HID_STRING_SIZE];
 };
 
 struct hiddev_report_info {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned num_fields;
+	__u32 report_type;
+	__u32 report_id;
+	__u32 num_fields;
 };
 
 /* To do a GUSAGE/SUSAGE, fill in at least usage_code,  report_type and 
@@ -88,20 +88,20 @@ struct hiddev_report_info {
 #define HID_REPORT_TYPE_MAX     3
 
 struct hiddev_field_info {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned field_index;
-	unsigned maxusage;
-	unsigned flags;
-	unsigned physical;		/* physical usage for this field */
-	unsigned logical;		/* logical usage for this field */
-	unsigned application;		/* application usage for this field */
+	__u32 report_type;
+	__u32 report_id;
+	__u32 field_index;
+	__u32 maxusage;
+	__u32 flags;
+	__u32 physical;		/* physical usage for this field */
+	__u32 logical;		/* logical usage for this field */
+	__u32 application;		/* application usage for this field */
 	__s32 logical_minimum;
 	__s32 logical_maximum;
 	__s32 physical_minimum;
 	__s32 physical_maximum;
-	unsigned unit_exponent;
-	unsigned unit;
+	__u32 unit_exponent;
+	__u32 unit;
 };
 
 /* Fill in report_type, report_id and field_index to get the information on a
@@ -118,14 +118,22 @@ struct hiddev_field_info {
 #define HID_FIELD_BUFFERED_BYTE		0x100
 
 struct hiddev_usage_ref {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned field_index;
-	unsigned usage_index;
-	unsigned usage_code;
+	__u32 report_type;
+	__u32 report_id;
+	__u32 field_index;
+	__u32 usage_index;
+	__u32 usage_code;
 	__s32 value;
 };
 
+/* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
+ * It really manifests itself as setting the value of consecutive usages */
+struct hiddev_usage_ref_multi {
+	struct hiddev_usage_ref uref;
+	__u32 num_values;
+	__s32 values[HID_MAX_USAGES];
+};
+
 /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
  * is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has
  * been sent by the device 
@@ -160,6 +168,11 @@ struct hiddev_usage_ref {
 #define HIDIOCGCOLLECTIONINDEX	_IOW('H', 0x10, struct hiddev_usage_ref)
 #define HIDIOCGCOLLECTIONINFO	_IOWR('H', 0x11, struct hiddev_collection_info)
 
+/* For writing/reading to multiple/consecutive usages */
+#define HIDIOCGUSAGES		_IOWR('H', 0x12, struct hiddev_usage_ref_multi)
+#define HIDIOCSUSAGES		_IOW('H', 0x13, struct hiddev_usage_ref_multi)
+
+
 /* 
  * Flags to be used in HIDIOCSFLAG
  */
@@ -204,6 +217,7 @@ int hiddev_connect(struct hid_device *);
 void hiddev_disconnect(struct hid_device *);
 void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
 		      struct hid_usage *usage, __s32 value);
+void hiddev_report_event(struct hid_device *hid, struct hid_report *report);
 int __init hiddev_init(void);
 void __exit hiddev_exit(void);
 #else
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/ide.h linux-2.4.26-pre6/include/linux/ide.h
--- linux-2.4.25/include/linux/ide.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/ide.h	2004-03-25 00:18:06.000000000 +0000
@@ -1102,7 +1102,6 @@ typedef struct {
 #ifdef CONFIG_PROC_FS
 extern void proc_ide_create(void);
 extern void proc_ide_destroy(void);
-extern void recreate_proc_ide_device(ide_hwif_t *, ide_drive_t *);
 extern void destroy_proc_ide_device(ide_hwif_t *, ide_drive_t *);
 extern void destroy_proc_ide_drives(ide_hwif_t *);
 extern void create_proc_ide_interfaces(void);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/if_bonding.h linux-2.4.26-pre6/include/linux/if_bonding.h
--- linux-2.4.25/include/linux/if_bonding.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/if_bonding.h	2004-03-25 00:21:29.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
  *
- * 
+ *
  * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
  * NCM: Network and Communications Management, Inc.
  *
@@ -10,11 +10,11 @@
  *
  *	This software may be used and distributed according to the terms
  *	of the GNU Public License, incorporated herein by reference.
- * 
+ *
  * 2003/03/18 - Amir Noam <amir.noam at intel dot com>
  *	- Added support for getting slave's speed and duplex via ethtool.
  *	  Needed for 802.3ad and other future modes.
- * 
+ *
  * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
  *		Shmulik Hen <shmulik.hen at intel dot com>
  *	- Enable support of modes that need to use the unique mac address of
@@ -32,6 +32,9 @@
  * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
  *	- Added ABI version control to restore compatibility between
  *	  new/old ifenslave and new/old bonding.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef _LINUX_IF_BONDING_H
@@ -42,7 +45,7 @@
 #include <linux/if_ether.h>
 
 /* userland - kernel ABI version (2003/05/08) */
-#define BOND_ABI_VERSION 1
+#define BOND_ABI_VERSION 2
 
 /*
  * We can remove these ioctl definitions in 2.5.  People should use the
@@ -77,10 +80,6 @@
 
 #define BOND_DEFAULT_MAX_BONDS  1   /* Default maximum number of devices to support */
 
-#define BOND_MULTICAST_DISABLED 0
-#define BOND_MULTICAST_ACTIVE   1
-#define BOND_MULTICAST_ALL      2
-
 typedef struct ifbond {
 	__s32 bond_mode;
 	__s32 num_slaves;
@@ -91,8 +90,8 @@ typedef struct ifslave
 {
 	__s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */
 	char slave_name[IFNAMSIZ];
-	char link;
-	char state;
+	__s8 link;
+	__s8 state;
 	__u32  link_failure_count;
 } ifslave;
 
@@ -115,3 +114,4 @@ struct ad_info {
  *  tab-width: 8
  * End:
  */
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/if_vlan.h linux-2.4.26-pre6/include/linux/if_vlan.h
--- linux-2.4.25/include/linux/if_vlan.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/if_vlan.h	2004-03-25 00:18:06.000000000 +0000
@@ -200,6 +200,148 @@ static inline int vlan_hwaccel_receive_s
 {
 	return __vlan_hwaccel_rx(skb, grp, vlan_tag, 1);
 }
+
+/**
+ * __vlan_put_tag - regular VLAN tag inserting
+ * @skb: skbuff to tag
+ * @tag: VLAN tag to insert
+ *
+ * Inserts the VLAN tag into @skb as part of the payload
+ * Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
+ * 
+ * Following the skb_unshare() example, in case of error, the calling function
+ * doesn't have to worry about freeing the original skb.
+ */
+static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, unsigned short tag)
+{
+	struct vlan_ethhdr *veth;
+
+	if (skb_headroom(skb) < VLAN_HLEN) {
+		struct sk_buff *sk_tmp = skb;
+		skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
+		kfree_skb(sk_tmp);
+		if (!skb) {
+			printk(KERN_ERR "vlan: failed to realloc headroom\n");
+			return NULL;
+		}
+	} else {
+		skb = skb_unshare(skb, GFP_ATOMIC);
+		if (!skb) {
+			printk(KERN_ERR "vlan: failed to unshare skbuff\n");
+			return NULL;
+		}
+	}
+
+	veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
+
+	/* Move the mac addresses to the beginning of the new header. */
+	memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
+
+	/* first, the ethernet type */
+	veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
+
+	/* now, the tag */
+	veth->h_vlan_TCI = htons(tag);
+
+	return skb;
+}
+
+/**
+ * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
+ * @skb: skbuff to tag
+ * @tag: VLAN tag to insert
+ *
+ * Puts the VLAN tag in @skb->cb[] and lets the device do the rest
+ */
+static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, unsigned short tag)
+{
+	struct vlan_skb_tx_cookie *cookie;
+
+	cookie = VLAN_TX_SKB_CB(skb);
+	cookie->magic = VLAN_TX_COOKIE_MAGIC;
+	cookie->vlan_tag = tag;
+
+	return skb;
+}
+
+#define HAVE_VLAN_PUT_TAG
+
+/**
+ * vlan_put_tag - inserts VLAN tag according to device features
+ * @skb: skbuff to tag
+ * @tag: VLAN tag to insert
+ *
+ * Assumes skb->dev is the target that will xmit this frame.
+ * Returns a VLAN tagged skb.
+ */
+static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, unsigned short tag)
+{
+	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
+		return __vlan_hwaccel_put_tag(skb, tag);
+	} else {
+		return __vlan_put_tag(skb, tag);
+	}
+}
+
+/**
+ * __vlan_get_tag - get the VLAN ID that is part of the payload
+ * @skb: skbuff to query
+ * @tag: buffer to store vlaue
+ * 
+ * Returns error if the skb is not of VLAN type
+ */
+static inline int __vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
+{
+	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
+
+	if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) {
+		return -EINVAL;
+	}
+
+	*tag = ntohs(veth->h_vlan_TCI);
+
+	return 0;
+}
+
+/**
+ * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
+ * @skb: skbuff to query
+ * @tag: buffer to store vlaue
+ * 
+ * Returns error if @skb->cb[] is not set correctly
+ */
+static inline int __vlan_hwaccel_get_tag(struct sk_buff *skb, unsigned short *tag)
+{
+	struct vlan_skb_tx_cookie *cookie;
+
+	cookie = VLAN_TX_SKB_CB(skb);
+	if (cookie->magic == VLAN_TX_COOKIE_MAGIC) {
+		*tag = cookie->vlan_tag;
+		return 0;
+	} else {
+		*tag = 0;
+		return -EINVAL;
+	}
+}
+
+#define HAVE_VLAN_GET_TAG
+
+/**
+ * vlan_get_tag - get the VLAN ID from the skb
+ * @skb: skbuff to query
+ * @tag: buffer to store vlaue
+ * 
+ * Returns error if the skb is not VLAN tagged
+ */
+static inline int vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
+{
+	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
+		return __vlan_hwaccel_get_tag(skb, tag);
+	} else {
+		return __vlan_get_tag(skb, tag);
+	}
+}
+
 #endif /* __KERNEL__ */
 
 /* VLAN IOCTLs are found in sockios.h */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/inetdevice.h linux-2.4.26-pre6/include/linux/inetdevice.h
--- linux-2.4.25/include/linux/inetdevice.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/inetdevice.h	2004-03-25 00:20:47.000000000 +0000
@@ -18,6 +18,8 @@ struct ipv4_devconf
 	int	mc_forwarding;
 	int	tag;
 	int     arp_filter;
+	int	arp_announce;
+	int	arp_ignore;
 	int	medium_id;
 	int	force_igmp_version;
 	void	*sysctl;
@@ -69,6 +71,8 @@ struct in_device
 	  (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
 
 #define IN_DEV_ARPFILTER(in_dev)	(ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
+#define IN_DEV_ARP_ANNOUNCE(in_dev)	(max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
+#define IN_DEV_ARP_IGNORE(in_dev)	(max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
 
 struct in_ifaddr
 {
@@ -95,8 +99,9 @@ extern void		devinet_init(void);
 extern struct in_device *inetdev_init(struct net_device *dev);
 extern struct in_device	*inetdev_by_index(int);
 extern u32		inet_select_addr(const struct net_device *dev, u32 dst, int scope);
+extern u32		inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope);
 extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
-extern void		inet_forward_change(void);
+extern void		inet_forward_change(int);
 
 static __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/jhash.h linux-2.4.26-pre6/include/linux/jhash.h
--- linux-2.4.25/include/linux/jhash.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/jhash.h	2004-03-25 00:19:36.000000000 +0000
@@ -41,10 +41,10 @@
  * of bytes.  No alignment or length assumptions are made about
  * the input key.
  */
-static inline u32 jhash(void *key, u32 length, u32 initval)
+static inline u32 jhash(const void *key, u32 length, u32 initval)
 {
 	u32 a, b, c, len;
-	u8 *k = key;
+	const u8 *k = key;
 
 	len = length;
 	a = b = JHASH_GOLDEN_RATIO;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/lockd/debug.h linux-2.4.26-pre6/include/linux/lockd/debug.h
--- linux-2.4.25/include/linux/lockd/debug.h	2001-11-22 19:47:20.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/lockd/debug.h	2004-03-25 00:21:27.000000000 +0000
@@ -49,4 +49,13 @@ char *		  nlm_procname(u32);
 #define NLMDBG_ALL		0x7fff
 
 
+/*
+ * Support for printing NLM cookies in dprintk()
+ */
+#ifdef RPC_DEBUG
+struct nlm_cookie;
+/* Call this function with the BKL held (it uses a static buffer) */
+extern const char *nlmdbg_cookie2a(const struct nlm_cookie *);
+#endif
+
 #endif /* LINUX_LOCKD_DEBUG_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/lockd/lockd.h linux-2.4.26-pre6/include/linux/lockd/lockd.h
--- linux-2.4.25/include/linux/lockd/lockd.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/lockd/lockd.h	2004-03-25 00:17:59.000000000 +0000
@@ -164,7 +164,7 @@ u32		  nlmsvc_cancel_blocked(struct nlm_
 unsigned long	  nlmsvc_retry_blocked(void);
 int		  nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
 					int action);
-void	  nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status);
+void	  nlmsvc_grant_reply(struct svc_rqst *, struct nlm_cookie *, u32);
 
 /*
  * File handling for the server personality
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/lockd/xdr.h linux-2.4.26-pre6/include/linux/lockd/xdr.h
--- linux-2.4.25/include/linux/lockd/xdr.h	2001-11-22 19:47:20.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/lockd/xdr.h	2004-03-25 00:16:53.000000000 +0000
@@ -33,14 +33,15 @@ struct nlm_lock {
 };
 
 /*
- *	NLM cookies. Technically they can be 1K, Nobody uses over 8 bytes
- *	however.
+ *	NLM cookies. Technically they can be 1K, Few people use over 8 bytes,
+ *	FreeBSD uses 16, Apple Mac OS-X 10.3 uses 20.
  */
  
 struct nlm_cookie
 {
-	unsigned char data[8];
 	unsigned int len;
+#define NLM_MAXCOOKIELEN    	32
+	unsigned char data[NLM_MAXCOOKIELEN];
 };
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/netfilter_ipv4/ip_nat.h linux-2.4.26-pre6/include/linux/netfilter_ipv4/ip_nat.h
--- linux-2.4.25/include/linux/netfilter_ipv4/ip_nat.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/netfilter_ipv4/ip_nat.h	2004-03-25 00:22:22.000000000 +0000
@@ -105,9 +105,6 @@ struct ip_nat_info
 	/* Manipulations to be done on this conntrack. */
 	struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
 
-	/* The mapping type which created us (NULL for null mapping). */
-	const struct ip_nat_mapping_type *mtype;
-
 	struct ip_nat_hash bysource, byipsproto;
 
 	/* Helper (NULL if none). */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/netfilter_ipv4/listhelp.h linux-2.4.26-pre6/include/linux/netfilter_ipv4/listhelp.h
--- linux-2.4.25/include/linux/netfilter_ipv4/listhelp.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/netfilter_ipv4/listhelp.h	2004-03-25 00:17:35.000000000 +0000
@@ -28,7 +28,7 @@
 							\
 	ASSERT_WRITE_LOCK(head);			\
 	list_for_each(__i, (head))			\
-		if (cmpfn((const type)__i , ## args)) {	\
+		if (cmpfn((type)__i , ## args)) {	\
 			__j = __i;			\
 			break;				\
 		}					\
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/nfs_fs.h linux-2.4.26-pre6/include/linux/nfs_fs.h
--- linux-2.4.25/include/linux/nfs_fs.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/nfs_fs.h	2004-03-25 00:19:01.000000000 +0000
@@ -209,13 +209,13 @@ extern int  nfs_updatepage(struct file *
  * Try to write back everything synchronously (but check the
  * return value!)
  */
-extern int  nfs_sync_file(struct inode *, struct file *, unsigned long, unsigned int, int);
-extern int  nfs_flush_file(struct inode *, struct file *, unsigned long, unsigned int, int);
+extern int  nfs_sync_file(struct inode *, unsigned long, unsigned int, int);
+extern int  nfs_flush_file(struct inode *, unsigned long, unsigned int, int);
 extern int  nfs_flush_list(struct list_head *, int, int);
 extern int  nfs_scan_lru_dirty(struct nfs_server *, struct list_head *);
 extern int  nfs_scan_lru_dirty_timeout(struct nfs_server *, struct list_head *);
 #ifdef CONFIG_NFS_V3
-extern int  nfs_commit_file(struct inode *, struct file *, unsigned long, unsigned int, int);
+extern int  nfs_commit_file(struct inode *, int);
 extern int  nfs_commit_list(struct list_head *, int);
 extern int  nfs_scan_lru_commit(struct nfs_server *, struct list_head *);
 extern int  nfs_scan_lru_commit_timeout(struct nfs_server *, struct list_head *);
@@ -236,7 +236,7 @@ nfs_have_writebacks(struct inode *inode)
 static inline int
 nfs_wb_all(struct inode *inode)
 {
-	int error = nfs_sync_file(inode, 0, 0, 0, FLUSH_WAIT);
+	int error = nfs_sync_file(inode, 0, 0, FLUSH_WAIT);
 	return (error < 0) ? error : 0;
 }
 
@@ -246,17 +246,7 @@ nfs_wb_all(struct inode *inode)
 static inline int
 nfs_wb_page(struct inode *inode, struct page* page)
 {
-	int error = nfs_sync_file(inode, 0, page_index(page), 1, FLUSH_WAIT | FLUSH_STABLE);
-	return (error < 0) ? error : 0;
-}
-
-/*
- * Write back all pending writes for one user.. 
- */
-static inline int
-nfs_wb_file(struct inode *inode, struct file *file)
-{
-	int error = nfs_sync_file(inode, file, 0, 0, FLUSH_WAIT);
+	int error = nfs_sync_file(inode, page_index(page), 1, FLUSH_WAIT | FLUSH_STABLE);
 	return (error < 0) ? error : 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/nfs_page.h linux-2.4.26-pre6/include/linux/nfs_page.h
--- linux-2.4.25/include/linux/nfs_page.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/nfs_page.h	2004-03-25 00:17:29.000000000 +0000
@@ -53,7 +53,7 @@ extern	void nfs_list_add_request(struct 
 extern	int nfs_scan_lru(struct list_head *, struct list_head *, int);
 extern	int nfs_scan_lru_timeout(struct list_head *, struct list_head *, int);
 extern	int nfs_scan_list(struct list_head *, struct list_head *,
-			  struct file *, unsigned long, unsigned int);
+				unsigned long, unsigned int);
 extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/pci.h linux-2.4.26-pre6/include/linux/pci.h
--- linux-2.4.25/include/linux/pci.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/pci.h	2004-03-25 00:19:43.000000000 +0000
@@ -34,6 +34,7 @@
 #define  PCI_COMMAND_WAIT 	0x80	/* Enable address/data stepping */
 #define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
 #define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
 
 #define PCI_STATUS		0x06	/* 16 bits */
 #define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/pci_ids.h linux-2.4.26-pre6/include/linux/pci_ids.h
--- linux-2.4.25/include/linux/pci_ids.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/pci_ids.h	2004-03-25 00:19:21.000000000 +0000
@@ -287,6 +287,8 @@
 #define PCI_DEVICE_ID_ATI_RADEON_Ig	0x4967
 /* Radeon RV280 (9200) */
 #define PCI_DEVICE_ID_ATI_RADEON_Y_	0x5960
+#define PCI_DEVICE_ID_ATI_RADEON_Ya	0x5961
+#define PCI_DEVICE_ID_ATI_RADEON_Yd	0x5964
 /* Radeon R300 (9700) */
 #define PCI_DEVICE_ID_ATI_RADEON_ND	0x4e44
 #define PCI_DEVICE_ID_ATI_RADEON_NE	0x4e45
@@ -425,6 +427,7 @@
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
+#define PCI_DEVICE_ID_AMD_SERENADE	0x36c0
 #define PCI_DEVICE_ID_AMD_FE_GATE_7006	0x7006
 #define PCI_DEVICE_ID_AMD_FE_GATE_7007	0x7007
 #define PCI_DEVICE_ID_AMD_FE_GATE_700C	0x700C
@@ -523,6 +526,7 @@
 #define PCI_DEVICE_ID_SI_6202		0x0002
 #define PCI_DEVICE_ID_SI_503		0x0008
 #define PCI_DEVICE_ID_SI_ACPI		0x0009
+#define PCI_DEVICE_ID_SI_180		0x0180
 #define PCI_DEVICE_ID_SI_5597_VGA	0x0200
 #define PCI_DEVICE_ID_SI_6205		0x0205
 #define PCI_DEVICE_ID_SI_501		0x0406
@@ -657,6 +661,8 @@
 #define PCI_DEVICE_ID_TI_4410		0xac41
 #define PCI_DEVICE_ID_TI_4451		0xac42
 #define PCI_DEVICE_ID_TI_1420		0xac51
+#define PCI_DEVICE_ID_TI_1520		0xac55
+#define PCI_DEVICE_ID_TI_1510		0xac56
 
 #define PCI_VENDOR_ID_SONY		0x104d
 #define PCI_DEVICE_ID_SONY_CXD3222	0x8039
@@ -750,6 +756,7 @@
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P	0x0027
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP15	0x002d
 #define PCI_DEVICE_ID_APPLE_UNI_N_FW2	0x0030
+#define PCI_DEVICE_ID_APPLE_TIGON3	0x1645
 
 #define PCI_VENDOR_ID_YAMAHA		0x1073
 #define PCI_DEVICE_ID_YAMAHA_724	0x0004
@@ -969,9 +976,15 @@
 #define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
 #define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE	0x0085
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
 #define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3		0x00d1
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE	0x00d5
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S		0x00e1
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA	0x00e3
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE	0x00e5
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2	0x00ee
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
 #define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
@@ -1677,6 +1690,12 @@
 #define PCI_DEVICE_ID_TIGON3_5901_2	0x170e
 #define PCI_DEVICE_ID_BCM4401		0x4401
 
+#define PCI_VENDOR_ID_ENE		0x1524
+#define PCI_DEVICE_ID_ENE_1211		0x1211
+#define PCI_DEVICE_ID_ENE_1225		0x1225
+#define PCI_DEVICE_ID_ENE_1410		0x1410
+#define PCI_DEVICE_ID_ENE_1420		0x1420
+
 #define PCI_VENDOR_ID_SYBA		0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP	0x0782
 #define PCI_DEVICE_ID_SYBA_1P_ECP	0x0783
@@ -1853,7 +1872,7 @@
 #define PCI_DEVICE_ID_INTEL_82801DB_7	0x24c7
 #define PCI_DEVICE_ID_INTEL_82801DB_10	0x24ca
 #define PCI_DEVICE_ID_INTEL_82801DB_11	0x24cb
-#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
+#define PCI_DEVICE_ID_INTEL_82801DB_12	0x24cc
 #define PCI_DEVICE_ID_INTEL_82801DB_13	0x24cd
 #define PCI_DEVICE_ID_INTEL_82801EB_0	0x24d0
 #define PCI_DEVICE_ID_INTEL_82801EB_1	0x24d1
@@ -1880,6 +1899,10 @@
 #define PCI_DEVICE_ID_INTEL_ESB_11	0x25ac
 #define PCI_DEVICE_ID_INTEL_ESB_12	0x25ad
 #define PCI_DEVICE_ID_INTEL_ESB_13	0x25ae
+#define PCI_DEVICE_ID_INTEL_ICH6_0	0x2640
+#define PCI_DEVICE_ID_INTEL_ICH6_1	0x2641
+#define PCI_DEVICE_ID_INTEL_ICH6_2	0x266f
+#define PCI_DEVICE_ID_INTEL_ICH6_3	0x266e
 #define PCI_DEVICE_ID_INTEL_82850_HB	0x2530
 #define PCI_DEVICE_ID_INTEL_82845G_HB	0x2560
 #define PCI_DEVICE_ID_INTEL_80310	0x530d
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/sctp.h linux-2.4.26-pre6/include/linux/sctp.h
--- linux-2.4.25/include/linux/sctp.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/sctp.h	2004-03-25 00:20:06.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2002 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -42,6 +42,8 @@
  *    randall@sctp.chicago.il.us
  *    kmorneau@cisco.com
  *    qxie1@email.mot.com
+ *    Sridhar Samudrala <sri@us.ibm.com>
+ *    Kevin Gao <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -59,14 +61,14 @@ typedef struct sctphdr {
 	__u16 dest;
 	__u32 vtag;
 	__u32 checksum;
-} sctp_sctphdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_sctphdr_t;
 
 /* Section 3.2.  Chunk Field Descriptions. */
 typedef struct sctp_chunkhdr {
 	__u8 type;
 	__u8 flags;
 	__u16 length;
-} sctp_chunkhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_chunkhdr_t;
 
 
 /* Section 3.2.  Chunk Type Values.
@@ -150,7 +152,7 @@ enum { SCTP_CHUNK_FLAG_T = 0x01 };
 typedef struct sctp_paramhdr {
 	__u16 type;
 	__u16 length;
-} sctp_paramhdr_t __attribute((packed));
+} __attribute__((packed)) sctp_paramhdr_t;
 
 typedef enum {
 
@@ -200,12 +202,12 @@ typedef struct sctp_datahdr {
 	__u16 ssn;
 	__u32 ppid;
 	__u8  payload[0];
-} sctp_datahdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_datahdr_t;
 
 typedef struct sctp_data_chunk {
         sctp_chunkhdr_t chunk_hdr;
         sctp_datahdr_t  data_hdr;
-} sctp_data_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_data_chunk_t;
 
 /* DATA Chuck Specific Flags */
 enum {
@@ -230,48 +232,48 @@ typedef struct sctp_inithdr {
 	__u16 num_inbound_streams;
 	__u32 initial_tsn;
 	__u8  params[0];
-} sctp_inithdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_inithdr_t;
 
 typedef struct sctp_init_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_inithdr_t init_hdr;
-} sctp_init_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_init_chunk_t;
 
 
 /* Section 3.3.2.1. IPv4 Address Parameter (5) */
 typedef struct sctp_ipv4addr_param {
 	sctp_paramhdr_t param_hdr;
 	struct in_addr  addr;
-} sctp_ipv4addr_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_ipv4addr_param_t;
 
 /* Section 3.3.2.1. IPv6 Address Parameter (6) */
 typedef struct sctp_ipv6addr_param {
 	sctp_paramhdr_t param_hdr;
 	struct in6_addr addr;
-} sctp_ipv6addr_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_ipv6addr_param_t;
 
 /* Section 3.3.2.1 Cookie Preservative (9) */
 typedef struct sctp_cookie_preserve_param {
 	sctp_paramhdr_t param_hdr;
 	uint32_t        lifespan_increment;
-} sctp_cookie_preserve_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_cookie_preserve_param_t;
 
 /* Section 3.3.2.1 Host Name Address (11) */
 typedef struct sctp_hostname_param {
 	sctp_paramhdr_t param_hdr;
 	uint8_t hostname[0];
-} sctp_hostname_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_hostname_param_t;
 
 /* Section 3.3.2.1 Supported Address Types (12) */
 typedef struct sctp_supported_addrs_param {
 	sctp_paramhdr_t param_hdr;
 	uint16_t types[0];
-} sctp_supported_addrs_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_supported_addrs_param_t;
 
 /* Appendix A. ECN Capable (32768) */
 typedef struct sctp_ecn_capable_param {
 	sctp_paramhdr_t param_hdr;
-} sctp_ecn_capable_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_ecn_capable_param_t;
 
 
 
@@ -285,13 +287,13 @@ typedef sctp_init_chunk_t sctp_initack_c
 typedef struct sctp_cookie_param {
 	sctp_paramhdr_t p;
 	__u8 body[0];
-} sctp_cookie_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_cookie_param_t;
 
 /* Section 3.3.3.1 Unrecognized Parameters (8) */
 typedef struct sctp_unrecognized_param {
 	sctp_paramhdr_t param_hdr;
 	sctp_paramhdr_t unrecognized;
-} sctp_unrecognized_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_unrecognized_param_t;
 
 
 
@@ -306,7 +308,7 @@ typedef struct sctp_unrecognized_param {
 typedef struct sctp_gap_ack_block {
 	__u16 start;
 	__u16 end;
-} sctp_gap_ack_block_t __attribute__((packed));
+} __attribute__((packed)) sctp_gap_ack_block_t;
 
 typedef uint32_t sctp_dup_tsn_t;
 
@@ -321,12 +323,12 @@ typedef struct sctp_sackhdr {
 	__u16 num_gap_ack_blocks;
 	__u16 num_dup_tsns;
 	sctp_sack_variable_t variable[0];
-} sctp_sackhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_sackhdr_t;
 
 typedef struct sctp_sack_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_sackhdr_t sack_hdr;
-} sctp_sack_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_sack_chunk_t;
 
 
 /* RFC 2960.  Section 3.3.5 Heartbeat Request (HEARTBEAT) (4):
@@ -338,12 +340,12 @@ typedef struct sctp_sack_chunk {
 
 typedef struct sctp_heartbeathdr {
 	sctp_paramhdr_t info;
-} sctp_heartbeathdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_heartbeathdr_t;
 
 typedef struct sctp_heartbeat_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_heartbeathdr_t hb_hdr;
-} sctp_heartbeat_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_heartbeat_chunk_t;
 
 
 /* For the abort and shutdown ACK we must carry the init tag in the
@@ -352,7 +354,7 @@ typedef struct sctp_heartbeat_chunk {
  */
 typedef struct sctp_abort_chunk {
         sctp_chunkhdr_t uh;
-} sctp_abort_chunkt_t __attribute__((packed));
+} __attribute__((packed)) sctp_abort_chunkt_t;
 
 
 /* For the graceful shutdown we must carry the tag (in common header)
@@ -360,14 +362,12 @@ typedef struct sctp_abort_chunk {
  */
 typedef struct sctp_shutdownhdr {
 	__u32 cum_tsn_ack;
-} sctp_shutdownhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_shutdownhdr_t;
 
 struct sctp_shutdown_chunk_t {
         sctp_chunkhdr_t    chunk_hdr;
         sctp_shutdownhdr_t shutdown_hdr;
-} __attribute__((packed));
-
-
+} __attribute__ ((packed));
 
 /* RFC 2960.  Section 3.3.10 Operation Error (ERROR) (9) */
 
@@ -375,12 +375,12 @@ typedef struct sctp_errhdr {
 	__u16 cause;
 	__u16 length;
 	__u8  variable[0];
-} sctp_errhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_errhdr_t;
 
 typedef struct sctp_operr_chunk {
         sctp_chunkhdr_t chunk_hdr;
 	sctp_errhdr_t   err_hdr;
-} sctp_operr_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_operr_chunk_t;
 
 /* RFC 2960 3.3.10 - Operation Error
  *
@@ -437,12 +437,13 @@ typedef enum {
 	 * 0x0101          Operation Refused Due to Resource Shortage.
 	 * 0x0102          Request to Delete Source IP Address.
 	 * 0x0103          Association Aborted due to illegal ASCONF-ACK
+	 * 0x0104          Request refused - no authorization.
 	 */
 	SCTP_ERROR_DEL_LAST_IP	= __constant_htons(0x0100),
 	SCTP_ERROR_RSRC_LOW	= __constant_htons(0x0101),
 	SCTP_ERROR_DEL_SRC_IP	= __constant_htons(0x0102),
 	SCTP_ERROR_ASCONF_ACK   = __constant_htons(0x0103),
-
+	SCTP_ERROR_REQ_REFUSED	= __constant_htons(0x0104)
 } sctp_error_t;
 
 
@@ -457,7 +458,7 @@ typedef struct sctp_ecnehdr {
 typedef struct sctp_ecne_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_ecnehdr_t ence_hdr;
-} sctp_ecne_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_ecne_chunk_t;
 
 /* RFC 2960.  Appendix A.  Explicit Congestion Notification.
  *   Congestion Window Reduced (CWR) (13)
@@ -469,120 +470,57 @@ typedef struct sctp_cwrhdr {
 typedef struct sctp_cwr_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_cwrhdr_t cwr_hdr;
-} sctp_cwr_chunk_t __attribute__((packed));
-
-
-/* FIXME:  Cleanup needs to continue below this line. */
+} __attribute__((packed)) sctp_cwr_chunk_t;
 
 /*
  * ADDIP Section 3.1 New Chunk Types
  */
 
-
-/* ADDIP Section 3.1.1
- *
- * ASCONF-Request Correlation ID: 32 bits (unsigned integer)
- *
- * This is an opaque integer assigned by the sender to identify each
- * request parameter. It is in host byte order and is only meaningful
- * to the sender. The receiver of the ASCONF Chunk will copy this 32
- * bit value into the ASCONF Correlation ID field of the
- * ASCONF-ACK. The sender of the ASCONF can use this same value in the
- * ASCONF-ACK to find which request the response is for.
- *
- * ASCONF Parameter: TLV format
- *
- * Each Address configuration change is represented by a TLV parameter
- * as defined in Section 3.2. One or more requests may be present in
- * an ASCONF Chunk.
- */
-typedef struct {
-	__u32	correlation;
-	sctp_paramhdr_t p;
-	__u8		payload[0];
-} sctpAsconfReq_t;
-
 /* ADDIP
- * 3.1.1  Address/Stream Configuration Change Chunk (ASCONF)
+ * Section 3.1.1 Address Configuration Change Chunk (ASCONF)
  *
- * This chunk is used to communicate to the remote endpoint one of the
- * configuration change requests that MUST be acknowledged.  The
- * information carried in the ASCONF Chunk uses the form of a
- * Tag-Length-Value (TLV), as described in "3.2.1
- * Optional/Variable-length Parameter Format" in [RFC2960], for all
- * variable parameters.
- */
-typedef struct {
-	__u32	serial;
-	__u8	reserved[3];
-	__u8	addr_type;
-	__u32	addr[4];
-	sctpAsconfReq_t requests[0];
-} sctpAsconf_t;
-
-/* ADDIP
- * 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK)
- *
- * ASCONF-Request Correlation ID: 32 bits (unsigned integer)
- *
- * This value is copied from the ASCONF Correlation ID received in the
- * ASCONF Chunk. It is used by the receiver of the ASCONF-ACK to identify
- * which ASCONF parameter this response is associated with.
- *
- * ASCONF Parameter Response : TLV format
- *
- * The ASCONF Parameter Response is used in the ASCONF-ACK to report
- * status of ASCONF processing. By default, if a responding endpoint
- * does not include any Error Cause, a success is indicated. Thus a
- * sender of an ASCONF-ACK MAY indicate complete success of all TLVs in
- * an ASCONF by returning only the Chunk Type, Chunk Flags, Chunk Length
- * (set to 8) and the Serial Number.
- */
-typedef union {
-	struct {
-		__u32		correlation;
-		sctp_paramhdr_t header;	/* success report */
-	} success;
-	struct {
-		__u32		correlation;
-		sctp_paramhdr_t header;	/* error cause indication */
-		sctp_paramhdr_t errcause;
-		uint8_t request[0];	/* original request from ASCONF */
-	} error;
-#define __correlation	success.correlation
-#define __header	success.header
-#define __cause		error.errcause
-#define __request	error.request
-}  sctpAsconfAckRsp_t;
+ * 	Serial Number: 32 bits (unsigned integer)
+ *	This value represents a Serial Number for the ASCONF Chunk. The
+ *	valid range of Serial Number is from 0 to 2^32-1.
+ *	Serial Numbers wrap back to 0 after reaching 2^32 -1.
+ *
+ *	Address Parameter: 8 or 20 bytes (depending on type)
+ *	The address is an address of the sender of the ASCONF chunk,
+ *	the address MUST be considered part of the association by the
+ *	peer endpoint. This field may be used by the receiver of the 
+ *	ASCONF to help in finding the association. This parameter MUST
+ *	be present in every ASCONF message i.e. it is a mandatory TLV
+ *	parameter.
+ *
+ *	ASCONF Parameter: TLV format
+ *	Each Address configuration change is represented by a TLV
+ *	parameter as defined in Section 3.2. One or more requests may
+ *	be present in an ASCONF Chunk.
+ *
+ * Section 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK)
+ * 
+ *	Serial Number: 32 bits (unsigned integer)
+ *	This value represents the Serial Number for the received ASCONF
+ *	Chunk that is acknowledged by this chunk. This value is copied
+ *	from the received ASCONF Chunk. 
+ *
+ *	ASCONF Parameter Response: TLV format
+ *	The ASCONF Parameter Response is used in the ASCONF-ACK to
+ *	report status of ASCONF processing.
+ */
+typedef struct sctp_addip_param {
+	sctp_paramhdr_t	param_hdr;
+	__u32		crr_id;	
+} __attribute__((packed)) sctp_addip_param_t;
 
-/* ADDIP
- * 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK)
- *
- * This chunk is used by the receiver of an ASCONF Chunk to
- * acknowledge the reception. It carries zero or more results for any
- * ASCONF Parameters that were processed by the receiver.
- */
-typedef struct {
+typedef struct sctp_addiphdr {
 	__u32	serial;
-	sctpAsconfAckRsp_t responses[0];
-} sctpAsconfAck_t;
+	__u8	params[0];
+} __attribute__((packed)) sctp_addiphdr_t;
 
-/*********************************************************************
- * Internal structures
- *
- * These are data structures which never go out on the wire.
- *********************************************************************/
-
-/* What is this data structure for?  The TLV isn't one--it is just a
- * value.  Perhaps this data structure ought to have a type--otherwise
- * it is not unambigiously parseable.  --piggy
- */
-typedef struct {
-	struct list_head hook;
-	int length;	/* length of the TLV */
-
-	/* the actually TLV to be copied into ASCONF_ACK */
-	sctpAsconfAckRsp_t TLV;
-} sctpAsconfAckRspNode_t;
+typedef struct sctp_addip_chunk {
+	sctp_chunkhdr_t chunk_hdr;
+	sctp_addiphdr_t addip_hdr;
+} __attribute__((packed)) sctp_addip_chunk_t;
 
 #endif /* __LINUX_SCTP_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/sisfb.h linux-2.4.26-pre6/include/linux/sisfb.h
--- linux-2.4.25/include/linux/sisfb.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/sisfb.h	2004-03-25 00:20:57.000000000 +0000
@@ -38,7 +38,8 @@
 #define TV_AVIDEO               0x00000100
 #define TV_SVIDEO               0x00000200
 #define TV_SCART                0x00000400
-#define VB_CONEXANT		0x00000800
+#define VB_CONEXANT		0x00000800	/* 661 series only */
+#define VB_TRUMPION		VB_CONEXANT	/* 300 series only */
 #define TV_PALM                 0x00001000
 #define TV_PALN                 0x00002000
 #define TV_NTSCJ		0x00001000
@@ -71,7 +72,8 @@
 #define TV_YPBPR525I		TV_NTSC
 #define TV_YPBPR525P		TV_PAL
 #define TV_YPBPR750P		TV_PALM
-#define TV_YPBPRALL 		(TV_YPBPR525I | TV_YPBPR525P | TV_YPBPR750P)
+#define TV_YPBPR1080I		TV_PALN
+#define TV_YPBPRALL 		(TV_YPBPR525I | TV_YPBPR525P | TV_YPBPR750P | TV_YPBPR1080I)
 
 #define VB_SISBRIDGE            (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
 #define VB_SISTVBRIDGE          (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)
@@ -121,42 +123,44 @@ typedef enum _SIS_CHIP_TYPE {
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	unsigned long sisfb_id;         /* for identifying sisfb */
+	u32    	sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which sisfb manages */
-	int    heapstart;               /* heap start (= sisfb "mem" argument) in KB */
-	unsigned char fbvidmode;	/* current sisfb mode */
+ 	u32    	chip_id;		/* PCI ID of detected chip */
+	u32    	memory;			/* video memory in KB which sisfb manages */
+	u32    	heapstart;            	/* heap start (= sisfb "mem" argument) in KB */
+	u8     	fbvidmode;		/* current sisfb mode */
 
-	unsigned char sisfb_version;
-	unsigned char sisfb_revision;
-	unsigned char sisfb_patchlevel;
+	u8     	sisfb_version;
+	u8     	sisfb_revision;
+	u8 	sisfb_patchlevel;
 
-	unsigned char sisfb_caps;	/* Sisfb capabilities */
+	u8 	sisfb_caps;		/* Sisfb capabilities */
 
-	int    sisfb_tqlen;		/* turbo queue length (in KB) */
+	u32    	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	unsigned int sisfb_pcibus;      /* The card's PCI ID */
-	unsigned int sisfb_pcislot;
-	unsigned int sisfb_pcifunc;
+	u32 	sisfb_pcibus;      	/* The card's PCI ID */
+	u32 	sisfb_pcislot;
+	u32 	sisfb_pcifunc;
 
-	unsigned char sisfb_lcdpdc;	/* PanelDelayCompensation */
+	u8 	sisfb_lcdpdc;		/* PanelDelayCompensation */
 
-	unsigned char sisfb_lcda;	/* Detected status of LCDA for low res/text modes */
+	u8 	sisfb_lcda;		/* Detected status of LCDA for low res/text modes */
 
-	unsigned long sisfb_vbflags;
-	unsigned long sisfb_currentvbflags;
+	u32 	sisfb_vbflags;
+	u32 	sisfb_currentvbflags;
 
-	int sisfb_scalelcd;
-	unsigned long sisfb_specialtiming;
+	u32 	sisfb_scalelcd;
+	u32 	sisfb_specialtiming;
 
-	unsigned char sisfb_haveemi;
-	unsigned char sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	unsigned char sisfb_haveemilcd;
+	u8 	sisfb_haveemi;
+	u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	u8 	sisfb_haveemilcd;
 
-	char reserved[213]; 		/* for future use */
+	u8 	sisfb_lcdpdca;		/* PanelDelayCompensation for LCD-via-CRT1 */
+
+	u8 	reserved[212]; 		/* for future use */
 };
 
 /* For fb memory manager */
@@ -221,62 +225,84 @@ typedef enum _VGA_ENGINE {
 } VGA_ENGINE;
 
 struct video_info {
-	int           chip_id;
-	unsigned int  video_size;
-	unsigned long video_base;
-	char  *       video_vbase;
-	unsigned long mmio_base;
-	char  *       mmio_vbase;
-	unsigned long vga_base;
-	unsigned long mtrr;
-	unsigned long heapstart;
-
-	int    video_bpp;
-	int    video_cmap_len;
-	int    video_width;
-	int    video_height;
-	int    video_vwidth;			/* DEPRECATED - use var instead */
-	int    video_vheight;			/* DEPRECATED - use var instead */
-	int    org_x;				/* DEPRECATED - use var instead */
-	int    org_y;				/* DEPRECATED - use var instead */
-	int    video_linelength;
-	unsigned int refresh_rate;
-
-	unsigned long disp_state;		/* DEPRECATED */
-	unsigned char hasVB;			/* DEPRECATED */
-	unsigned char TV_type;			/* DEPRECATED */
-	unsigned char TV_plug;			/* DEPRECATED */
+	int           	chip_id;
+	unsigned int  	video_size;
+	unsigned long 	video_base;
+	char  *       	video_vbase;
+	unsigned long 	mmio_size;
+	unsigned long 	mmio_base;
+	char  *       	mmio_vbase;
+	unsigned long 	vga_base;
+	unsigned long 	mtrr;
+	unsigned long 	heapstart;
+	char  *	      	bios_vbase;
+	char  *	      	bios_abase;
+
+	int    		video_bpp;
+	int    		video_cmap_len;
+	int    		video_width;
+	int    		video_height;
+	int    		video_vwidth;		/* DEPRECATED - use var instead */
+	int    		video_vheight;		/* DEPRECATED - use var instead */
+	int    		org_x;			/* DEPRECATED - use var instead */
+	int    		org_y;			/* DEPRECATED - use var instead */
+	int    		video_linelength;
+	unsigned int 	refresh_rate;
+
+	unsigned long 	disp_state;		/* DEPRECATED */
+	unsigned char 	hasVB;			/* DEPRECATED */
+	unsigned char 	TV_type;		/* DEPRECATED */
+	unsigned char 	TV_plug;		/* DEPRECATED */
 
 	SIS_CHIP_TYPE chip;
 	unsigned char revision_id;
 
-        unsigned short DstColor;		/* For 2d acceleration */
-	unsigned long  SiS310_AccelDepth;
-	unsigned long  CommandReg;
-
-	spinlock_t     lockaccel;		/* Do not use outside of kernel! */
-
-        unsigned int   pcibus;
-	unsigned int   pcislot;
-	unsigned int   pcifunc;
-
-	int 	       accel;
-
-	unsigned short subsysvendor;
-	unsigned short subsysdevice;
-
-	unsigned long  vbflags;			/* Replacing deprecated stuff from above */
-	unsigned long  currentvbflags;
-
-	int    current_bpp;
-	int    current_width;
-	int    current_height;
-	int    current_htotal;
-	int    current_vtotal;
-	__u32  current_pixclock;
-	int    current_refresh_rate;
+        unsigned short 	DstColor;		/* For 2d acceleration */
+	unsigned long  	SiS310_AccelDepth;
+	unsigned long  	CommandReg;
+
+	spinlock_t     	lockaccel;		/* Do not use outside of kernel! */
+
+        unsigned int   	pcibus;
+	unsigned int   	pcislot;
+	unsigned int   	pcifunc;
+
+	int 	       	accel;
+
+	unsigned short 	subsysvendor;
+	unsigned short 	subsysdevice;
+
+	unsigned long  	vbflags;		/* Replacing deprecated stuff from above */
+	unsigned long  	currentvbflags;
+
+	int    		current_bpp;
+	int    		current_width;
+	int    		current_height;
+	int    		current_htotal;
+	int    		current_vtotal;
+	__u32  		current_pixclock;
+	int    		current_refresh_rate;
+	
+	u8  		mode_no;
+	u8  		rate_idx;
+	int    		modechanged;
+	unsigned char 	modeprechange;
+	
+	int  		newrom;
+	int  		registered;
+	
+	VGA_ENGINE 	sisvga_engine;
+	int 		hwcursor_size;
+	int 		CRT2_write_enable;
+	u8            	caps;
+	
+	unsigned char 	detectedpdc;
+	unsigned char 	detectedpdca;
+	unsigned char 	detectedlcda;
+	
+	unsigned long 	hwcursor_vbase;
 
-	char reserved[200];
+	char reserved[166];
 };
 
 extern struct video_info ivideo;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/skbuff.h linux-2.4.26-pre6/include/linux/skbuff.h
--- linux-2.4.25/include/linux/skbuff.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/skbuff.h	2004-03-25 00:17:11.000000000 +0000
@@ -221,9 +221,6 @@ struct sk_buff {
 #endif
 };
 
-#define SK_WMEM_MAX	65535
-#define SK_RMEM_MAX	65535
-
 #ifdef __KERNEL__
 /*
  *	Handling routines are only of interest to the kernel
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/sysctl.h linux-2.4.26-pre6/include/linux/sysctl.h
--- linux-2.4.25/include/linux/sysctl.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/sysctl.h	2004-03-25 00:16:56.000000000 +0000
@@ -312,6 +312,8 @@ enum
 	NET_TCP_FRTO=92,
 	NET_TCP_LOW_LATENCY=93,
 	NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
+	NET_TCP_WESTWOOD=95,
+	NET_IPV4_IGMP_MAX_MSF=96,
 };
 
 enum {
@@ -360,6 +362,8 @@ enum
 	NET_IPV4_CONF_ARPFILTER=13,
 	NET_IPV4_CONF_MEDIUM_ID=14,
 	NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
+	NET_IPV4_CONF_ARP_ANNOUNCE=18,
+	NET_IPV4_CONF_ARP_IGNORE=19,
 };
 
 /* /proc/sys/net/ipv4/netfilter */
@@ -387,7 +391,8 @@ enum {
 	NET_IPV6_NEIGH=17,
 	NET_IPV6_ROUTE=18,
 	NET_IPV6_ICMP=19,
-	NET_IPV6_BINDV6ONLY=20
+	NET_IPV6_BINDV6ONLY=20,
+	NET_IPV6_MLD_MAX_MSF=25,
 };
 
 enum {
@@ -548,6 +553,7 @@ enum {
 	NET_SCTP_HB_INTERVAL             = 10,
 	NET_SCTP_PRESERVE_ENABLE         = 11,
 	NET_SCTP_MAX_BURST               = 12,
+	NET_SCTP_ADDIP_ENABLE            = 13,
 };
 /* /proc/sys/net/khttpd/ */
 enum {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/usb_gadget.h linux-2.4.26-pre6/include/linux/usb_gadget.h
--- linux-2.4.25/include/linux/usb_gadget.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/linux/usb_gadget.h	2004-03-25 00:18:22.000000000 +0000
@@ -465,6 +465,8 @@ struct usb_gadget_ops {
  * 	driver setup() requests
  * @ep_list: List of other endpoints supported by the device.
  * @speed: Speed of current connection to USB host.
+ * @is_dualspeed: True if the controller supports both high and full speed
+ *	operation.  If it does, the gadget driver must also support both.
  * @name: Identifies the controller hardware type.  Used in diagnostics
  * 	and sometimes configuration.
  * @dev: Driver model state for this abstract device.
@@ -488,6 +490,7 @@ struct usb_gadget {
 	struct usb_ep			*ep0;
 	struct list_head		ep_list;	/* of usb_ep */
 	enum usb_device_speed		speed;
+	unsigned			is_dualspeed:1;
 	const char			*name;
 
 	struct __gadget_device {
@@ -707,7 +710,7 @@ int usb_gadget_unregister_driver (struct
 /**
  * struct usb_string - wraps a C string and its USB id
  * @id:the (nonzero) ID for this string
- * @s:the string, in ISO-8859/1 characters
+ * @s:the string, in UTF-8 encoding
  *
  * If you're using usb_gadget_get_string(), use this to wrap a string
  * together with its ID.
@@ -733,6 +736,17 @@ struct usb_gadget_strings {
 /* put descriptor for string with that id into buf (buflen >= 256) */
 int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
 
+/*-------------------------------------------------------------------------*/
+
+/* utility to simplify managing config descriptors */
+
+/* write vector of descriptors into buffer */
+int usb_descriptor_fillbuf(void *, unsigned,
+		const struct usb_descriptor_header **);
+
+/* build config descriptor from single descriptor vector */
+int usb_gadget_config_buf(const struct usb_config_descriptor *config,
+	void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
 
 #endif  /* __KERNEL__ */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/arp.h linux-2.4.26-pre6/include/net/arp.h
--- linux-2.4.25/include/net/arp.h	2001-11-22 19:47:14.000000000 +0000
+++ linux-2.4.26-pre6/include/net/arp.h	2004-03-25 00:18:11.000000000 +0000
@@ -5,6 +5,8 @@
 #include <linux/if_arp.h>
 #include <net/neighbour.h>
 
+#define HAVE_ARP_CREATE
+
 extern struct neigh_table arp_tbl;
 
 extern void	arp_init(void);
@@ -19,6 +21,12 @@ extern int	arp_bind_neighbour(struct dst
 extern int	arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
 extern void	arp_ifdown(struct net_device *dev);
 
+extern struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
+				  struct net_device *dev, u32 src_ip,
+				  unsigned char *dest_hw, unsigned char *src_hw,
+				  unsigned char *target_hw);
+extern void arp_xmit(struct sk_buff *skb);
+
 extern struct neigh_ops arp_broken_ops;
 
 #endif	/* _ARP_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/bluetooth/hci.h linux-2.4.26-pre6/include/net/bluetooth/hci.h
--- linux-2.4.25/include/net/bluetooth/hci.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/net/bluetooth/hci.h	2004-03-25 00:21:56.000000000 +0000
@@ -50,6 +50,11 @@
 #define HCI_RS232 	4
 #define HCI_PCI		5
 
+/* HCI device quirks */
+enum {
+	HCI_QUIRK_RESET_ON_INIT
+};
+
 /* HCI device flags */
 enum {
 	HCI_UP,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/bluetooth/hci_core.h linux-2.4.26-pre6/include/net/bluetooth/hci_core.h
--- linux-2.4.25/include/net/bluetooth/hci_core.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/net/bluetooth/hci_core.h	2004-03-25 00:20:09.000000000 +0000
@@ -72,7 +72,9 @@ struct hci_dev {
 	__u16		pkt_type;
 	__u16		link_policy;
 	__u16		link_mode;
-	
+
+	unsigned long	quirks;
+
 	atomic_t 	cmd_cnt;
 	unsigned int 	acl_cnt;
 	unsigned int 	sco_cnt;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/ip_vs.h linux-2.4.26-pre6/include/net/ip_vs.h
--- linux-2.4.25/include/net/ip_vs.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/ip_vs.h	2004-03-25 00:17:48.000000000 +0000
@@ -8,7 +8,7 @@
 
 #include <asm/types.h>          /* For __uXX types */
 
-#define IP_VS_VERSION_CODE            0x01000A
+#define IP_VS_VERSION_CODE            0x01000B
 #define NVERSION(version)                       \
 	(version >> 16) & 0xFF,                 \
 	(version >> 8) & 0xFF,                  \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/ipv6.h linux-2.4.26-pre6/include/net/ipv6.h
--- linux-2.4.25/include/net/ipv6.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/ipv6.h	2004-03-25 00:21:29.000000000 +0000
@@ -104,6 +104,7 @@ struct frag_hdr {
 
 /* sysctls */
 extern int sysctl_ipv6_bindv6only;
+extern int sysctl_mld_max_msf;
 
 extern struct ipv6_mib		ipv6_statistics[NR_CPUS*2];
 #define IP6_INC_STATS(field)		SNMP_INC_STATS(ipv6_statistics, field)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/command.h linux-2.4.26-pre6/include/net/sctp/command.h
--- linux-2.4.25/include/net/sctp/command.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/command.h	2004-03-25 00:21:24.000000000 +0000
@@ -1,5 +1,6 @@
-/* SCTP kernel reference Implementation Copyright (C) 1999-2001
- * Cisco, Motorola, and IBM
+/* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
+ * Copyright (C) 1999-2001 Cisco, Motorola
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -87,6 +88,8 @@ typedef enum {
 	SCTP_CMD_RTO_PENDING,	 /* Set transport's rto_pending. */
 	SCTP_CMD_PART_DELIVER,	 /* Partial data delivery considerations. */
 	SCTP_CMD_RENEGE,         /* Renege data on an association. */
+	SCTP_CMD_SETUP_T4,	 /* ADDIP, setup T4 RTO timer parms. */
+	SCTP_CMD_PROCESS_OPERR,  /* Process an ERROR chunk. */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/compat.h linux-2.4.26-pre6/include/net/sctp/compat.h
--- linux-2.4.25/include/net/sctp/compat.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/compat.h	2004-03-25 00:16:54.000000000 +0000
@@ -1,5 +1,6 @@
 /* SCTP kernel reference Implementation
  *
+ * (C) Copyright IBM Corp. 2004
  * Copyright (c) 2003 Hewlett-Packard Company
  * 
  * This file is part of the SCTP kernel reference Implementation
@@ -36,7 +37,7 @@
 #include <linux/seq_file.h>
 
 /*
- * The following defines are for compatibility with 2.5
+ * The following defines are for compatibility with 2.6
  */
 /*
  * container_of - cast a member of a structure out to the containing structure
@@ -54,7 +55,6 @@
 	extern type name[]
 #define SNMP_DEC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_softirq()].field--)
 
-#define sctp_sk(__sk) (&(((struct sock *)__sk)->tp_pinfo.af_sctp))
 #define inet_sk(__sk) (&(((struct sock *)__sk)->protinfo.af_inet))
 #define inet6_sk(__sk) (&(((struct sock *)__sk)->net_pinfo.af_inet6))
 
@@ -64,9 +64,37 @@
 #define __unsafe(x) MOD_INC_USE_COUNT
 #define dst_pmtu(x) ((x)->pmtu)
 
-void sctp_hash_digest(const char *key, const int in_key_len,
-		      const char *text, const int text_len,
-		      __u8 *digest);
+#define sk_family family
+#define sk_state state
+#define sk_type type
+#define sk_socket socket
+#define sk_prot prot
+#define sk_rcvbuf rcvbuf
+#define sk_sndbuf sndbuf
+#define sk_ack_backlog ack_backlog
+#define sk_max_ack_backlog max_ack_backlog
+#define sk_write_space write_space
+#define sk_use_write_queue use_write_queue
+#define sk_err err
+#define sk_err_soft err_soft
+#define sk_error_report error_report
+#define sk_error_queue error_queue
+#define sk_shutdown shutdown
+#define sk_state_change state_change
+#define sk_receive_queue receive_queue
+#define sk_data_ready data_ready
+#define sk_no_check no_check
+#define sk_reuse reuse
+#define sk_destruct destruct
+#define sk_zapped zapped
+#define sk_protocol protocol
+#define sk_backlog_rcv backlog_rcv
+#define sk_allocation allocation
+#define sk_lingertime lingertime
+#define sk_sleep sleep
+#define sk_wmem_queued wmem_queued
+#define sk_bound_dev_if bound_dev_if
+
 /*
  * find last bit set.
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/constants.h linux-2.4.26-pre6/include/net/sctp/constants.h
--- linux-2.4.25/include/net/sctp/constants.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/constants.h	2004-03-25 00:16:56.000000000 +0000
@@ -1,8 +1,8 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
- * Copyright (c) 2001-2002 International Business Machines Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -75,6 +75,7 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX
 #define SCTP_NUM_BASE_CHUNK_TYPES	(SCTP_CID_BASE_MAX + 1)
 #define SCTP_NUM_CHUNK_TYPES		(SCTP_NUM_BASE_CHUNKTYPES + 2)
 
+#define SCTP_NUM_ADDIP_CHUNK_TYPES	2
 
 /* These are the different flavours of event.  */
 typedef enum {
@@ -99,6 +100,7 @@ typedef enum {
 	SCTP_EVENT_TIMEOUT_T1_INIT,
 	SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
 	SCTP_EVENT_TIMEOUT_T3_RTX,
+	SCTP_EVENT_TIMEOUT_T4_RTO,
 	SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
 	SCTP_EVENT_TIMEOUT_HEARTBEAT,
 	SCTP_EVENT_TIMEOUT_SACK,
@@ -122,9 +124,10 @@ typedef enum {
 	SCTP_PRIMITIVE_ABORT,
 	SCTP_PRIMITIVE_SEND,
 	SCTP_PRIMITIVE_REQUESTHEARTBEAT,
+	SCTP_PRIMITIVE_ASCONF,
 } sctp_event_primitive_t;
 
-#define SCTP_EVENT_PRIMITIVE_MAX	SCTP_PRIMITIVE_REQUESTHEARTBEAT
+#define SCTP_EVENT_PRIMITIVE_MAX	SCTP_PRIMITIVE_ASCONF
 #define SCTP_NUM_PRIMITIVE_TYPES	(SCTP_EVENT_PRIMITIVE_MAX + 1)
 
 /* We define here a utility type for manipulating subtypes.
@@ -267,7 +270,8 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 
  * nearest power of 2.
  */
 enum { SCTP_MIN_PMTU = 576 };
-enum { SCTP_MAX_DUP_TSNS = 128 };
+enum { SCTP_MAX_DUP_TSNS = 16 };
+enum { SCTP_MAX_GABS = 16 };
 
 typedef enum {
 	SCTP_COUNTER_INIT_ERROR,
@@ -319,7 +323,7 @@ typedef enum {
 #define SCTP_DEFAULT_COOKIE_LIFE_USEC	0  /* microseconds */
 
 #define SCTP_DEFAULT_MINWINDOW	1500	/* default minimum rwnd size */
-#define SCTP_DEFAULT_MAXWINDOW	32768	/* default rwnd size */
+#define SCTP_DEFAULT_MAXWINDOW	65535	/* default rwnd size */
 #define SCTP_DEFAULT_MAXSEGMENT 1500	/* MTU size, this is the limit
                                          * to which we will raise the P-MTU.
 					 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/sctp.h linux-2.4.26-pre6/include/net/sctp/sctp.h
--- linux-2.4.25/include/net/sctp/sctp.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/sctp.h	2004-03-25 00:18:46.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 International Business Machines, Corp.
  * Copyright (c) 2001-2003 Intel Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
@@ -39,6 +39,8 @@
  *    Daisy Chang           <daisyc@us.ibm.com>
  *    Sridhar Samudrala     <sri@us.ibm.com>
  *    Ardelle Fan           <ardelle.fan@intel.com>
+ *    Ryan Layer            <rmlayer@us.ibm.com>
+ *    Kevin Gao             <kevin.gao@intel.com> 
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -75,7 +77,6 @@
 #include <linux/tty.h>
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
-#include <linux/crypto.h>
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <net/ipv6.h>
@@ -114,17 +115,20 @@
 #define SCTP_STATIC static
 #endif
 
+#define SCTP_MSECS_TO_JIFFIES(msec) \
+	(((msec / 1000) * HZ) + ((msec % 1000) * HZ) / 1000)
+#define JIFFIES_TO_MSECS(jiff) \
+	(((jiff / HZ) * 1000) + ((jiff % HZ) * 1000) / HZ)
+
 /*
  * Function declarations.
  */
 
 /*
- * sctp_protocol.c
+ * sctp/protocol.c
  */
-extern struct sctp_protocol sctp_proto;
 extern struct sock *sctp_get_ctl_sock(void);
-extern int sctp_copy_local_addr_list(struct sctp_protocol  *,
-				     struct sctp_bind_addr *,
+extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
 				     sctp_scope_t, int gfp, int flags);
 extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
 extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
@@ -132,54 +136,55 @@ extern int sctp_register_pf(struct sctp_
 /*
  * sctp/socket.c
  */
-extern int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
-extern int sctp_inet_listen(struct socket *sock, int backlog);
-extern void sctp_write_space(struct sock *sk);
-extern unsigned int sctp_poll(struct file *file, struct socket *sock,
+int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+int sctp_inet_listen(struct socket *sock, int backlog);
+void sctp_write_space(struct sock *sk);
+unsigned int sctp_poll(struct file *file, struct socket *sock,
 		poll_table *wait);
 
 /*
  * sctp/primitive.c
  */
-extern int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg);
-extern int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
-extern int sctp_primitive_ABORT(struct sctp_association *, void *arg);
-extern int sctp_primitive_SEND(struct sctp_association *, void *arg);
-extern int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg);
+int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg);
+int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
+int sctp_primitive_ABORT(struct sctp_association *, void *arg);
+int sctp_primitive_SEND(struct sctp_association *, void *arg);
+int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg);
+int sctp_primitive_ASCONF(struct sctp_association *, void *arg);
 
 /*
  * sctp/crc32c.c
  */
-extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count);
-extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
-extern __u32 sctp_end_cksum(__u32 cksum);
-extern __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
+__u32 sctp_start_cksum(__u8 *ptr, __u16 count);
+__u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
+__u32 sctp_end_cksum(__u32 cksum);
+__u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
 
 /*
  * sctp/input.c
  */
-extern int sctp_rcv(struct sk_buff *skb);
-extern void sctp_v4_err(struct sk_buff *skb, u32 info);
-extern void sctp_hash_established(struct sctp_association *);
-extern void __sctp_hash_established(struct sctp_association *);
-extern void sctp_unhash_established(struct sctp_association *);
-extern void __sctp_unhash_established(struct sctp_association *);
-extern void sctp_hash_endpoint(struct sctp_endpoint *);
-extern void __sctp_hash_endpoint(struct sctp_endpoint *);
-extern void sctp_unhash_endpoint(struct sctp_endpoint *);
-extern void __sctp_unhash_endpoint(struct sctp_endpoint *);
-extern struct sctp_association *__sctp_lookup_association(
+int sctp_rcv(struct sk_buff *skb);
+void sctp_v4_err(struct sk_buff *skb, u32 info);
+void sctp_hash_established(struct sctp_association *);
+void __sctp_hash_established(struct sctp_association *);
+void sctp_unhash_established(struct sctp_association *);
+void __sctp_unhash_established(struct sctp_association *);
+void sctp_hash_endpoint(struct sctp_endpoint *);
+void __sctp_hash_endpoint(struct sctp_endpoint *);
+void sctp_unhash_endpoint(struct sctp_endpoint *);
+void __sctp_unhash_endpoint(struct sctp_endpoint *);
+struct sctp_association *__sctp_lookup_association(
 	const union sctp_addr *,
 	const union sctp_addr *,
 	struct sctp_transport **);
-extern struct sock *sctp_err_lookup(int family, struct sk_buff *,
-				    struct sctphdr *, struct sctp_endpoint **,
-				    struct sctp_association **,
-				    struct sctp_transport **);
-extern void sctp_err_finish(struct sock *, struct sctp_endpoint *,
+struct sock *sctp_err_lookup(int family, struct sk_buff *,
+			     struct sctphdr *, struct sctp_endpoint **,
+			     struct sctp_association **,
+			     struct sctp_transport **);
+void sctp_err_finish(struct sock *, struct sctp_endpoint *,
 			    struct sctp_association *);
-extern void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
-				  struct sctp_transport *t, __u32 pmtu);
+void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
+			   struct sctp_transport *t, __u32 pmtu);
 
 /*
  *  Section:  Macros, externs, and inlines
@@ -227,10 +232,10 @@ static inline int sctp_is_valid_kaddr(un
 	if (addr < PAGE_OFFSET)
 		return 0;
 
-	page = virt_to_page((void*)addr);
+	page = virt_to_page(addr);
 
 	/* Is this page valid? */
-	if (!virt_addr_valid((void*)addr) || PageReserved(page))
+	if (!virt_addr_valid(addr) || PageReserved(page))
 		return 0;
 
 	return 1;
@@ -277,6 +282,7 @@ extern atomic_t sctp_dbg_objcnt_chunk;
 extern atomic_t sctp_dbg_objcnt_bind_addr;
 extern atomic_t sctp_dbg_objcnt_addr;
 extern atomic_t sctp_dbg_objcnt_ssnmap;
+extern atomic_t sctp_dbg_objcnt_datamsg;
 
 /* Macros to atomically increment/decrement objcnt counters.  */
 #define SCTP_DBG_OBJCNT_INC(name) \
@@ -292,8 +298,8 @@ atomic_t sctp_dbg_objcnt_## name = ATOMI
 #define SCTP_DBG_OBJCNT_ENTRY(name) \
 {.label= #name, .counter= &sctp_dbg_objcnt_## name}
 
-extern void sctp_dbg_objcnt_init(void);
-extern void sctp_dbg_objcnt_exit(void);
+void sctp_dbg_objcnt_init(void);
+void sctp_dbg_objcnt_exit(void);
 
 #else
 
@@ -306,11 +312,17 @@ static inline void sctp_dbg_objcnt_exit(
 #endif /* CONFIG_SCTP_DBG_OBJCOUNT */
 
 #if defined CONFIG_SYSCTL
-extern void sctp_sysctl_register(void);
-extern void sctp_sysctl_unregister(void);
+void sctp_sysctl_register(void);
+void sctp_sysctl_unregister(void);
 #else
 static inline void sctp_sysctl_register(void) { return; }
 static inline void sctp_sysctl_unregister(void) { return; }
+static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int *name, int nlen,
+				 void *oldval, size_t *oldlenp, void *newval,
+				 size_t newlen, void **context)
+{
+	return -ENOSYS;
+}
 #endif
 
 /* Size of Supported Address Parameter for 'x' address types. */
@@ -318,9 +330,9 @@ static inline void sctp_sysctl_unregiste
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
-extern int sctp_v6_init(void);
-extern void sctp_v6_exit(void);
-extern void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+int sctp_v6_init(void);
+void sctp_v6_exit(void);
+void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 			int type, int code, int offset, __u32 info);
 
 #else /* #ifdef defined(CONFIG_IPV6) */
@@ -348,7 +360,6 @@ static inline sctp_assoc_t sctp_assoc2id
 	return (sctp_assoc_t) asoc;
 }
 
-
 /* Look up the association by its id.  */
 struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
 
@@ -399,6 +410,12 @@ static inline struct list_head *sctp_lis
 	return result;
 }
 
+/* Tests if the list has one and only one entry. */
+static inline int sctp_list_single_entry(struct list_head *head)
+{
+	return ((head->next != head) && (head->next == head->prev));
+}
+
 /* Calculate the size (in bytes) occupied by the data of an iovec.  */
 static inline size_t get_user_iov_size(struct iovec *iov, int iovlen)
 {
@@ -418,6 +435,10 @@ static inline __s32 sctp_jitter(__u32 rt
 	static __u32 sctp_rand;
 	__s32 ret;
 
+	/* Avoid divide by zero. */
+	if (!rto)
+		rto = 1;
+
 	sctp_rand += jiffies;
 	sctp_rand ^= (sctp_rand << 12);
 	sctp_rand ^= (sctp_rand >> 20);
@@ -430,12 +451,16 @@ static inline __s32 sctp_jitter(__u32 rt
 }
 
 /* Break down data chunks at this point.  */
-static inline int sctp_frag_point(int pmtu)
+static inline int sctp_frag_point(const struct sctp_opt *sp, int pmtu)
 {
-	pmtu -= SCTP_IP_OVERHEAD + sizeof(struct sctp_data_chunk);
-	pmtu -= sizeof(struct sctp_sack_chunk);
+	int frag = pmtu;
+	frag -= SCTP_IP_OVERHEAD + sizeof(struct sctp_data_chunk);
+	frag -= sizeof(struct sctp_sack_chunk);
+
+	if (sp->user_frag)
+		frag = min_t(int, frag, sp->user_frag);
 
-	return pmtu;
+	return frag;
 }
 
 /* Walk through a list of TLV parameters.  Don't trust the
@@ -444,7 +469,7 @@ static inline int sctp_frag_point(int pm
  * there is room for a param header too.
  */
 #define sctp_walk_params(pos, chunk, member)\
-_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
+_sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member)
 
 #define _sctp_walk_params(pos, chunk, end, member)\
 for (pos.v = chunk->member;\
@@ -452,6 +477,18 @@ for (pos.v = chunk->member;\
      pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \
      pos.v += WORD_ROUND(ntohs(pos.p->length)))
 
+#define sctp_walk_errors(err, chunk_hdr)\
+_sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))
+
+#define _sctp_walk_errors(err, chunk_hdr, end)\
+for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
+	    sizeof(sctp_chunkhdr_t));\
+     (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\
+     (void *)err <= (void *)chunk_hdr + end - \
+		    WORD_ROUND(ntohs(err->length));\
+     err = (sctp_errhdr_t *)((void *)err + \
+	    WORD_ROUND(ntohs(err->length))))
+
 /* Round an int up to the next multiple of 4.  */
 #define WORD_ROUND(s) (((s)+3)&~3)
 
@@ -462,37 +499,28 @@ for (pos.v = chunk->member;\
 #define tv_lt(s, t) \
    (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec))
 
-/* Stolen from net/profile.h.  Using it from there is more grief than
- * it is worth.
- */
-static inline void tv_add(const struct timeval *entered, struct timeval *leaved)
-{
-	time_t usecs = leaved->tv_usec + entered->tv_usec;
-	time_t secs = leaved->tv_sec + entered->tv_sec;
-
-	if (usecs >= 1000000) {
-		usecs -= 1000000;
-		secs++;
-	}
-	leaved->tv_sec = secs;
-	leaved->tv_usec = usecs;
-}
-
+/* Add tv1 to tv2. */
+#define TIMEVAL_ADD(tv1, tv2) \
+({ \
+        suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \
+        time_t secs = (tv2).tv_sec + (tv1).tv_sec; \
+\
+        if (usecs >= 1000000) { \
+                usecs -= 1000000; \
+                secs++; \
+        } \
+        (tv2).tv_sec = secs; \
+        (tv2).tv_usec = usecs; \
+})
 
 /* External references. */
 
 extern struct proto sctp_prot;
 extern struct proc_dir_entry *proc_net_sctp;
-extern void sctp_put_port(struct sock *sk);
+void sctp_put_port(struct sock *sk);
 
 /* Static inline functions. */
 
-/* Return the SCTP protocol structure. */
-static inline struct sctp_protocol *sctp_get_protocol(void)
-{
-	return &sctp_proto;
-}
-
 /* Convert from an IP version number to an Address Family symbol.  */
 static inline int ipver2af(__u8 ipver)
 {
@@ -506,6 +534,19 @@ static inline int ipver2af(__u8 ipver)
 	};
 }
 
+/* Convert from an address parameter type to an address family.  */
+static inline int param_type2af(__u16 type)
+{
+	switch (type) {
+	case SCTP_PARAM_IPV4_ADDRESS:
+	        return  AF_INET;
+	case SCTP_PARAM_IPV6_ADDRESS:
+		return AF_INET6;
+	default:
+		return 0;
+	};
+}
+
 /* Perform some sanity checks. */
 static inline int sctp_sanity_check(void)
 {
@@ -520,24 +561,21 @@ static inline int sctp_sanity_check(void
 /* This is the hash function for the SCTP port hash table. */
 static inline int sctp_phashfn(__u16 lport)
 {
-	struct sctp_protocol *sctp_proto = sctp_get_protocol();
-	return (lport & (sctp_proto->port_hashsize - 1));
+	return (lport & (sctp_port_hashsize - 1));
 }
 
 /* This is the hash function for the endpoint hash table. */
 static inline int sctp_ep_hashfn(__u16 lport)
 {
-	struct sctp_protocol *sctp_proto = sctp_get_protocol();
-	return (lport & (sctp_proto->ep_hashsize - 1));
+	return (lport & (sctp_ep_hashsize - 1));
 }
 
 /* This is the hash function for the association hash table. */
 static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
 {
-	struct sctp_protocol *sctp_proto = sctp_get_protocol();
 	int h = (lport << 16) + rport;
 	h ^= h>>8;
-	return (h & (sctp_proto->assoc_hashsize - 1));
+	return (h & (sctp_assoc_hashsize - 1));
 }
 
 /* This is the hash function for the association hash table.  This is
@@ -546,10 +584,53 @@ static inline int sctp_assoc_hashfn(__u1
  */
 static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag)
 {
-	struct sctp_protocol *sctp_proto = sctp_get_protocol();
 	int h = (lport << 16) + rport;
 	h ^= vtag;
-	return (h & (sctp_proto->assoc_hashsize-1));
+	return (h & (sctp_assoc_hashsize-1));
+}
+
+#define sctp_sk(__sk) (&(((struct sock *)__sk)->tp_pinfo.af_sctp))
+#define sctp_opt2sk(__sp) container_of(__sp, struct sock, tp_pinfo.af_sctp)
+
+/* Is a socket of this style? */
+#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
+int static inline __sctp_style(const struct sock *sk, sctp_socket_type_t style)
+{
+	return sctp_sk(sk)->type == style;
+}
+
+/* Is the association in this state? */
+#define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state))
+int static inline __sctp_state(const struct sctp_association *asoc,
+			       sctp_state_t state)
+{
+	return asoc->state == state;
+}
+
+/* Is the socket in this state? */
+#define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state))
+int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
+{
+	return sk->sk_state == state;
+}
+
+/* Map v4-mapped v6 address back to v4 address */
+static inline void sctp_v6_map_v4(union sctp_addr *addr)
+{
+	addr->v4.sin_family = AF_INET;
+	addr->v4.sin_port = addr->v6.sin6_port;
+	addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3];
+}
+
+/* Map v4 address to v4-mapped v6 address */
+static inline void sctp_v4_map_v6(union sctp_addr *addr)
+{
+	addr->v6.sin6_family = AF_INET6;
+	addr->v6.sin6_port = addr->v4.sin_port;
+	addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
+	addr->v6.sin6_addr.s6_addr32[0] = 0;
+	addr->v6.sin6_addr.s6_addr32[1] = 0;
+	addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
 }
 
 #endif /* __net_sctp_h__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/sm.h linux-2.4.26-pre6/include/net/sctp/sm.h
--- linux-2.4.25/include/net/sctp/sm.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/sm.h	2004-03-25 00:18:53.000000000 +0000
@@ -1,15 +1,11 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
- * Copyright (c) 2001-2002 International Business Machines Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
- * This file is part of the implementation of the add-IP extension,
- * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
- * for the SCTP kernel reference Implementation.
- *
  * These are definitions needed by the state machine.
  *
  * The SCTP reference implementation is free software;
@@ -45,12 +41,12 @@
  *    Sridhar Samudrala <sri@us.ibm.com>
  *    Daisy Chang <daisyc@us.ibm.com>
  *    Ardelle Fan <ardelle.fan@intel.com>
+ *    Kevin Gao <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
 
-
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/slab.h>
@@ -89,7 +85,7 @@ typedef sctp_disposition_t (sctp_state_f
 typedef void (sctp_timer_event_t) (unsigned long);
 typedef struct {
 	sctp_state_fn_t *fn;
-	char *name;
+	const char *name;
 } sctp_sm_table_entry_t;
 
 /* A naming convention of "sctp_sf_xxx" applies to all the state functions
@@ -122,6 +118,7 @@ sctp_state_fn_t sctp_sf_tabort_8_4_8;
 sctp_state_fn_t sctp_sf_operr_notify;
 sctp_state_fn_t sctp_sf_t1_timer_expire;
 sctp_state_fn_t sctp_sf_t2_timer_expire;
+sctp_state_fn_t sctp_sf_t4_timer_expire;
 sctp_state_fn_t sctp_sf_t5_timer_expire;
 sctp_state_fn_t sctp_sf_sendbeat_8_3;
 sctp_state_fn_t sctp_sf_beat_8_3;
@@ -142,6 +139,8 @@ sctp_state_fn_t sctp_sf_unk_chunk;
 sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
 sctp_state_fn_t sctp_sf_cookie_echoed_err;
 sctp_state_fn_t sctp_sf_do_5_2_6_stale;
+sctp_state_fn_t sctp_sf_do_asconf;
+sctp_state_fn_t sctp_sf_do_asconf_ack;
 
 /* Prototypes for primitive event state functions.  */
 sctp_state_fn_t sctp_sf_do_prm_asoc;
@@ -159,6 +158,7 @@ sctp_state_fn_t sctp_sf_error_closed;
 sctp_state_fn_t sctp_sf_error_shutdown;
 sctp_state_fn_t sctp_sf_ignore_primitive;
 sctp_state_fn_t sctp_sf_do_prm_requestheartbeat;
+sctp_state_fn_t sctp_sf_do_prm_asconf;
 
 /* Prototypes for other event state functions.  */
 sctp_state_fn_t sctp_sf_do_9_2_start_shutdown;
@@ -181,9 +181,6 @@ sctp_state_fn_t sctp_sf_do_9_2_reshutack
 sctp_state_fn_t sctp_sf_do_9_2_reshut;
 sctp_state_fn_t sctp_sf_do_9_2_shutack;
 
-sctp_state_fn_t lucky;
-sctp_state_fn_t other_stupid;
-
 /* Prototypes for timeout event state functions.  Not in use. */
 sctp_state_fn_t sctp_do_4_2_reinit;
 sctp_state_fn_t sctp_do_4_3_reecho;
@@ -192,15 +189,11 @@ sctp_state_fn_t sctp_do_9_2_reshutack;
 sctp_state_fn_t sctp_do_8_3_hb_err;
 sctp_state_fn_t sctp_heartoff;
 
-/* Prototypes for addip related state functions.  Not in use. */
-sctp_state_fn_t sctp_addip_do_asconf;
-sctp_state_fn_t sctp_addip_do_asconf_ack;
-
 /* Prototypes for utility support functions.  */
 __u8 sctp_get_chunk_type(struct sctp_chunk *chunk);
-sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
-					    sctp_state_t state,
-					    sctp_subtype_t event_subtype);
+const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t,
+					    sctp_state_t,
+					    sctp_subtype_t);
 int sctp_chunk_iif(const struct sctp_chunk *);
 struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *,
 					     struct sctp_chunk *,
@@ -209,71 +202,84 @@ __u32 sctp_generate_verification_tag(voi
 void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
 
 /* Prototypes for chunk-building functions.  */
-sctp_chunk_t *sctp_make_init(const struct sctp_association *,
-			     const sctp_bind_addr_t *,
+struct sctp_chunk *sctp_make_init(const struct sctp_association *,
+			     const struct sctp_bind_addr *,
 			     int gfp, int vparam_len);
-sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *,
-				 const sctp_chunk_t *,
+struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *,
+				 const struct sctp_chunk *,
 				 const int gfp,
 				 const int unkparam_len);
-sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *,
-				    const sctp_chunk_t *);
-sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *,
-				   const sctp_chunk_t *);
-sctp_chunk_t *sctp_make_cwr(const struct sctp_association *,
+struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *,
+				    const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
+				   const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
 				 const __u32 lowest_tsn,
-				 const sctp_chunk_t *);
-sctp_chunk_t *sctp_make_datafrag(struct sctp_association *,
+				 const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_datafrag(struct sctp_association *,
 				 const struct sctp_sndrcvinfo *sinfo,
 				 int len, const __u8 *data,
 				 __u8 flags, __u16 ssn);
-sctp_chunk_t * sctp_make_datafrag_empty(struct sctp_association *,
+struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
 					const struct sctp_sndrcvinfo *sinfo,
 					int len, const __u8 flags,
 					__u16 ssn);
-sctp_chunk_t *sctp_make_data(struct sctp_association *,
+struct sctp_chunk *sctp_make_data(struct sctp_association *,
 			     const struct sctp_sndrcvinfo *sinfo,
 			     int len, const __u8 *data);
-sctp_chunk_t *sctp_make_data_empty(struct sctp_association *,
+struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
 				   const struct sctp_sndrcvinfo *, int len);
-sctp_chunk_t *sctp_make_ecne(const struct sctp_association *,
+struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
 				  const __u32);
-sctp_chunk_t *sctp_make_sack(const struct sctp_association *);
-sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc);
-sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc,
-					  const sctp_chunk_t *);
-sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *,
-					  const sctp_chunk_t *);
-void sctp_init_cause(sctp_chunk_t *, __u16 cause, const void *, size_t);
-sctp_chunk_t *sctp_make_abort(const struct sctp_association *,
-			      const sctp_chunk_t *,
+struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
+struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
+				      const struct sctp_chunk *chunk);
+struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
+					  const struct sctp_chunk *);
+struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
+					  const struct sctp_chunk *);
+void sctp_init_cause(struct sctp_chunk *, __u16 cause, const void *, size_t);
+struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
+			      const struct sctp_chunk *,
 			      const size_t hint);
-sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *,
-				      const sctp_chunk_t *,
+struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
+				      const struct sctp_chunk *,
 				      __u32 tsn);
-sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *,
-				   const sctp_chunk_t *,
+struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
+				   const struct sctp_chunk *,
 				   const struct msghdr *);
-sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *,
+struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
 				  const struct sctp_transport *,
 				  const void *payload,
 				  const size_t paylen);
-sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *,
-				      const sctp_chunk_t *,
+struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
+				      const struct sctp_chunk *,
 				      const void *payload,
 				      const size_t paylen);
-sctp_chunk_t *sctp_make_op_error(const struct sctp_association *,
-				 const sctp_chunk_t *chunk,
+struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
+				 const struct sctp_chunk *chunk,
 				 __u16 cause_code,
 				 const void *payload,
 				 size_t paylen);
-void sctp_chunk_assign_tsn(sctp_chunk_t *);
-void sctp_chunk_assign_ssn(sctp_chunk_t *);
-int sctp_datachunks_from_user(struct sctp_association *,
-			      const struct sctp_sndrcvinfo *,
-			      struct msghdr *, int len,
-			      struct sk_buff_head *);
 
+struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
+				    union sctp_addr *addr,
+				    int vparam_len);
+struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
+					      union sctp_addr *,
+					      struct sockaddr *,
+					      int, __u16);
+struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
+					     union sctp_addr *addr);
+struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
+					__u32 serial, int vparam_len);
+struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+				       struct sctp_chunk *asconf);
+int sctp_process_asconf_ack(struct sctp_association *asoc,
+			    struct sctp_chunk *asconf_ack);
+
+void sctp_chunk_assign_tsn(struct sctp_chunk *);
+void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
 /* Prototypes for statetable processing. */
 
@@ -294,24 +300,17 @@ int sctp_side_effects(sctp_event_t event
                       int gfp);
 
 /* 2nd level prototypes */
-int
-sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
-		     sctp_state_t state,
-		     struct sctp_endpoint *ep,
-		     struct sctp_association *asoc,
-		     void *event_arg,
-		     sctp_disposition_t status,
-		     sctp_cmd_seq_t *retval,
-		     int gfp);
+int sctp_cmd_interpreter(sctp_event_t, sctp_subtype_t, sctp_state_t,
+			 struct sctp_endpoint *, struct sctp_association *,
+			 void *event_arg, sctp_disposition_t,
+			 sctp_cmd_seq_t *retval, int gfp);
 
 
 int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
-void sctp_do_TSNdup(struct sctp_association *, sctp_chunk_t *, long gap);
-
 void sctp_generate_t3_rtx_event(unsigned long peer);
 void sctp_generate_heartbeat_event(unsigned long peer);
 
-sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *);
+sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *);
 struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *,
 				       const struct sctp_association *,
 				       struct sctp_chunk *chunk,
@@ -321,39 +320,33 @@ struct sctp_packet *sctp_ootb_pkt_new(co
 				      const struct sctp_chunk *);
 void sctp_ootb_pkt_free(struct sctp_packet *);
 
-sctp_cookie_param_t *
+struct sctp_cookie_param *
 sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
 		 const struct sctp_chunk *, int *cookie_len,
 		 const __u8 *, int addrs_len);
 struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
 				       const struct sctp_association *,
-				       sctp_chunk_t *, int gfp, int *err,
-				       sctp_chunk_t **err_chk_p);
+				       struct sctp_chunk *, int gfp, int *err,
+				       struct sctp_chunk **err_chk_p);
 int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
 			   struct sockaddr_storage*, int);
 void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
 				const struct sctp_association *asoc,
-				const sctp_chunk_t *chunk,
+				const struct sctp_chunk *chunk,
 				sctp_cmd_seq_t *commands,
-				sctp_chunk_t *err_chunk);
+				struct sctp_chunk *err_chunk);
 
 /* 3rd level prototypes */
 __u32 sctp_generate_tag(const struct sctp_endpoint *);
 __u32 sctp_generate_tsn(const struct sctp_endpoint *);
 
-/* 4th level prototypes */
-void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *,
-			 __u16 port, int iif);
-int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *);
-int sockaddr2sctp_addr(const union sctp_addr *, sctp_addr_param_t *);
-
 /* Extern declarations for major data structures.  */
-sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
-extern sctp_sm_table_entry_t
+const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
+extern const sctp_sm_table_entry_t
 primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
-extern sctp_sm_table_entry_t
+extern const sctp_sm_table_entry_t
 other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
-extern sctp_sm_table_entry_t
+extern const sctp_sm_table_entry_t
 timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
 extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
 
@@ -361,7 +354,7 @@ extern sctp_timer_event_t *sctp_timer_ev
 
 
 /* Get the size of a DATA chunk payload. */
-static inline __u16 sctp_data_size(sctp_chunk_t *chunk)
+static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
 {
 	__u16 size;
 
@@ -438,6 +431,21 @@ static inline int SSN_lte(__u16 s, __u16
 	return (((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT));
 }
 
+/*
+ * ADDIP 3.1.1
+ * The valid range of Serial Number is from 0 to 4294967295 (2**32 - 1). Serial
+ * Numbers wrap back to 0 after reaching 4294967295.
+ */
+enum {
+	ADDIP_SERIAL_SIGN_BIT = (1<<31)
+};
+
+static inline int ADDIP_SERIAL_gte(__u16 s, __u16 t)
+{
+	return (((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT));
+}
+
+
 /* Run sctp_add_cmd() generating a BUG() if there is a failure.  */
 static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
 {
@@ -449,7 +457,7 @@ static inline void sctp_add_cmd_sf(sctp_
  * tag and the T bit is set in the Chunk Flags.
  */
 static inline int
-sctp_vtag_verify_either(const sctp_chunk_t *chunk,
+sctp_vtag_verify_either(const struct sctp_chunk *chunk,
 			const struct sctp_association *asoc)
 {
         /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/structs.h linux-2.4.26-pre6/include/net/sctp/structs.h
--- linux-2.4.25/include/net/sctp/structs.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/structs.h	2004-03-25 00:20:56.000000000 +0000
@@ -1,8 +1,8 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
- * Copyright (c) 2001-2003 International Business Machines Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -14,7 +14,7 @@
  *
  * The SCTP reference implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- *                 ************************
+ *		   ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public License for more details.
  *
@@ -31,18 +31,21 @@
  *    http://www.sf.net/projects/lksctp
  *
  * Written or modified by:
- *    Randall Stewart       <randall@sctp.chicago.il.us>
- *    Ken Morneau           <kmorneau@cisco.com>
- *    Qiaobing Xie          <qxie1@email.mot.com>
+ *    Randall Stewart	    <randall@sctp.chicago.il.us>
+ *    Ken Morneau	    <kmorneau@cisco.com>
+ *    Qiaobing Xie	    <qxie1@email.mot.com>
  *    La Monte H.P. Yarroll <piggy@acm.org>
- *    Karl Knutson          <karl@athena.chicago.il.us>
- *    Jon Grimm             <jgrimm@us.ibm.com>
- *    Xingang Guo           <xingang.guo@intel.com>
- *    Hui Huang             <hui.huang@nokia.com>
- *    Sridhar Samudrala     <sri@us.ibm.com>
+ *    Karl Knutson	    <karl@athena.chicago.il.us>
+ *    Jon Grimm		    <jgrimm@us.ibm.com>
+ *    Xingang Guo	    <xingang.guo@intel.com>
+ *    Hui Huang		    <hui.huang@nokia.com>
+ *    Sridhar Samudrala	    <sri@us.ibm.com>
  *    Daisy Chang	    <daisyc@us.ibm.com>
- *    Dajiang Zhang         <dajiang.zhang@nokia.com>
- *    Ardelle Fan           <ardelle.fan@intel.com>
+ *    Dajiang Zhang	    <dajiang.zhang@nokia.com>
+ *    Ardelle Fan	    <ardelle.fan@intel.com>
+ *    Ryan Layer	    <rmlayer@us.ibm.com>
+ *    Anup Pemmaiah	    <pemmaiah@cc.usu.edu>
+ *    Kevin Gao             <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -54,12 +57,12 @@
 #include <linux/time.h>		/* We get struct timespec.    */
 #include <linux/socket.h>	/* linux/in.h needs this!!    */
 #include <linux/in.h>		/* We get struct sockaddr_in. */
-#include <linux/in6.h>          /* We get struct in6_addr     */
+#include <linux/in6.h>		/* We get struct in6_addr     */
 #include <asm/param.h>		/* We get MAXHOSTNAMELEN.     */
 #include <asm/atomic.h>		/* This gets us atomic counters.  */
 #include <linux/skbuff.h>	/* We need sk_buff_head. */
-#include <linux/sctp.h>         /* We need sctp* header structs.  */
-#include <linux/crypto.h>
+#include <linux/tqueue.h>	/* We need tq_struct.	 */
+#include <linux/sctp.h>		/* We need sctp* header structs.  */
 
 /* A convenience structure for handling sockaddr structures.
  * We should wean ourselves off this.
@@ -70,9 +73,8 @@ union sctp_addr {
 	struct sockaddr sa;
 };
 
-
 /* Forward declarations for data structures. */
-struct sctp_protocol;
+struct sctp_globals;
 struct sctp_endpoint;
 struct sctp_association;
 struct sctp_transport;
@@ -86,46 +88,45 @@ struct sctp_opt;
 struct sctp_ep_common;
 struct sctp_ssnmap;
 
-typedef struct sctp_chunk sctp_chunk_t;
-typedef struct sctp_bind_addr sctp_bind_addr_t;
 
+#include <net/sctp/compat.h>
 #include <net/sctp/tsnmap.h>
 #include <net/sctp/ulpevent.h>
 #include <net/sctp/ulpqueue.h>
 
 /* Structures useful for managing bind/connect. */
 
-typedef struct sctp_bind_bucket {
-	unsigned short 	port;
+struct sctp_bind_bucket {
+	unsigned short	port;
 	unsigned short	fastreuse;
 	struct sctp_bind_bucket *next;
 	struct sctp_bind_bucket **pprev;
 	struct sock	        *sk;
-} sctp_bind_bucket_t;
+};
 
-typedef struct sctp_bind_hashbucket {
+struct sctp_bind_hashbucket {
 	spinlock_t	lock;
 	struct sctp_bind_bucket	*chain;
-} sctp_bind_hashbucket_t;
+};
 
 /* Used for hashing all associations.  */
-typedef struct sctp_hashbucket {
+struct sctp_hashbucket {
 	rwlock_t	lock;
 	struct sctp_ep_common  *chain;
-} sctp_hashbucket_t __attribute__((__aligned__(8)));
+} __attribute__((__aligned__(8)));
 
 
-/* The SCTP protocol structure. */
-struct sctp_protocol {
+/* The SCTP globals structure. */
+extern struct sctp_globals {
 	/* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values
 	 *
 	 * The following protocol parameters are RECOMMENDED:
 	 *
-	 * RTO.Initial              - 3  seconds
-	 * RTO.Min                  - 1  second
-	 * RTO.Max                 -  60 seconds
-	 * RTO.Alpha                - 1/8  (3 when converted to right shifts.)
-	 * RTO.Beta                 - 1/4  (2 when converted to right shifts.)
+	 * RTO.Initial		    - 3	 seconds
+	 * RTO.Min		    - 1	 second
+	 * RTO.Max		   -  60 seconds
+	 * RTO.Alpha		    - 1/8  (3 when converted to right shifts.)
+	 * RTO.Beta		    - 1/4  (2 when converted to right shifts.)
 	 */
 	__u32 rto_initial;
 	__u32 rto_min;
@@ -140,24 +141,24 @@ struct sctp_protocol {
 	/* Max.Burst		    - 4 */
 	int max_burst;
 
-	/* Valid.Cookie.Life        - 60  seconds  */
+	/* Valid.Cookie.Life	    - 60  seconds  */
 	int valid_cookie_life;
 
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
 	int cookie_preserve_enable;
 
 	/* Association.Max.Retrans  - 10 attempts
-	 * Path.Max.Retrans         - 5  attempts (per destination address)
-	 * Max.Init.Retransmits     - 8  attempts
+	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
+	 * Max.Init.Retransmits	    - 8	 attempts
 	 */
 	int max_retrans_association;
 	int max_retrans_path;
 	int max_retrans_init;
 
-	/* HB.interval              - 30 seconds  */
+	/* HB.interval		    - 30 seconds  */
 	int hb_interval;
 
-	/* The following variables are implementation specific.  */
+	/* The following variables are implementation specific.	 */
 
 	/* Default initialization values to be applied to new associations. */
 	__u16 max_instreams;
@@ -170,102 +171,57 @@ struct sctp_protocol {
 
 	/* This is the hash of all endpoints. */
 	int ep_hashsize;
-	sctp_hashbucket_t *ep_hashbucket;
+	struct sctp_hashbucket *ep_hashtable;
 
 	/* This is the hash of all associations. */
 	int assoc_hashsize;
-	sctp_hashbucket_t *assoc_hashbucket;
+	struct sctp_hashbucket *assoc_hashtable;
 
-	/* This is the sctp port control hash.  */
+	/* This is the sctp port control hash.	*/
 	int port_hashsize;
 	int port_rover;
 	spinlock_t port_alloc_lock;  /* Protects port_rover. */
-	sctp_bind_hashbucket_t *port_hashtable;
+	struct sctp_bind_hashbucket *port_hashtable;
 
 	/* This is the global local address list.
 	 * We actively maintain this complete list of interfaces on
 	 * the system by catching routing events.
 	 *
-	 * It is a list of struct sockaddr_storage_list.
+	 * It is a list of sctp_sockaddr_entry.
 	 */
 	struct list_head local_addr_list;
 	spinlock_t local_addr_lock;
-};
-
-
-/*
- * Pointers to address related SCTP functions.
- * (i.e. things that depend on the address family.)
- */
-struct sctp_af {
-	int		(*sctp_xmit)	(struct sk_buff *skb,
-					 struct sctp_transport *,
-					 int ipfragok);
-	int 		(*setsockopt)	(struct sock *sk,
-					 int level,
-					 int optname,
-					 char *optval,
-					 int optlen);
-	int 		(*getsockopt)	(struct sock *sk,
-					 int level,
-					 int optname,
-					 char *optval,
-					 int *optlen);
-	struct dst_entry *(*get_dst)	(struct sctp_association *asoc,
-					 union sctp_addr *daddr,
-					 union sctp_addr *saddr);
-	void 		(*get_saddr)	(struct sctp_association *asoc,
-					 struct dst_entry *dst,
-					 union sctp_addr *daddr,
-				 	 union sctp_addr *saddr);
-	void            (*copy_addrlist) (struct list_head *,
-					  struct net_device *);
-	void            (*dst_saddr)    (union sctp_addr *saddr,
-					 struct dst_entry *dst,
-					 unsigned short port);
-	int             (*cmp_addr)     (const union sctp_addr *addr1,
-					 const union sctp_addr *addr2);
-	void            (*addr_copy)    (union sctp_addr *dst,
-					 union sctp_addr *src);
-	void            (*from_skb)     (union sctp_addr *,
-					 struct sk_buff *skb,
-					 int saddr);
-	void            (*from_sk)      (union sctp_addr *,
-					 struct sock *sk);
-	void            (*to_sk_saddr)  (union sctp_addr *,
-					 struct sock *sk);
-	void            (*to_sk_daddr)  (union sctp_addr *,
-					 struct sock *sk);
-	int             (*addr_valid)   (union sctp_addr *);
-	sctp_scope_t    (*scope) (union sctp_addr *);
-	void            (*inaddr_any)   (union sctp_addr *, unsigned short);
-	int             (*is_any)       (const union sctp_addr *);
-	int             (*available)    (const union sctp_addr *);
-	int             (*skb_iif)      (const struct sk_buff *sk);
-	__u16		net_header_len;
-	int		sockaddr_len;
-	sa_family_t	sa_family;
-	struct list_head list;
-};
-
-struct sctp_af *sctp_get_af_specific(sa_family_t);
-int sctp_register_af(struct sctp_af *);
+	
+	/* Flag to indicate if addip is enabled. */
+	int addip_enable;
+} sctp_globals;
 
-/* Protocol family functions. */
-struct sctp_pf {
-	void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
-	void (*skb_msgname)  (struct sk_buff *, char *, int *);
-	int  (*af_supported) (sa_family_t);
-	int  (*cmp_addr) (const union sctp_addr *,
-			  const union sctp_addr *,
-			  struct sctp_opt *);
-	int  (*bind_verify) (struct sctp_opt *, union sctp_addr *);
-	int  (*send_verify) (struct sctp_opt *, union sctp_addr *);
-	int  (*supported_addrs)(const struct sctp_opt *, __u16 *);
-	struct sock *(*create_accept_sk) (struct sock *sk,
-					  struct sctp_association *asoc);
-	struct sctp_af *af;
-};
+#define sctp_rto_initial		(sctp_globals.rto_initial)
+#define sctp_rto_min			(sctp_globals.rto_min)
+#define sctp_rto_max			(sctp_globals.rto_max)
+#define sctp_rto_alpha			(sctp_globals.rto_alpha)
+#define sctp_rto_beta			(sctp_globals.rto_beta)
+#define sctp_max_burst			(sctp_globals.max_burst)
+#define sctp_valid_cookie_life		(sctp_globals.valid_cookie_life)
+#define sctp_cookie_preserve_enable	(sctp_globals.cookie_preserve_enable)
+#define sctp_max_retrans_association	(sctp_globals.max_retrans_association)
+#define sctp_max_retrans_path		(sctp_globals.max_retrans_path)
+#define sctp_max_retrans_init		(sctp_globals.max_retrans_init)
+#define sctp_hb_interval		(sctp_globals.hb_interval)
+#define sctp_max_instreams		(sctp_globals.max_instreams)
+#define sctp_max_outstreams		(sctp_globals.max_outstreams)
+#define sctp_address_families		(sctp_globals.address_families)
+#define sctp_ep_hashsize		(sctp_globals.ep_hashsize)
+#define sctp_ep_hashtable		(sctp_globals.ep_hashtable)
+#define sctp_assoc_hashsize		(sctp_globals.assoc_hashsize)
+#define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
+#define sctp_port_hashsize		(sctp_globals.port_hashsize)
+#define sctp_port_rover			(sctp_globals.port_rover)
+#define sctp_port_alloc_lock		(sctp_globals.port_alloc_lock)
+#define sctp_port_hashtable		(sctp_globals.port_hashtable)
+#define sctp_local_addr_list		(sctp_globals.local_addr_list)
+#define sctp_local_addr_lock		(sctp_globals.local_addr_lock)
+#define sctp_addip_enable		(sctp_globals.addip_enable)
 
 /* SCTP Socket type: UDP or TCP style. */
 typedef enum {
@@ -291,14 +247,21 @@ struct sctp_opt {
 	/* Various Socket Options.  */
 	__u16 default_stream;
 	__u32 default_ppid;
+	__u16 default_flags;
+	__u32 default_context;
+	__u32 default_timetolive;
+
 	struct sctp_initmsg initmsg;
 	struct sctp_rtoinfo rtoinfo;
 	struct sctp_paddrparams paddrparam;
 	struct sctp_event_subscribe subscribe;
+	struct sctp_assocparams assocparams;
+	int user_frag;
 	__u32 autoclose;
 	__u8 nodelay;
 	__u8 disable_fragments;
 	__u8 pd_mode;
+	__u8 v4mapped;
 
 	/* Receive to here while partial delivery is in effect. */
 	struct sk_buff_head pd_lobby;
@@ -315,22 +278,23 @@ struct sctp_opt {
  *
  */
 
-typedef struct sctp_cookie {
-        /* My          : Tag expected in every inbound packet and sent
-         * Verification: in the INIT or INIT ACK chunk.
-         * Tag         :
-         */
-        __u32 my_vtag;
-
-        /* Peer's      : Tag expected in every outbound packet except
-         * Verification: in the INIT chunk.
-         * Tag         :
-         */
-        __u32 peer_vtag;
-
-        /* The rest of these are not from the spec, but really need to
-         * be in the cookie.
-         */
+struct sctp_cookie {
+
+	/* My	       : Tag expected in every inbound packet and sent
+	 * Verification: in the INIT or INIT ACK chunk.
+	 * Tag	       :
+	 */
+	__u32 my_vtag;
+
+	/* Peer's      : Tag expected in every outbound packet except
+	 * Verification: in the INIT chunk.
+	 * Tag	       :
+	 */
+	__u32 peer_vtag;
+
+	/* The rest of these are not from the spec, but really need to
+	 * be in the cookie.
+	 */
 
 	/* My Tie Tag  : Assist in discovering a restarting association. */
 	__u32 my_ttag;
@@ -338,16 +302,16 @@ typedef struct sctp_cookie {
 	/* Peer's Tie Tag: Assist in discovering a restarting association. */
 	__u32 peer_ttag;
 
+	/* When does this cookie expire? */
+	struct timeval expiration;
+
 	/* Number of inbound/outbound streams which are set
 	 * and negotiated during the INIT process.
 	 */
 	__u16 sinit_num_ostreams;
 	__u16 sinit_max_instreams;
 
-        /* When does this cookie expire? */
-        struct timeval expiration __attribute__((packed));
-
-        /* This is the first sequence number I used.  */
+	/* This is the first sequence number I used.  */
 	__u32 initial_tsn;
 
 	/* This holds the originating address of the INIT packet.  */
@@ -360,38 +324,38 @@ typedef struct sctp_cookie {
 	 * the association TCB is re-constructed from the cookie.
 	 */
 	__u32 raw_addr_list_len;
-	sctp_init_chunk_t peer_init[0];
-} sctp_cookie_t __attribute__((aligned(4)));
+	struct sctp_init_chunk peer_init[0];
+};
 
 
 /* The format of our cookie that we send to our peer. */
-typedef struct sctp_signed_cookie {
+struct sctp_signed_cookie {
 	__u8 signature[SCTP_SECRET_SIZE];
-	sctp_cookie_t c;
-} sctp_signed_cookie_t;
+	struct sctp_cookie c;
+};
 
 /* This is another convenience type to allocate memory for address
  * params for the maximum size and pass such structures around
  * internally.
  */
-typedef union {
-	sctp_ipv4addr_param_t v4;
-	sctp_ipv6addr_param_t v6;
-} sctp_addr_param_t;
+union sctp_addr_param {
+	struct sctp_ipv4addr_param v4;
+	struct sctp_ipv6addr_param v6;
+};
 
 /* A convenience type to allow walking through the various
  * parameters and avoid casting all over the place.
  */
 union sctp_params {
 	void *v;
-	sctp_paramhdr_t *p;
-	sctp_cookie_preserve_param_t *life;
-	sctp_hostname_param_t *dns;
-	sctp_cookie_param_t *cookie;
-	sctp_supported_addrs_param_t *sat;
-	sctp_ipv4addr_param_t *v4;
-	sctp_ipv6addr_param_t *v6;
-	sctp_addr_param_t *addr;
+	struct sctp_paramhdr *p;
+	struct sctp_cookie_preserve_param *life;
+	struct sctp_hostname_param *dns;
+	struct sctp_cookie_param *cookie;
+	struct sctp_supported_addrs_param *sat;
+	struct sctp_ipv4addr_param *v4;
+	struct sctp_ipv6addr_param *v6;
+	union sctp_addr_param *addr;
 };
 
 /* RFC 2960.  Section 3.3.5 Heartbeat.
@@ -402,10 +366,10 @@ union sctp_params {
  *    HEARTBEAT is sent (see Section 8.3).
  */
 typedef struct sctp_sender_hb_info {
-	sctp_paramhdr_t param_hdr;
+	struct sctp_paramhdr param_hdr;
 	union sctp_addr daddr;
 	unsigned long sent_at;
-} sctp_sender_hb_info_t __attribute__((packed, aligned(4)));
+} __attribute__((packed)) sctp_sender_hb_info_t;
 
 /*
  *  RFC 2960 1.3.2 Sequenced Delivery within Streams
@@ -443,12 +407,129 @@ static inline __u16 sctp_ssn_peek(struct
 	return stream->ssn[id];
 }
 
-/* Return the next SSN number for this stream.  */
+/* Return the next SSN number for this stream.	*/
 static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
 {
 	return stream->ssn[id]++;
 }
 
+/*
+ * Pointers to address related SCTP functions.
+ * (i.e. things that depend on the address family.)
+ */
+struct sctp_af {
+	int		(*sctp_xmit)	(struct sk_buff *skb,
+					 struct sctp_transport *,
+					 int ipfragok);
+	int		(*setsockopt)	(struct sock *sk,
+					 int level,
+					 int optname,
+					 char *optval,
+					 int optlen);
+	int		(*getsockopt)	(struct sock *sk,
+					 int level,
+					 int optname,
+					 char *optval,
+					 int *optlen);
+	struct dst_entry *(*get_dst)	(struct sctp_association *asoc,
+					 union sctp_addr *daddr,
+					 union sctp_addr *saddr);
+	void		(*get_saddr)	(struct sctp_association *asoc,
+					 struct dst_entry *dst,
+					 union sctp_addr *daddr,
+					 union sctp_addr *saddr);
+	void		(*copy_addrlist) (struct list_head *,
+					  struct net_device *);
+	void		(*dst_saddr)	(union sctp_addr *saddr,
+					 struct dst_entry *dst,
+					 unsigned short port);
+	int		(*cmp_addr)	(const union sctp_addr *addr1,
+					 const union sctp_addr *addr2);
+	void		(*addr_copy)	(union sctp_addr *dst,
+					 union sctp_addr *src);
+	void		(*from_skb)	(union sctp_addr *,
+					 struct sk_buff *skb,
+					 int saddr);
+	void		(*from_sk)	(union sctp_addr *,
+					 struct sock *sk);
+	void		(*to_sk_saddr)	(union sctp_addr *,
+					 struct sock *sk);
+	void		(*to_sk_daddr)	(union sctp_addr *,
+					 struct sock *sk);
+	void		(*from_addr_param) (union sctp_addr *,
+					    union sctp_addr_param *,
+					    __u16 port, int iif);	
+	int		(*to_addr_param) (const union sctp_addr *,
+					  union sctp_addr_param *); 
+	int		(*addr_valid)	(union sctp_addr *,
+					 struct sctp_opt *);
+	sctp_scope_t	(*scope) (union sctp_addr *);
+	void		(*inaddr_any)	(union sctp_addr *, unsigned short);
+	int		(*is_any)	(const union sctp_addr *);
+	int		(*available)	(union sctp_addr *,
+					 struct sctp_opt *);
+	int		(*skb_iif)	(const struct sk_buff *sk);
+	int		(*is_ce)	(const struct sk_buff *sk);
+	void		(*seq_dump_addr)(struct seq_file *seq,
+					 union sctp_addr *addr);
+	__u16		net_header_len;
+	int		sockaddr_len;
+	sa_family_t	sa_family;
+	struct list_head list;
+};
+
+struct sctp_af *sctp_get_af_specific(sa_family_t);
+int sctp_register_af(struct sctp_af *);
+
+/* Protocol family functions. */
+struct sctp_pf {
+	void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
+	void (*skb_msgname)  (struct sk_buff *, char *, int *);
+	int  (*af_supported) (sa_family_t, struct sctp_opt *);
+	int  (*cmp_addr) (const union sctp_addr *,
+			  const union sctp_addr *,
+			  struct sctp_opt *);
+	int  (*bind_verify) (struct sctp_opt *, union sctp_addr *);
+	int  (*send_verify) (struct sctp_opt *, union sctp_addr *);
+	int  (*supported_addrs)(const struct sctp_opt *, __u16 *);
+	struct sock *(*create_accept_sk) (struct sock *sk,
+					  struct sctp_association *asoc);
+	void (*addr_v4map) (struct sctp_opt *, union sctp_addr *);
+	struct sctp_af *af;
+};
+
+
+/* Structure to track chunk fragments that have been acked, but peer
+ * fragments of the same message have not.
+ */
+struct sctp_datamsg {
+	/* Chunks waiting to be submitted to lower layer. */
+	struct list_head chunks;
+	/* Chunks that have been transmitted. */
+	struct list_head track;
+	/* Reference counting. */
+	atomic_t refcnt;
+	/* When is this message no longer interesting to the peer? */
+	unsigned long expires_at;
+	/* Did the messenge fail to send? */
+	int send_error;
+	char send_failed;
+	/* Control whether fragments from this message can expire. */
+	char can_expire;
+};
+
+struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
+					    struct sctp_sndrcvinfo *,
+					    struct msghdr *, int len);
+struct sctp_datamsg *sctp_datamsg_new(int gfp);
+void sctp_datamsg_put(struct sctp_datamsg *);
+void sctp_datamsg_hold(struct sctp_datamsg *);
+void sctp_datamsg_free(struct sctp_datamsg *);
+void sctp_datamsg_track(struct sctp_chunk *);
+void sctp_datamsg_assign(struct sctp_datamsg *, struct sctp_chunk *);
+void sctp_datamsg_fail(struct sctp_chunk *, int error);
+int sctp_datamsg_expires(struct sctp_chunk *);
+
 
 /* RFC2960 1.4 Key Terms
  *
@@ -463,9 +544,10 @@ struct sctp_chunk {
 	 * three elements of struct sk_buff.  This allows us to reuse
 	 * all the skb_* queue management functions.
 	 */
-	sctp_chunk_t *next;
-	sctp_chunk_t *prev;
+	struct sctp_chunk *next;
+	struct sctp_chunk *prev;
 	struct sk_buff_head *list;
+	atomic_t refcnt;
 
 	/* This is our link to the per-transport transmitted list.  */
 	struct list_head transmitted_list;
@@ -490,23 +572,23 @@ struct sctp_chunk {
 	union sctp_params param_hdr;
 	union {
 		__u8 *v;
-		sctp_datahdr_t *data_hdr;
-		sctp_inithdr_t *init_hdr;
-		sctp_sackhdr_t *sack_hdr;
-		sctp_heartbeathdr_t *hb_hdr;
-		sctp_sender_hb_info_t *hbs_hdr;
-		sctp_shutdownhdr_t *shutdown_hdr;
-		sctp_signed_cookie_t *cookie_hdr;
-		sctp_ecnehdr_t *ecne_hdr;
-		sctp_cwrhdr_t *ecn_cwr_hdr;
-		sctp_errhdr_t *err_hdr;
+		struct sctp_datahdr *data_hdr;
+		struct sctp_inithdr *init_hdr;
+		struct sctp_sackhdr *sack_hdr;
+		struct sctp_heartbeathdr *hb_hdr;
+		struct sctp_sender_hb_info *hbs_hdr;
+		struct sctp_shutdownhdr *shutdown_hdr;
+		struct sctp_signed_cookie *cookie_hdr;
+		struct sctp_ecnehdr *ecne_hdr;
+		struct sctp_cwrhdr *ecn_cwr_hdr;
+		struct sctp_errhdr *err_hdr;
+		struct sctp_addiphdr *addip_hdr;
 	} subh;
 
 	__u8 *chunk_end;
 
-	sctp_chunkhdr_t *chunk_hdr;
-
-	sctp_sctphdr_t  *sctp_hdr;
+	struct sctp_chunkhdr *chunk_hdr;
+	struct sctphdr *sctp_hdr;
 
 	/* This needs to be recoverable for SCTP_SEND_FAILED events. */
 	struct sctp_sndrcvinfo sinfo;
@@ -520,50 +602,59 @@ struct sctp_chunk {
 	/* We fill this in if we are calculating RTT. */
 	unsigned long sent_at;
 
-	__u8 rtt_in_progress;  /* Is this chunk used for RTT calculation? */
-	__u8 num_times_sent;   /* How man times did we send this? */
-	__u8 has_tsn;          /* Does this chunk have a TSN yet? */
-	__u8 has_ssn;          /* Does this chunk have a SSN yet? */
-	__u8 singleton;        /* Was this the only chunk in the packet? */
-	__u8 end_of_packet;    /* Was this the last chunk in the packet? */
-	__u8 ecn_ce_done;      /* Have we processed the ECN CE bit? */
-	__u8 pdiscard;	  /* Discard the whole packet now? */
-	__u8 tsn_gap_acked;	  /* Is this chunk acked by a GAP ACK? */
-	__u8 fast_retransmit;    /* Is this chunk fast retransmitted? */
-	__u8 tsn_missing_report; /* Data chunk missing counter. */
-
 	/* What is the origin IP address for this chunk?  */
 	union sctp_addr source;
 	/* Destination address for this chunk. */
 	union sctp_addr dest;
 
+	/* For outbound message, track all fragments for SEND_FAILED. */
+	struct sctp_datamsg *msg;
+
 	/* For an inbound chunk, this tells us where it came from.
 	 * For an outbound chunk, it tells us where we'd like it to
-	 * go.  It is NULL if we have no preference.
+	 * go.	It is NULL if we have no preference.
 	 */
 	struct sctp_transport *transport;
+
+	__u8 rtt_in_progress;	/* Is this chunk used for RTT calculation? */
+	__u8 resent;		/* Has this chunk ever been retransmitted. */
+	__u8 has_tsn;		/* Does this chunk have a TSN yet? */
+	__u8 has_ssn;		/* Does this chunk have a SSN yet? */
+	__u8 singleton;		/* Was this the only chunk in the packet? */
+	__u8 end_of_packet;	/* Was this the last chunk in the packet? */
+	__u8 ecn_ce_done;	/* Have we processed the ECN CE bit? */
+	__u8 pdiscard;		/* Discard the whole packet now? */
+	__u8 tsn_gap_acked;	/* Is this chunk acked by a GAP ACK? */
+	__u8 fast_retransmit;	 /* Is this chunk fast retransmitted? */
+	__u8 tsn_missing_report; /* Data chunk missing counter. */
 };
 
-sctp_chunk_t *sctp_make_chunk(const struct sctp_association *, __u8 type,
-			      __u8 flags, int size);
-void sctp_free_chunk(sctp_chunk_t *);
-void  *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data);
-sctp_chunk_t *sctp_chunkify(struct sk_buff *, const struct sctp_association *,
-			    struct sock *);
-void sctp_init_addrs(sctp_chunk_t *, union sctp_addr *, union sctp_addr *);
-const union sctp_addr *sctp_source(const sctp_chunk_t *chunk);
+void sctp_chunk_hold(struct sctp_chunk *);
+void sctp_chunk_put(struct sctp_chunk *);
+int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
+			  struct iovec *data);
+struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
+				   __u8 flags, int size);
+void sctp_chunk_free(struct sctp_chunk *);
+void  *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
+struct sctp_chunk *sctp_chunkify(struct sk_buff *,
+				 const struct sctp_association *,
+				 struct sock *);
+void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
+		     union sctp_addr *);
+const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
 
 /* This is a structure for holding either an IPv6 or an IPv4 address.  */
 /* sin_family -- AF_INET or AF_INET6
  * sin_port -- ordinary port number
  * sin_addr -- cast to either (struct in_addr) or (struct in6_addr)
  */
-struct sockaddr_storage_list {
+struct sctp_sockaddr_entry {
 	struct list_head list;
 	union sctp_addr a;
 };
 
-typedef sctp_chunk_t *(sctp_packet_phandler_t)(struct sctp_association *);
+typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
 
 /* This structure holds lists of chunks as we are assembling for
  * transmission.
@@ -611,22 +702,22 @@ typedef int (sctp_outq_thandler_t)(struc
 typedef int (sctp_outq_ehandler_t)(struct sctp_outq *);
 typedef struct sctp_packet *(sctp_outq_ohandler_init_t)
 	(struct sctp_packet *,
-         struct sctp_transport *,
-         __u16 sport,
-         __u16 dport);
+	 struct sctp_transport *,
+	 __u16 sport,
+	 __u16 dport);
 typedef struct sctp_packet *(sctp_outq_ohandler_config_t)
-        (struct sctp_packet *,
+	(struct sctp_packet *,
 	 __u32 vtag,
 	 int ecn_capable,
 	 sctp_packet_phandler_t *get_prepend_chunk);
 typedef sctp_xmit_t (sctp_outq_ohandler_t)(struct sctp_packet *,
-                                               sctp_chunk_t *);
+					       struct sctp_chunk *);
 typedef int (sctp_outq_ohandler_force_t)(struct sctp_packet *);
 
 sctp_outq_ohandler_init_t    sctp_packet_init;
 sctp_outq_ohandler_config_t  sctp_packet_config;
-sctp_outq_ohandler_t         sctp_packet_append_chunk;
-sctp_outq_ohandler_t         sctp_packet_transmit_chunk;
+sctp_outq_ohandler_t	     sctp_packet_append_chunk;
+sctp_outq_ohandler_t	     sctp_packet_transmit_chunk;
 sctp_outq_ohandler_force_t   sctp_packet_transmit;
 void sctp_packet_free(struct sctp_packet *);
 
@@ -636,19 +727,19 @@ void sctp_packet_free(struct sctp_packet
  *
  * RFC2960 Section 1.4 Key Terms
  *
- *   o  Transport address:  A Transport Address is traditionally defined
- *      by Network Layer address, Transport Layer protocol and Transport
- *      Layer port number.  In the case of SCTP running over IP, a
- *      transport address is defined by the combination of an IP address
- *      and an SCTP port number (where SCTP is the Transport protocol).
+ *   o	Transport address:  A Transport Address is traditionally defined
+ *	by Network Layer address, Transport Layer protocol and Transport
+ *	Layer port number.  In the case of SCTP running over IP, a
+ *	transport address is defined by the combination of an IP address
+ *	and an SCTP port number (where SCTP is the Transport protocol).
  *
  * RFC2960 Section 7.1 SCTP Differences from TCP Congestion control
  *
- *   o  The sender keeps a separate congestion control parameter set for
- *      each of the destination addresses it can send to (not each
- *      source-destination pair but for each destination).  The parameters
- *      should decay if the address is not used for a long enough time
- *      period.
+ *   o	The sender keeps a separate congestion control parameter set for
+ *	each of the destination addresses it can send to (not each
+ *	source-destination pair but for each destination).  The parameters
+ *	should decay if the address is not used for a long enough time
+ *	period.
  *
  */
 struct sctp_transport {
@@ -657,12 +748,12 @@ struct sctp_transport {
 
 	/* Reference counting. */
 	atomic_t refcnt;
-	int      dead;
+	int	 dead;
 
 	/* This is the peer's IP address and port. */
 	union sctp_addr ipaddr;
 
-	/* These are the functions we call to handle LLP stuff.  */
+	/* These are the functions we call to handle LLP stuff.	 */
 	struct sctp_af *af_specific;
 
 	/* Which association do we belong to?  */
@@ -676,33 +767,33 @@ struct sctp_transport {
 	 * address list derived from the INIT or INIT ACK chunk, a
 	 * number of data elements needs to be maintained including:
 	 */
-	__u32 rtt;		/* This is the most recent RTT.  */
+	__u32 rtt;		/* This is the most recent RTT.	 */
 
-	/* RTO         : The current retransmission timeout value.  */
+	/* RTO	       : The current retransmission timeout value.  */
 	__u32 rto;
 
 	/* RTTVAR      : The current RTT variation.  */
 	__u32 rttvar;
 
-	/* SRTT        : The current smoothed round trip time.  */
+	/* SRTT	       : The current smoothed round trip time.	*/
 	__u32 srtt;
 
 	/* RTO-Pending : A flag used to track if one of the DATA
-	 *              chunks sent to this address is currently being
-	 *              used to compute a RTT. If this flag is 0,
-	 *              the next DATA chunk sent to this destination
-	 *              should be used to compute a RTT and this flag
-	 *              should be set. Every time the RTT
-	 *              calculation completes (i.e. the DATA chunk
-	 *              is SACK'd) clear this flag.
-         */
+	 *		chunks sent to this address is currently being
+	 *		used to compute a RTT. If this flag is 0,
+	 *		the next DATA chunk sent to this destination
+	 *		should be used to compute a RTT and this flag
+	 *		should be set. Every time the RTT
+	 *		calculation completes (i.e. the DATA chunk
+	 *		is SACK'd) clear this flag.
+	 */
 	int rto_pending;
 
 	/*
 	 * These are the congestion stats.
 	 */
-	/* cwnd        : The current congestion window.  */
-	__u32 cwnd;               /* This is the actual cwnd.  */
+	/* cwnd	       : The current congestion window.	 */
+	__u32 cwnd;		  /* This is the actual cwnd.  */
 
 	/* ssthresh    : The current slow start threshold value.  */
 	__u32 ssthresh;
@@ -715,7 +806,7 @@ struct sctp_transport {
 	/* Data that has been sent, but not acknowledged. */
 	__u32 flight_size;
 
-	/* PMTU       : The current known path MTU.  */
+	/* PMTU	      : The current known path MTU.  */
 	__u32 pmtu;
 
 	/* Destination */
@@ -745,23 +836,23 @@ struct sctp_transport {
 	unsigned long last_time_ecne_reduced;
 
 	/* active      : The current active state of this destination,
-	 *             :  i.e. DOWN, UP, etc.
+	 *	       :  i.e. DOWN, UP, etc.
 	 */
 	int active;
 
 	/* hb_allowed  : The current heartbeat state of this destination,
-	 *             :  i.e. ALLOW-HB, NO-HEARTBEAT, etc.
+	 *	       :  i.e. ALLOW-HB, NO-HEARTBEAT, etc.
 	 */
 	int hb_allowed;
 
 	/* These are the error stats for this destination.  */
 
-	/* Error count : The current error count for this destination.  */
+	/* Error count : The current error count for this destination.	*/
 	unsigned short error_count;
 
 	/* Error       : Current error threshold for this destination
 	 * Threshold   : i.e. what value marks the destination down if
-	 *             : errorCount reaches this value.
+	 *	       : errorCount reaches this value.
 	 */
 	unsigned short error_threshold;
 
@@ -771,10 +862,7 @@ struct sctp_transport {
 	 */
 	int max_retrans;
 
-	/* We use this name for debugging output... */
-	char *debug_name;
-
-	/* Per         : A timer used by each destination.
+	/* Per	       : A timer used by each destination.
 	 * Destination :
 	 * Timer       :
 	 *
@@ -799,6 +887,35 @@ struct sctp_transport {
 	struct list_head send_ready;
 
 	int malloced; /* Is this structure kfree()able? */
+
+	/* State information saved for SFR_CACC algorithm. The key
+	 * idea in SFR_CACC is to maintain state at the sender on a
+	 * per-destination basis when a changeover happens.
+	 *	char changeover_active;
+	 *	char cycling_changeover;
+	 *	__u32 next_tsn_at_change;
+	 *	char cacc_saw_newack;
+	 */
+	struct {
+		/* An unsigned integer, which stores the next TSN to be
+		 * used by the sender, at the moment of changeover.
+		 */
+		__u32 next_tsn_at_change;
+
+		/* A flag which indicates the occurrence of a changeover */
+		char changeover_active;
+
+		/* A glag which indicates whether the change of primary is
+		 * the first switch to this destination address during an
+		 * active switch.
+		 */
+		char cycling_changeover;
+
+		/* A temporary flag, which is used during the processing of
+		 * a SACK to estimate the causative TSN(s)'s group.
+		 */
+		char cacc_saw_newack;
+	} cacc;
 };
 
 struct sctp_transport *sctp_transport_new(const union sctp_addr *, int);
@@ -831,20 +948,20 @@ struct sctp_inq {
 	/* This is the packet which is currently off the in queue and is
 	 * being worked on through the inbound chunk processing.
 	 */
-	sctp_chunk_t *in_progress;
+	struct sctp_chunk *in_progress;
 
 	/* This is the delayed task to finish delivering inbound
 	 * messages.
 	 */
 	struct tq_struct immediate;
 
-	int malloced;        /* Is this structure kfree()able?  */
+	int malloced;	     /* Is this structure kfree()able?	*/
 };
 
 struct sctp_inq *sctp_inq_new(void);
 void sctp_inq_init(struct sctp_inq *);
 void sctp_inq_free(struct sctp_inq *);
-void sctp_inq_push(struct sctp_inq *, sctp_chunk_t *packet);
+void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
 struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
 void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
 
@@ -855,7 +972,7 @@ void sctp_inq_set_th_handler(struct sctp
  * This structure covers sections 6.3, 6.4, 6.7, 6.8, 6.10, 7., 8.1,
  * and 8.2 of the v13 draft.
  *
- * It handles retransmissions.  The connection to the timeout portion
+ * It handles retransmissions.	The connection to the timeout portion
  * of the state machine is through sctp_..._timeout() and timeout_handler.
  *
  * If you feed it SACKs, it will eat them.
@@ -901,23 +1018,26 @@ struct sctp_outq {
 	sctp_outq_ohandler_t	*build_output;
 	sctp_outq_ohandler_force_t	*force_output;
 
-	/* How many unackd bytes do we have in-flight?  */
+	/* How many unackd bytes do we have in-flight?	*/
 	__u32 outstanding_bytes;
 
+	/* Corked? */
+	char cork;
+
 	/* Is this structure empty?  */
-	int empty;
+	char empty;
 
 	/* Are we kfree()able? */
-	int malloced;
+	char malloced;
 };
 
 struct sctp_outq *sctp_outq_new(struct sctp_association *);
 void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
 void sctp_outq_teardown(struct sctp_outq *);
 void sctp_outq_free(struct sctp_outq*);
-int sctp_outq_tail(struct sctp_outq *, sctp_chunk_t *chunk);
+int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
 int sctp_outq_flush(struct sctp_outq *, int);
-int sctp_outq_sack(struct sctp_outq *, sctp_sackhdr_t *);
+int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
 int sctp_outq_is_empty(const struct sctp_outq *);
 int sctp_outq_set_output_handlers(struct sctp_outq *,
 				  sctp_outq_ohandler_init_t init,
@@ -926,18 +1046,24 @@ int sctp_outq_set_output_handlers(struct
 				  sctp_outq_ohandler_t build,
 				  sctp_outq_ohandler_force_t force);
 void sctp_outq_restart(struct sctp_outq *);
+
 void sctp_retransmit(struct sctp_outq *, struct sctp_transport *,
 		     sctp_retransmit_reason_t);
 void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8);
-
+int sctp_outq_uncork(struct sctp_outq *);
+/* Uncork and flush an outqueue.  */
+static inline void sctp_outq_cork(struct sctp_outq *q)
+{
+	q->cork = 1;
+}
 
 /* These bind address data fields common between endpoints and associations */
 struct sctp_bind_addr {
 
 	/* RFC 2960 12.1 Parameters necessary for the SCTP instance
 	 *
-	 * SCTP Port:   The local SCTP port number the endpoint is
-	 * 		bound to.
+	 * SCTP Port:	The local SCTP port number the endpoint is
+	 *		bound to.
 	 */
 	__u16 port;
 
@@ -949,19 +1075,24 @@ struct sctp_bind_addr {
 	 */
 	struct list_head address_list;
 
-	int malloced;        /* Are we kfree()able?  */
+	int malloced;	     /* Are we kfree()able?  */
 };
 
-sctp_bind_addr_t *sctp_bind_addr_new(int gfp_mask);
-void sctp_bind_addr_init(sctp_bind_addr_t *, __u16 port);
-void sctp_bind_addr_free(sctp_bind_addr_t *);
-int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
+struct sctp_bind_addr *sctp_bind_addr_new(int gfp_mask);
+void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
+void sctp_bind_addr_free(struct sctp_bind_addr *);
+int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+			const struct sctp_bind_addr *src,
 			sctp_scope_t scope, int gfp,int flags);
-int sctp_add_bind_addr(sctp_bind_addr_t *, union sctp_addr *,
+int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
 		       int gfp);
-int sctp_del_bind_addr(sctp_bind_addr_t *, union sctp_addr *);
-int sctp_bind_addr_match(sctp_bind_addr_t *, const union sctp_addr *,
+int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
+int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
 			 struct sctp_opt *);
+union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
+					const union sctp_addr	*addrs,
+					int			addrcnt,
+					struct sctp_opt		*opt);
 union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
 					 int *addrs_len, int gfp);
 int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
@@ -985,13 +1116,13 @@ typedef enum {
  * local endpoint.
  * This common structure is useful for several purposes:
  *   1) Common interface for lookup routines.
- *      a) Subfunctions work for either endpoint or association
- *      b) Single interface to lookup allows hiding the lookup lock rather
- *         than acquiring it externally.
+ *	a) Subfunctions work for either endpoint or association
+ *	b) Single interface to lookup allows hiding the lookup lock rather
+ *	   than acquiring it externally.
  *   2) Common interface for the inbound chunk handling/state machine.
  *   3) Common object handling routines for reference counting, etc.
  *   4) Disentangle association lookup from endpoint lookup, where we
- *      do not have to find our endpoint to find our association.
+ *	do not have to find our endpoint to find our association.
  *
  */
 
@@ -1010,21 +1141,21 @@ struct sctp_ep_common {
 	 *   malloced - Do we need to kfree this object?
 	 */
 	atomic_t    refcnt;
-	char        dead;
-	char        malloced;
+	char	    dead;
+	char	    malloced;
 
 	/* What socket does this endpoint belong to?  */
 	struct sock *sk;
 
 	/* This is where we receive inbound chunks.  */
-	struct sctp_inq   inqueue;
+	struct sctp_inq	  inqueue;
 
 	/* This substructure includes the defining parameters of the
 	 * endpoint:
 	 * bind_addr.port is our shared port number.
 	 * bind_addr.address_list is our set of local IP addresses.
 	 */
-	sctp_bind_addr_t bind_addr;
+	struct sctp_bind_addr bind_addr;
 
 	/* Protection during address list comparisons. */
 	rwlock_t   addr_lock;
@@ -1055,22 +1186,22 @@ struct sctp_endpoint {
 	struct sctp_ep_common base;
 
 	/* Associations: A list of current associations and mappings
-	 *            to the data consumers for each association. This
-	 *            may be in the form of a hash table or other
-	 *            implementation dependent structure. The data
-	 *            consumers may be process identification
-	 *            information such as file descriptors, named pipe
-	 *            pointer, or table pointers dependent on how SCTP
-	 *            is implemented.
+	 *	      to the data consumers for each association. This
+	 *	      may be in the form of a hash table or other
+	 *	      implementation dependent structure. The data
+	 *	      consumers may be process identification
+	 *	      information such as file descriptors, named pipe
+	 *	      pointer, or table pointers dependent on how SCTP
+	 *	      is implemented.
 	 */
 	/* This is really a list of struct sctp_association entries. */
 	struct list_head asocs;
 
 	/* Secret Key: A secret key used by this endpoint to compute
-	 *            the MAC.  This SHOULD be a cryptographic quality
-	 *            random number with a sufficient length.
+	 *	      the MAC.	This SHOULD be a cryptographic quality
+	 *	      random number with a sufficient length.
 	 *	      Discussion in [RFC1750] can be helpful in
-	 * 	      selection of the key.
+	 *	      selection of the key.
 	 */
 	__u8 secret_key[SCTP_HOW_MANY_SECRETS][SCTP_SECRET_SIZE];
 	int current_key;
@@ -1080,7 +1211,7 @@ struct sctp_endpoint {
 	/* Default timeouts.  */
 	int timeouts[SCTP_NUM_TIMEOUT_TYPES];
 
-	/* Various thresholds.  */
+	/* Various thresholds.	*/
 
 	/* Name for debugging output... */
 	char *debug_name;
@@ -1157,11 +1288,11 @@ struct sctp_association {
 	 */
 	__u32 eyecatcher;
 
-	/* This is our parent endpoint.  */
+	/* This is our parent endpoint.	 */
 	struct sctp_endpoint *ep;
 
 	/* These are those association elements needed in the cookie.  */
-	sctp_cookie_t c;
+	struct sctp_cookie c;
 
 	/* This is all information about our peer.  */
 	struct {
@@ -1173,11 +1304,11 @@ struct sctp_association {
 
 		/* transport_addr_list
 		 *
-		 * Peer        : A list of SCTP transport addresses that the
+		 * Peer	       : A list of SCTP transport addresses that the
 		 * Transport   : peer is bound to. This information is derived
 		 * Address     : from the INIT or INIT ACK and is used to
-		 * List        : associate an inbound packet with a given
-		 *             : association. Normally this information is
+		 * List	       : associate an inbound packet with a given
+		 *	       : association. Normally this information is
 		 *	       : hashed or keyed for quick lookup and access
 		 *	       : of the TCB.
 		 *
@@ -1193,8 +1324,8 @@ struct sctp_association {
 		/* primary_path
 		 *
 		 * Primary     : This is the current primary destination
-		 * Path        : transport address of the peer endpoint.  It
-		 *             : may also specify a source transport address
+		 * Path	       : transport address of the peer endpoint.  It
+		 *	       : may also specify a source transport address
 		 *	       : on this endpoint.
 		 *
 		 * All of these paths live on transport_addr_list.
@@ -1233,25 +1364,25 @@ struct sctp_association {
 		/* Pointer to last transport I have sent on.  */
 		struct sctp_transport *last_sent_to;
 
-		/* This is the last transport I have received DATA on.  */
+		/* This is the last transport I have received DATA on.	*/
 		struct sctp_transport *last_data_from;
 
 		/*
 		 * Mapping  An array of bits or bytes indicating which out of
 		 * Array    order TSN's have been received (relative to the
-		 *          Last Rcvd TSN). If no gaps exist, i.e. no out of
-		 *          order packets have been received, this array
-		 *          will be set to all zero. This structure may be
-		 *          in the form of a circular buffer or bit array.
+		 *	    Last Rcvd TSN). If no gaps exist, i.e. no out of
+		 *	    order packets have been received, this array
+		 *	    will be set to all zero. This structure may be
+		 *	    in the form of a circular buffer or bit array.
 		 *
 		 * Last Rcvd   : This is the last TSN received in
 		 * TSN	       : sequence. This value is set initially by
-		 *             : taking the peer's Initial TSN, received in
-		 *             : the INIT or INIT ACK chunk, and subtracting
-		 *             : one from it.
+		 *	       : taking the peer's Initial TSN, received in
+		 *	       : the INIT or INIT ACK chunk, and subtracting
+		 *	       : one from it.
 		 *
 		 * Throughout most of the specification this is called the
-		 * "Cumulative TSN ACK Point".  In this case, we
+		 * "Cumulative TSN ACK Point".	In this case, we
 		 * ignore the advice in 12.2 in favour of the term
 		 * used in the bulk of the text.  This value is hidden
 		 * in tsn_map--we get it by calling sctp_tsnmap_get_ctsn().
@@ -1260,39 +1391,47 @@ struct sctp_association {
 		__u8 _map[sctp_tsnmap_storage_size(SCTP_TSN_MAP_SIZE)];
 
 		/* Do we need to sack the peer? */
-		__u8    sack_needed;
+		__u8	sack_needed;
 		/* These are capabilities which our peer advertised.  */
-		__u8	ecn_capable;     /* Can peer do ECN? */
-		__u8	ipv4_address;    /* Peer understands IPv4 addresses? */
-		__u8	ipv6_address;    /* Peer understands IPv6 addresses? */
+		__u8	ecn_capable;	 /* Can peer do ECN? */
+		__u8	ipv4_address;	 /* Peer understands IPv4 addresses? */
+		__u8	ipv6_address;	 /* Peer understands IPv6 addresses? */
 		__u8	hostname_address;/* Peer understands DNS addresses? */
-		sctp_inithdr_t i;
+
+		/* Does peer support ADDIP? */
+		__u8    asconf_capable;
+
+		/* This mask is used to disable sending the ASCONF chunk
+		 * with specified parameter to peer.
+		 */
+		__u16 addip_disabled_mask;
+
+		struct sctp_inithdr i;
 		int cookie_len;
 		void *cookie;
 
-		/* ADDIP Extention (ADDIP)		--xguo */
-		/* <expected peer-serial-number> minus 1 (ADDIP sec. 4.2 C1) */
+		/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.
+		 * C1) ... "Peer-Serial-Number'. This value MUST be initialized to the
+		 * Initial TSN Value minus 1
+		 */
 		__u32 addip_serial;
 	} peer;
 
 	/* State       : A state variable indicating what state the
 	 *	       : association is in, i.e. COOKIE-WAIT,
-	 *             : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING,
-	 *             : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT.
+	 *	       : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING,
+	 *	       : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT.
 	 *
-	 *              Note: No "CLOSED" state is illustrated since if a
-	 *              association is "CLOSED" its TCB SHOULD be removed.
+	 *		Note: No "CLOSED" state is illustrated since if a
+	 *		association is "CLOSED" its TCB SHOULD be removed.
 	 *
-	 * 		In this implementation we DO have a CLOSED
+	 *		In this implementation we DO have a CLOSED
 	 *		state which is used during initiation and shutdown.
 	 *
-	 * 		State takes values from SCTP_STATE_*.
+	 *		State takes values from SCTP_STATE_*.
 	 */
 	sctp_state_t state;
 
-	/* When did we enter this state?  */
-	int state_timestamp;
-
 	/* The cookie life I award for any cookie.  */
 	struct timeval cookie_life;
 
@@ -1301,12 +1440,6 @@ struct sctp_association {
 	 */
 	int overall_error_count;
 
-	/* Overall     : The threshold for this association that if
-	 * Error       : the Overall Error Count reaches will cause
-	 * Threshold   : this association to be torn down.
-	 */
-	int overall_error_threshold;
-
 	/* These are the association's initial, max, and min RTO values.
 	 * These values will be initialized by system defaults, but can
 	 * be modified via the SCTP_RTOINFO socket option.
@@ -1333,7 +1466,6 @@ struct sctp_association {
 	/* The largest timeout or RTO value to use in attempting an INIT */
 	__u16 max_init_timeo;
 
-
 	int timeouts[SCTP_NUM_TIMEOUT_TYPES];
 	struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
 
@@ -1341,19 +1473,19 @@ struct sctp_association {
 	struct sctp_transport *shutdown_last_sent_to;
 
 	/* Next TSN    : The next TSN number to be assigned to a new
-	 *             : DATA chunk.  This is sent in the INIT or INIT
-	 *             : ACK chunk to the peer and incremented each
-	 *             : time a DATA chunk is assigned a TSN
-	 *             : (normally just prior to transmit or during
+	 *	       : DATA chunk.  This is sent in the INIT or INIT
+	 *	       : ACK chunk to the peer and incremented each
+	 *	       : time a DATA chunk is assigned a TSN
+	 *	       : (normally just prior to transmit or during
 	 *	       : fragmentation).
 	 */
 	__u32 next_tsn;
 
 	/*
 	 * Last Rcvd   : This is the last TSN received in sequence.  This value
-	 * TSN         : is set initially by taking the peer's Initial TSN,
-	 *             : received in the INIT or INIT ACK chunk, and
-	 *             : subtracting one from it.
+	 * TSN	       : is set initially by taking the peer's Initial TSN,
+	 *	       : received in the INIT or INIT ACK chunk, and
+	 *	       : subtracting one from it.
 	 *
 	 * Most of RFC 2960 refers to this as the Cumulative TSN Ack Point.
 	 */
@@ -1393,7 +1525,7 @@ struct sctp_association {
 	wait_queue_head_t	wait;
 
 	/* Association : The smallest PMTU discovered for all of the
-	 * PMTU        : peer's transport addresses.
+	 * PMTU	       : peer's transport addresses.
 	 */
 	__u32 pmtu;
 
@@ -1401,29 +1533,28 @@ struct sctp_association {
 	__u32 frag_point;
 
 	/* Ack State   : This flag indicates if the next received
-	 *             : packet is to be responded to with a
-	 *             : SACK. This is initializedto 0.  When a packet
-	 *             : is received it is incremented. If this value
-	 *             : reaches 2 or more, a SACK is sent and the
-	 *             : value is reset to 0. Note: This is used only
-	 *             : when no DATA chunks are received out of
-	 *	       : order.  When DATA chunks are out of order,
-	 *             : SACK's are not delayed (see Section 6).
+	 *	       : packet is to be responded to with a
+	 *	       : SACK. This is initializedto 0.	 When a packet
+	 *	       : is received it is incremented. If this value
+	 *	       : reaches 2 or more, a SACK is sent and the
+	 *	       : value is reset to 0. Note: This is used only
+	 *	       : when no DATA chunks are received out of
+	 *	       : order.	 When DATA chunks are out of order,
+	 *	       : SACK's are not delayed (see Section 6).
 	 */
 	/* Do we need to send an ack?
 	 * When counters[SctpCounterAckState] is above 1 we do!
 	 */
 	int counters[SCTP_NUMBER_COUNTERS];
 
-	struct {
-		__u16 stream;
-		__u16 flags;
-		__u32 ppid;
-		__u32 context;
-		__u32 timetolive;
-	} defaults;
+	/* Default send parameters. */
+	__u16 default_stream;
+	__u16 default_flags;
+	__u32 default_ppid;
+	__u32 default_context;
+	__u32 default_timetolive;
 
-	/* This tracks outbound ssn for a given stream.  */
+	/* This tracks outbound ssn for a given stream.	 */
 	struct sctp_ssnmap *ssnmap;
 
 	/* All outbound chunks go through this structure.  */
@@ -1434,13 +1565,10 @@ struct sctp_association {
 	 */
 	struct sctp_ulpq ulpq;
 
-	/* Need to send an ECNE Chunk? */
-	int need_ecne;
-
 	/* Last TSN that caused an ECNE Chunk to be sent.  */
 	__u32 last_ecne_tsn;
 
-	/* Last TSN that caused a CWR Chunk to be sent.  */
+	/* Last TSN that caused a CWR Chunk to be sent.	 */
 	__u32 last_cwr_tsn;
 
 	/* How many duplicated TSNs have we seen?  */
@@ -1449,9 +1577,6 @@ struct sctp_association {
 	/* Number of seconds of idle time before an association is closed.  */
 	__u32 autoclose;
 
-	/* Name for debugging output... */
-	char *debug_name;
-
 	/* These are to support
 	 * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses
 	 *  and Enforcement of Flow and Message Limits"
@@ -1459,8 +1584,7 @@ struct sctp_association {
 	 * or "ADDIP" for short.
 	 */
 
-	/* Is the ADDIP extension enabled for this association? */
-	int addip_enable;
+
 
 	/* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
 	 *
@@ -1476,7 +1600,7 @@ struct sctp_association {
 	 * [This is our one-and-only-one ASCONF in flight.  If we do
 	 * not have an ASCONF in flight, this is NULL.]
 	 */
-	sctp_chunk_t *addip_last_asconf;
+	struct sctp_chunk *addip_last_asconf;
 
 	/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.
 	 *
@@ -1491,7 +1615,7 @@ struct sctp_association {
 	 * [This is our saved ASCONF-ACK.  We invalidate it when a new
 	 * ASCONF serial number arrives.]
 	 */
-	sctp_chunk_t *addip_last_asconf_ack;
+	struct sctp_chunk *addip_last_asconf_ack;
 
 	/* These ASCONF chunks are waiting to be sent.
 	 *
@@ -1504,7 +1628,7 @@ struct sctp_association {
 	 *
 	 * In defining the ASCONF Chunk transfer procedures, it is
 	 * essential that these transfers MUST NOT cause congestion
-	 * within the network.  To achieve this, we place these
+	 * within the network.	To achieve this, we place these
 	 * restrictions on the transfer of ASCONF Chunks:
 	 *
 	 * R1) One and only one ASCONF Chunk MAY be in transit and
@@ -1518,20 +1642,20 @@ struct sctp_association {
 	 *
 	 *
 	 * [I really think this is EXACTLY the sort of intelligence
-	 *  which already resides in sctp_outq.  Please move this
-	 *  queue and its supporting logic down there.  --piggy]
+	 *  which already resides in sctp_outq.	 Please move this
+	 *  queue and its supporting logic down there.	--piggy]
 	 */
 	struct sk_buff_head addip_chunks;
 
 	/* ADDIP Section 4.1 ASCONF Chunk Procedures
 	 *
 	 * A2) A serial number should be assigned to the Chunk. The
-	 * serial number should be a monotonically increasing
-	 * number. All serial numbers are defined to be initialized at
+	 * serial number SHOULD be a monotonically increasing
+	 * number. The serial number SHOULD be initialized at
 	 * the start of the association to the same value as the
-	 * Initial TSN.
-	 *
-	 * [and]
+	 * Initial TSN and every time a new ASCONF chunk is created
+	 * it is incremented by one after assigning the serial number
+	 * to the newly created chunk.
 	 *
 	 * ADDIP
 	 * 3.1.1  Address/Stream Configuration Change Chunk (ASCONF)
@@ -1540,13 +1664,16 @@ struct sctp_association {
 	 *
 	 * This value represents a Serial Number for the ASCONF
 	 * Chunk. The valid range of Serial Number is from 0 to
-	 * 4294967295 (2**32 - 1).  Serial Numbers wrap back to 0
+	 * 4294967295 (2^32 - 1).  Serial Numbers wrap back to 0
 	 * after reaching 4294967295.
 	 */
 	__u32 addip_serial;
 
-	/* Is it a temporary association? */ 
-	__u8 temp;
+	/* Need to send an ECNE Chunk? */
+	char need_ecne;
+
+	/* Is it a temporary association? */
+	char temp;
 };
 
 
@@ -1566,7 +1693,7 @@ static inline struct sctp_association *s
 	return asoc;
 }
 
-/* These are function signatures for manipulating associations.  */
+/* These are function signatures for manipulating associations.	 */
 
 
 struct sctp_association *
@@ -1585,9 +1712,13 @@ struct sctp_transport *sctp_assoc_choose
 void sctp_assoc_update_retran_path(struct sctp_association *);
 struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *,
 					  const union sctp_addr *);
+int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
+			    const union sctp_addr *laddr);
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
 				     const union sctp_addr *address,
 				     const int gfp);
+void sctp_assoc_del_peer(struct sctp_association *asoc,
+			 const union sctp_addr *addr);
 void sctp_assoc_control_transport(struct sctp_association *,
 				  struct sctp_transport *,
 				  sctp_transport_cmd_t, sctp_sn_error_t);
@@ -1603,18 +1734,18 @@ __u32 sctp_association_get_next_tsn(stru
 __u32 sctp_association_get_tsn_block(struct sctp_association *, int);
 
 void sctp_assoc_sync_pmtu(struct sctp_association *);
-void sctp_assoc_rwnd_increase(struct sctp_association *, int);
-void sctp_assoc_rwnd_decrease(struct sctp_association *, int);
+void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned);
+void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned);
 void sctp_assoc_set_primary(struct sctp_association *,
 			    struct sctp_transport *);
 int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, int);
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
-					 sctp_cookie_t *, int gfp);
+					 struct sctp_cookie*, int gfp);
 
 int sctp_cmp_addr_exact(const union sctp_addr *ss1,
-		        const union sctp_addr *ss2);
-sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc);
-sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc);
+			const union sctp_addr *ss2);
+struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
+struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc);
 
 /* A convenience structure to parse out SCTP specific CMSGs. */
 typedef struct sctp_cmsgs {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/tsnmap.h linux-2.4.26-pre6/include/net/sctp/tsnmap.h
--- linux-2.4.25/include/net/sctp/tsnmap.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/tsnmap.h	2004-03-25 00:21:16.000000000 +0000
@@ -1,5 +1,8 @@
-/* SCTP kernel reference Implementation Copyright (C) 1999-2001
- * Cisco, Motorola, Intel, and International Business Machines Corp.
+/* SCTP kernel reference Implementation
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001-2003 International Business Machines, Corp.
+ * Copyright (c) 2001 Intel Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -97,13 +100,16 @@ struct sctp_tsnmap {
 	/* Data chunks pending receipt. used by SCTP_STATUS sockopt */
 	__u16 pending_data;
 
-	/* We record duplicate TSNs here.  We clear this after
+	/* Record duplicate TSNs here.  We clear this after
 	 * every SACK.  Store up to SCTP_MAX_DUP_TSNS worth of
 	 * information.
 	 */
 	__u32 dup_tsns[SCTP_MAX_DUP_TSNS];
 	__u16 num_dup_tsns;
 
+	/* Record gap ack block information here.  */
+	struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
+
 	int malloced;
 
 	__u8 raw_map[0];
@@ -140,12 +146,18 @@ int sctp_tsnmap_check(const struct sctp_
 void sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
 
 /* Retrieve the Cumulative TSN ACK Point.  */
-__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *);
+static inline __u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map)
+{
+	return map->cumulative_tsn_ack_point;
+}
 
 /* Retrieve the highest TSN we've seen.  */
-__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *);
+static inline __u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map)
+{
+	return map->max_tsn_seen;
+}
 
-/* How many Duplicate TSNs are stored? */
+/* How many duplicate TSNs are stored? */
 static inline __u16 sctp_tsnmap_num_dups(struct sctp_tsnmap *map)
 {
 	return map->num_dup_tsns;
@@ -158,6 +170,27 @@ static inline __u32 *sctp_tsnmap_get_dup
 	return map->dup_tsns;
 }
 
+/* How many gap ack blocks do we have recorded? */
+__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map);
+
+/* Refresh the count on pending data. */
+__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map);
+
+/* Return pointer to gap ack blocks as needed by SACK. */
+static inline struct sctp_gap_ack_block *sctp_tsnmap_get_gabs(struct sctp_tsnmap *map)
+{
+	return map->gabs;
+}
+
+/* Is there a gap in the TSN map?  */
+static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
+{
+	int has_gap;
+
+	has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen);
+	return has_gap;
+}
+
 /* Mark a duplicate TSN.  Note:  limit the storage of duplicate TSN
  * information.
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/ulpevent.h linux-2.4.26-pre6/include/net/sctp/ulpevent.h
--- linux-2.4.25/include/net/sctp/ulpevent.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/ulpevent.h	2004-03-25 00:22:07.000000000 +0000
@@ -40,6 +40,7 @@
  *   Jon Grimm             <jgrimm@us.ibm.com>
  *   La Monte H.P. Yarroll <piggy@acm.org>
  *   Karl Knutson          <karl@athena.chicago.il.us>
+ *   Sridhar Samudrala     <sri@us.ibm.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -48,8 +49,6 @@
 #ifndef __sctp_ulpevent_h__
 #define __sctp_ulpevent_h__
 
-#include <net/sctp/compat.h>
-
 /* A structure to carry information to the ULP (e.g. Sockets API) */
 /* Warning: This sits inside an skb.cb[] area.  Be very careful of
  * growing this structure as it is at the maximum limit now.
@@ -59,7 +58,6 @@ struct sctp_ulpevent {
 	int msg_flags;
 	int iif;
 };
-#define event_asoc sndrcvinfo.sinfo_assoc_id
 
 /* Retrieve the skb this event sits inside of. */
 static inline struct sk_buff *sctp_event2skb(struct sctp_ulpevent *ev)
@@ -74,9 +72,10 @@ static inline struct sctp_ulpevent *sctp
 }
 
 struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp);
-struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
+void sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
 void sctp_ulpevent_free(struct sctp_ulpevent *);
 int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
+void sctp_queue_purge_ulpevents(struct sk_buff_head *list);
 
 struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
 	const struct sctp_association *asoc,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/user.h linux-2.4.26-pre6/include/net/sctp/user.h
--- linux-2.4.25/include/net/sctp/user.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sctp/user.h	2004-03-25 00:19:32.000000000 +0000
@@ -1,38 +1,39 @@
 /* SCTP kernel reference Implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001 International Business Machines, Corp.
- * 
+ * Copyright (c) 2001-2003 International Business Machines, Corp.
+ * Copyright (c) 2002 Intel Corp.
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
+ *
  * This header represents the structures and constants needed to support
- * the SCTP Extension to the Sockets API. 
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ * the SCTP Extension to the Sockets API.
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
  * the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
  *                 ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
+ * Written or modified by:
  *    La Monte H.P. Yarroll    <piggy@acm.org>
  *    R. Stewart               <randall@sctp.chicago.il.us>
  *    K. Morneau               <kmorneau@cisco.com>
@@ -40,61 +41,63 @@
  *    Karl Knutson             <karl@athena.chicago.il.us>
  *    Jon Grimm                <jgrimm@us.ibm.com>
  *    Daisy Chang              <daisyc@us.ibm.com>
- * 
- * 
+ *    Ryan Layer               <rmlayer@us.ibm.com>
+ *    Ardelle Fan	       <ardelle.fan@intel.com>
+ *    Sridhar Samudrala        <sri@us.ibm.com>
+ *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
-#include <linux/types.h>
-#include <linux/socket.h>
 
 #ifndef __net_sctp_user_h__
 #define __net_sctp_user_h__
 
-struct sctp_association;
-typedef struct sctp_association * sctp_assoc_t;
+#include <linux/types.h>
+#include <linux/socket.h>
+
+typedef void * sctp_assoc_t;
 
 /* The following symbols come from the Sockets API Extensions for
- * SCTP <draft-ietf-tsvwg-sctpsocket-04.txt>.
+ * SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
  */
 enum sctp_optname {
 	SCTP_RTOINFO,
 #define SCTP_RTOINFO SCTP_RTOINFO
-	SCTP_ASSOCRTXINFO,
-#define SCTP_ASSOCRTXINFO SCTP_ASSOCRTXINFO
+	SCTP_ASSOCINFO,
+#define SCTP_ASSOCINFO SCTP_ASSOCINFO
 	SCTP_INITMSG,
 #define SCTP_INITMSG SCTP_INITMSG
-	SCTP_AUTO_CLOSE,
-#define SCTP_AUTO_CLOSE SCTP_AUTO_CLOSE
-	SCTP_SET_PRIMARY_ADDR,
-#define SCTP_SET_PRIMARY_ADDR SCTP_SET_PRIMARY_ADDR
+	SCTP_NODELAY, 	/* Get/set nodelay option. */
+#define SCTP_NODELAY	SCTP_NODELAY
+	SCTP_AUTOCLOSE,
+#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE
 	SCTP_SET_PEER_PRIMARY_ADDR, 
 #define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR
-	SCTP_SET_ADAPTATION_LAYER,      
-#define SCTP_SET_ADAPTATION_LAYER SCTP_SET_ADAPTATION_LAYER
-	SCTP_SET_STREAM_TIMEOUTS,
-#define SCTP_SET_STREAM_TIMEOUTS SCTP_SET_STREAM_TIMEOUTS
+	SCTP_PRIMARY_ADDR,
+#define SCTP_PRIMARY_ADDR SCTP_PRIMARY_ADDR
+	SCTP_ADAPTION_LAYER,      
+#define SCTP_ADAPTION_LAYER SCTP_ADAPTION_LAYER
 	SCTP_DISABLE_FRAGMENTS,
 #define SCTP_DISABLE_FRAGMENTS SCTP_DISABLE_FRAGMENTS
-	SCTP_SET_PEER_ADDR_PARAMS,
-#define SCTP_SET_PEER_ADDR_PARAMS SCTP_SET_PEER_ADDR_PARAMS
-	SCTP_GET_PEER_ADDR_PARAMS,
-#define SCTP_GET_PEER_ADDR_PARAMS SCTP_GET_PEER_ADDR_PARAMS
+	SCTP_PEER_ADDR_PARAMS,
+#define SCTP_PEER_ADDR_PARAMS SCTP_PEER_ADDR_PARAMS
+	SCTP_DEFAULT_SEND_PARAM,
+#define SCTP_DEFAULT_SEND_PARAM SCTP_DEFAULT_SEND_PARAM
+	SCTP_EVENTS,
+#define SCTP_EVENTS SCTP_EVENTS
+	SCTP_I_WANT_MAPPED_V4_ADDR,  /* Turn on/off mapped v4 addresses  */
+#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR
+	SCTP_MAXSEG, 	/* Get/set maximum fragment. */
+#define SCTP_MAXSEG 	SCTP_MAXSEG
 	SCTP_STATUS,
 #define SCTP_STATUS SCTP_STATUS
 	SCTP_GET_PEER_ADDR_INFO,
 #define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
-	SCTP_SET_EVENTS,
-#define SCTP_SET_EVENTS SCTP_SET_EVENTS
-	SCTP_AUTOCLOSE,
-#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE
-	SCTP_SET_DEFAULT_SEND_PARAM,
-#define SCTP_SET_DEFAULT_SEND_PARAM SCTP_SET_DEFAULT_SEND_PARAM
 
-	SCTP_SOCKOPT_DEBUG_NAME = 42, /* FIXME */
-#define SCTP_SOCKOPT_DEBUG_NAME	SCTP_SOCKOPT_DEBUG_NAME
-
-	SCTP_SOCKOPT_BINDX_ADD, /* BINDX requests for adding addresses. */
+	/* Internal Socket Options. Some of the sctp library functions are 
+	 * implemented using these socket options.
+	 */
+	SCTP_SOCKOPT_BINDX_ADD = 100,/* BINDX requests for adding addresses. */
 #define SCTP_SOCKOPT_BINDX_ADD	SCTP_SOCKOPT_BINDX_ADD
 	SCTP_SOCKOPT_BINDX_REM, /* BINDX requests for removing addresses. */
 #define SCTP_SOCKOPT_BINDX_REM	SCTP_SOCKOPT_BINDX_REM
@@ -108,25 +111,8 @@ enum sctp_optname {
 #define SCTP_GET_LOCAL_ADDRS_NUM	SCTP_GET_LOCAL_ADDRS_NUM
 	SCTP_GET_LOCAL_ADDRS, 	/* Get all local addresss. */
 #define SCTP_GET_LOCAL_ADDRS	SCTP_GET_LOCAL_ADDRS
-	SCTP_NODELAY, 	/* Get/set nodelay option. */
-#define SCTP_NODELAY	SCTP_NODELAY
 };
 
-
-/*
- * 5.2 SCTP msg_control Structures
- *
- * A key element of all SCTP-specific socket extensions is the use of
- * ancillary data to specify and access SCTP-specific data via the
- * struct msghdr's msg_control member used in sendmsg() and recvmsg().
- * Fine-grained control over initialization and sending parameters are
- * handled with ancillary data.
- *
- * Each ancillary data item is preceeded by a struct cmsghdr (see
- * Section 5.1), which defines the function and purpose of the data
- * contained in in the cmsg_data[] member.
- */
-
 /*
  * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
  *
@@ -147,7 +133,6 @@ struct sctp_initmsg {
 	__u16 sinit_max_init_timeo;
 };
 
-
 /*
  * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
  *
@@ -209,7 +194,6 @@ typedef enum sctp_cmsg_type {
  *   following format:
  *
  */
-
 struct sctp_assoc_change {
 	__u16 sac_type;
 	__u16 sac_flags;
@@ -262,11 +246,11 @@ struct sctp_paddr_change {
  *   event that happened to the address.  They include:
  */
 enum sctp_spc_state {
-	ADDRESS_AVAILABLE,
-	ADDRESS_UNREACHABLE,
-	ADDRESS_REMOVED,
-	ADDRESS_ADDED,
-	ADDRESS_MADE_PRIM,
+	SCTP_ADDR_REACHABLE,
+	SCTP_ADDR_UNREACHABLE,
+	SCTP_ADDR_REMOVED,
+	SCTP_ADDR_ADDED,
+	SCTP_ADDR_MADE_PRIM,
 };
 
 
@@ -285,7 +269,6 @@ struct sctp_remote_error {
 	__u16 sre_flags;
 	__u32 sre_length;
 	__u16 sre_error;
-	__u16 sre_len;
 	sctp_assoc_t sre_assoc_id;
 	__u8 sre_data[0];
 };
@@ -319,7 +302,6 @@ struct sctp_send_failed {
  *                       Note that this does not necessarily mean that the
  *                       data was (or was not) successfully delivered.
  */
-
 enum sctp_ssf_flags {
 	SCTP_DATA_UNSENT,
 	SCTP_DATA_SENT,
@@ -331,7 +313,6 @@ enum sctp_ssf_flags {
  *   When a peer sends a SHUTDOWN, SCTP delivers this notification to
  *   inform the application that it should cease sending data.
  */
-
 struct sctp_shutdown_event {
 	__u16 sse_type;
 	__u16 sse_flags;
@@ -350,8 +331,8 @@ struct sctp_adaption_event {
 	__u16 sai_type;
 	__u16 sai_flags;
 	__u32 sai_length;
-	__u32 sai_adaptation_bits;
-	sctp_assoc_t sse_assoc_id;
+	__u32 sai_adaption_ind;
+	sctp_assoc_t sai_assoc_id;
 };
 
 /*
@@ -361,8 +342,7 @@ struct sctp_adaption_event {
  *   message this notification will be used to inidicate
  *   various events.
  */
-
-struct sctp_rcv_pdapi_event {
+struct sctp_pdapi_event {
 	__u16 pdapi_type;
 	__u16 pdapi_flags;
 	__u32 pdapi_length;
@@ -399,14 +379,14 @@ union sctp_notification {
 		__u16 sn_type;             /* Notification type. */
 		__u16 sn_flags;
 		__u32 sn_length;
-	} h;
+	} sn_header;
 	struct sctp_assoc_change sn_assoc_change;
-	struct sctp_paddr_change sn_padr_change;
+	struct sctp_paddr_change sn_paddr_change;
 	struct sctp_remote_error sn_remote_error;
 	struct sctp_send_failed sn_send_failed;
 	struct sctp_shutdown_event sn_shutdown_event;
 	struct sctp_adaption_event sn_adaption_event;
-	struct sctp_rcv_pdapi_event sn_rcv_pdapi_event;
+	struct sctp_pdapi_event sn_pdapi_event;
 };
 
 /* Section 5.3.1
@@ -443,102 +423,110 @@ typedef enum sctp_sn_error {
 } sctp_sn_error_t;
 
 /*
- *
- * 7.1.14 Peer Address Parameters
- *
- *   Applications can enable or disable heartbeats for any peer address
- *   of an association, modify an address's heartbeat interval, force a
- *   heartbeat to be sent immediately, and adjust the address's maximum
- *   number of retransmissions sent before an address is considered
- *   unreachable. The following structure is used to access and modify an
- *   address's parameters:
- */
-
-struct sctp_paddrparams {
-	struct sockaddr_storage	spp_address;
-	__u32			spp_hbinterval;
-	__u16			spp_pathmaxrxt;
-	sctp_assoc_t		spp_assoc_id;
-};
-
-/*
- * 7.2.2 Peer Address Information
- *
- *   Applications can retrieve information about a specific peer address
- *   of an association, including its reachability state, congestion
- *   window, and retransmission timer values.  This information is
- *   read-only. The following structure is used to access this
- *   information:
- */
-
-struct sctp_paddrinfo {
-	sctp_assoc_t		spinfo_assoc_id;
-	struct sockaddr_storage	spinfo_address;
-	__s32			spinfo_state;
-	__u32			spinfo_cwnd;
-	__u32			spinfo_srtt;
-	__u32			spinfo_rto;
-	__u32			spinfo_mtu;
-};
-
-
-/*
  * 7.1.1 Retransmission Timeout Parameters (SCTP_RTOINFO)
  *
  *   The protocol parameters used to initialize and bound retransmission
  *   timeout (RTO) are tunable.  See [SCTP] for more information on how
- *   these parameters are used in RTO calculation.  The peer address
- *   parameter is ignored for TCP style socket.
+ *   these parameters are used in RTO calculation. 
  */
-
 struct sctp_rtoinfo {
+	sctp_assoc_t	srto_assoc_id;
 	__u32		srto_initial;
 	__u32		srto_max;
 	__u32		srto_min;
-	sctp_assoc_t	srto_assoc_id;
 };
 
 /*
- * 7.1.2 Association Retransmission Parameter (SCTP_ASSOCRTXINFO)
+ * 7.1.2 Association Parameters (SCTP_ASSOCINFO)
  *
- *   The protocol parameter used to set the number of retransmissions
- *   sent before an association is considered unreachable.
- *   See [SCTP] for more information on how this parameter is used.  The
- *   peer address parameter is ignored for TCP style socket.
+ *   This option is used to both examine and set various association and
+ *   endpoint parameters.
  */
-
 struct sctp_assocparams {
-	__u16		sasoc_asocmaxrxt;
 	sctp_assoc_t	sasoc_assoc_id;
+	__u16		sasoc_asocmaxrxt;
+	__u16		sasoc_number_peer_destinations;
+	__u32		sasoc_peer_rwnd;
+	__u32		sasoc_local_rwnd;
+	__u32		sasoc_cookie_life;
 };
 
-
 /*
- * 7.1.9 Set Primary Address (SCTP_SET_PRIMARY_ADDR)
+ * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
  *
  *  Requests that the peer mark the enclosed address as the association
  *  primary. The enclosed address must be one of the association's
  *  locally bound addresses. The following structure is used to make a
  *   set primary request:
  */
-
-struct sctp_setprim {
-	struct sockaddr_storage ssp_addr;
-	sctp_assoc_t            ssp_assoc_id;
+struct sctp_setpeerprim {
+	sctp_assoc_t            sspp_assoc_id;
+	struct sockaddr_storage sspp_addr;
 };
 
 /*
- * 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
+ * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
  *
  *  Requests that the local SCTP stack use the enclosed peer address as
  *  the association primary. The enclosed address must be one of the
  *  association peer's addresses. The following structure is used to
  *  make a set peer primary request:
  */
+struct sctp_prim {
+	sctp_assoc_t            ssp_assoc_id;
+	struct sockaddr_storage ssp_addr;
+};
 
-struct sctp_setpeerprim {
-	struct sockaddr_storage sspp_addr;
-	sctp_assoc_t            sspp_assoc_id;
+/*
+ * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
+ *
+ * Requests that the local endpoint set the specified Adaption Layer
+ * Indication parameter for all future INIT and INIT-ACK exchanges.
+ */
+struct sctp_setadaption {
+	__u32	ssb_adaption_ind;
+};
+
+/*
+ * 7.1.13 Peer Address Parameters  (SCTP_PEER_ADDR_PARAMS)
+ *
+ *   Applications can enable or disable heartbeats for any peer address
+ *   of an association, modify an address's heartbeat interval, force a
+ *   heartbeat to be sent immediately, and adjust the address's maximum
+ *   number of retransmissions sent before an address is considered
+ *   unreachable. The following structure is used to access and modify an
+ *   address's parameters:
+ */
+struct sctp_paddrparams {
+	sctp_assoc_t		spp_assoc_id;
+	struct sockaddr_storage	spp_address;
+	__u32			spp_hbinterval;
+	__u16			spp_pathmaxrxt;
+};
+
+/*
+ * 7.2.2 Peer Address Information
+ *
+ *   Applications can retrieve information about a specific peer address
+ *   of an association, including its reachability state, congestion
+ *   window, and retransmission timer values.  This information is
+ *   read-only. The following structure is used to access this
+ *   information:
+ */
+struct sctp_paddrinfo {
+	sctp_assoc_t		spinfo_assoc_id;
+	struct sockaddr_storage	spinfo_address;
+	__s32			spinfo_state;
+	__u32			spinfo_cwnd;
+	__u32			spinfo_srtt;
+	__u32			spinfo_rto;
+	__u32			spinfo_mtu;
+};
+
+/* Peer addresses's state. */
+enum sctp_spinfo_state {
+	SCTP_INACTIVE,
+	SCTP_ACTIVE,
 };
 
 /*
@@ -562,40 +550,16 @@ struct sctp_status {
 	struct sctp_paddrinfo	sstat_primary;
 };
 
-
 /*
- * 7.1.12 Set Adaption Layer Indicator
- *
- * Requests that the local endpoint set the specified Adaption Layer
- * Indication parameter for all future
- *  INIT and INIT-ACK exchanges.
- */
-
-struct sctp_setadaption {
-	__u32	ssb_adaption_ind;
-};
-
-/*
- * 7.1.12 Set default message time outs (SCTP_SET_STREAM_TIMEOUTS)
- *
- * This option requests that the requested stream apply a
- *  default time-out for messages in queue.
- */
-struct sctp_setstrm_timeout   {
-	sctp_assoc_t	ssto_assoc_id;
-	__u32		ssto_timeout;
-	__u16		ssto_streamid_start;
-	__u16		ssto_streamid_end;
-};
-
-/*
- * 8.3 8.5 get all peer/local addresses on a socket
- * This parameter struct is for getsockopt
+ * 8.3, 8.5 get all peer/local addresses in an association.
+ * This parameter struct is used by SCTP_GET_PEER_ADDRS and 
+ * SCTP_GET_LOCAL_ADDRS socket options used internally to implement
+ * sctp_getpaddrs() and sctp_getladdrs() API. 
  */
 struct sctp_getaddrs {
 	sctp_assoc_t            assoc_id;
 	int			addr_num;
-	struct sockaddr_storage *addrs;
+	struct sockaddr		*addrs;
 };
 
 /* These are bit fields for msghdr->msg_flags.  See section 5.1.  */
@@ -611,8 +575,8 @@ enum sctp_msg_flags {
  * The flags parameter is formed from the bitwise OR of zero or more of the
  * following currently defined flags:
  */
-#define BINDX_ADD_ADDR 0x01
-#define BINDX_REM_ADDR 0x02
+#define SCTP_BINDX_ADD_ADDR 0x01
+#define SCTP_BINDX_REM_ADDR 0x02
 
 /* This is the structure that is passed as an argument(optval) to
  * getsockopt(SCTP_SOCKOPT_PEELOFF).
@@ -623,6 +587,3 @@ typedef struct {
 } sctp_peeloff_arg_t;
 
 #endif /* __net_sctp_user_h__ */
-
-
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sock.h linux-2.4.26-pre6/include/net/sock.h
--- linux-2.4.25/include/net/sock.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/include/net/sock.h	2004-03-25 00:21:03.000000000 +0000
@@ -432,6 +432,19 @@ struct tcp_opt {
 	__u32                   frto_highmark; /* snd_nxt when RTO occurred */
 
 	unsigned long last_synq_overflow; 
+
+/* TCP Westwood structure */
+        struct {
+                __u32    bw_ns_est;        /* first bandwidth estimation..not too smoothed 8) */
+                __u32    bw_est;           /* bandwidth estimate */
+                __u32    rtt_win_sx;       /* here starts a new evaluation... */
+                __u32    bk;
+                __u32    snd_una;          /* used for evaluating the number of acked bytes */
+                __u32    cumul_ack;
+                __u32    accounted;
+                __u32    rtt;
+                __u32    rtt_min;          /* minimum observed RTT */
+        } westwood;
 };
 
  	
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/tcp.h linux-2.4.26-pre6/include/net/tcp.h
--- linux-2.4.25/include/net/tcp.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/include/net/tcp.h	2004-03-25 00:17:35.000000000 +0000
@@ -463,6 +463,7 @@ extern int sysctl_tcp_adv_win_scale;
 extern int sysctl_tcp_tw_reuse;
 extern int sysctl_tcp_frto;
 extern int sysctl_tcp_low_latency;
+extern int sysctl_tcp_westwood;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -1863,4 +1864,121 @@ static inline void tcp_mib_init(void)
 	TCP_ADD_STATS_USER(TcpMaxConn, -1);
 }
 
+
+/* TCP Westwood functions and constants */
+
+#define TCP_WESTWOOD_INIT_RTT               20*HZ           /* maybe too conservative?! */
+#define TCP_WESTWOOD_RTT_MIN                HZ/20           /* 50ms */
+
+static inline void tcp_westwood_update_rtt(struct tcp_opt *tp, __u32 rtt_seq)
+{
+	if (sysctl_tcp_westwood)
+		tp->westwood.rtt = rtt_seq;
+}
+
+void __tcp_westwood_fast_bw(struct sock *, struct sk_buff *);
+void __tcp_westwood_slow_bw(struct sock *, struct sk_buff *);
+
+/*
+ * This function initializes fields used in TCP Westwood+. We can't
+ * get no information about RTTmin at this time so we simply set it to
+ * TCP_WESTWOOD_INIT_RTT. This value was chosen to be too conservative
+ * since in this way we're sure it will be updated in a consistent
+ * way as soon as possible. It will reasonably happen within the first
+ * RTT period of the connection lifetime.
+ */
+
+static inline void __tcp_init_westwood(struct sock *sk)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	tp->westwood.bw_ns_est = 0;
+	tp->westwood.bw_est = 0;
+	tp->westwood.accounted = 0;
+	tp->westwood.cumul_ack = 0;
+	tp->westwood.rtt_win_sx = tcp_time_stamp;
+	tp->westwood.rtt = TCP_WESTWOOD_INIT_RTT;
+	tp->westwood.rtt_min = TCP_WESTWOOD_INIT_RTT;
+	tp->westwood.snd_una = tp->snd_una;
+}
+
+static inline void tcp_init_westwood(struct sock *sk)
+{
+	__tcp_init_westwood(sk);
+}
+
+static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
+{
+	if (sysctl_tcp_westwood)
+		__tcp_westwood_fast_bw(sk, skb);
+}
+
+static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
+{
+	if (sysctl_tcp_westwood)
+		__tcp_westwood_slow_bw(sk, skb);
+}
+
+static inline __u32 __tcp_westwood_bw_rttmin(struct tcp_opt *tp)
+{
+	return (__u32) ((tp->westwood.bw_est) * (tp->westwood.rtt_min) /
+			(__u32) (tp->mss_cache));
+}
+
+static inline __u32 tcp_westwood_bw_rttmin(struct tcp_opt *tp)
+{
+	__u32 ret = 0;
+
+	if (sysctl_tcp_westwood)
+		ret = (__u32) (max(__tcp_westwood_bw_rttmin(tp), 2U));
+
+	return ret;
+}
+
+static inline int tcp_westwood_ssthresh(struct tcp_opt *tp)
+{
+	int ret = 0;
+	__u32 ssthresh;
+
+	if (sysctl_tcp_westwood) {
+		if (!(ssthresh = tcp_westwood_bw_rttmin(tp)))
+			return ret;
+
+		tp->snd_ssthresh = ssthresh;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static inline int tcp_westwood_cwnd(struct tcp_opt *tp)
+{
+	int ret = 0;
+	__u32 cwnd;
+
+	if (sysctl_tcp_westwood) {
+		if (!(cwnd = tcp_westwood_bw_rttmin(tp)))
+			return ret;
+
+		tp->snd_cwnd = cwnd;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static inline int tcp_westwood_complete_cwr(struct tcp_opt *tp) 
+{
+	int ret = 0;
+
+	if (sysctl_tcp_westwood) {
+		if (tcp_westwood_cwnd(tp)) {
+			tp->snd_ssthresh = tp->snd_cwnd;
+			ret = 1;
+		}
+	}
+
+	return ret;
+}
+
 #endif	/* _TCP_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/lib/Makefile linux-2.4.26-pre6/lib/Makefile
--- linux-2.4.25/lib/Makefile	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/lib/Makefile	2004-03-25 00:17:18.000000000 +0000
@@ -42,7 +42,7 @@ include $(TOPDIR)/Rules.make
 crc32.o: crc32table.h
 
 gen_crc32table: gen_crc32table.c
-	$(HOSTCC) $(HOSTCCFLAGS) -o $@ $<
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
 crc32table.h: gen_crc32table
 	./$< > $@
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/lib/crc32.c linux-2.4.26-pre6/lib/crc32.c
--- linux-2.4.25/lib/crc32.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/lib/crc32.c	2004-03-25 00:16:52.000000000 +0000
@@ -1,6 +1,9 @@
-/* 
+/*
  * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
  * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
+ * Code was from the public domain, copyright abandoned.  Code was
+ * subsequently included in the kernel, thus was re-licensed under the
+ * GNU GPL v2.
  *
  * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
  * Same crc32 function was used in 5 other places in the kernel.
@@ -12,7 +15,9 @@
  *   drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
  *   fs/jffs2 uses seed 0, doesn't xor with ~0.
  *   fs/partitions/efi.c uses seed ~0, xor's with ~0.
- * 
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
  */
 
 #include <linux/crc32.h>
@@ -39,16 +44,10 @@
 #define attribute(x)
 #endif
 
-/*
- * This code is in the public domain; copyright abandoned.
- * Liability for non-performance of this code is limited to the amount
- * you paid for it.  Since it is distributed for free, your refund will
- * be very very small.  If it breaks, you get to keep both pieces.
- */
 
 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>");
 MODULE_DESCRIPTION("Ethernet CRC32 calculations");
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
 
 #if CRC_LE_BITS == 1
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/mm/filemap.c linux-2.4.26-pre6/mm/filemap.c
--- linux-2.4.25/mm/filemap.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/mm/filemap.c	2004-03-25 00:18:54.000000000 +0000
@@ -1346,7 +1346,7 @@ static void generic_file_readahead(int r
 	while (ahead < max_ahead) {
 		unsigned long ra_index = raend + ahead + 1;
 
-		if (ra_index > end_index)
+		if (ra_index >= end_index)
 			break;
 		if (page_cache_read(filp, ra_index) < 0)
 			break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/mm/mremap.c linux-2.4.26-pre6/mm/mremap.c
--- linux-2.4.25/mm/mremap.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/mm/mremap.c	2004-03-25 00:20:14.000000000 +0000
@@ -77,12 +77,16 @@ static inline int copy_one_pte(struct mm
 static int move_one_page(struct mm_struct *mm, unsigned long old_addr, unsigned long new_addr)
 {
 	int error = 0;
-	pte_t * src;
+	pte_t * src, * dst;
 
 	spin_lock(&mm->page_table_lock);
 	src = get_one_pte(mm, old_addr);
-	if (src)
-		error = copy_one_pte(mm, src, alloc_one_pte(mm, new_addr));
+	if (src) {
+		dst = alloc_one_pte(mm, new_addr);
+		src = get_one_pte(mm, old_addr);
+		if (src) 
+			error = copy_one_pte(mm, src, dst);
+	}
 	spin_unlock(&mm->page_table_lock);
 	return error;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/mm/vmalloc.c linux-2.4.26-pre6/mm/vmalloc.c
--- linux-2.4.25/mm/vmalloc.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/mm/vmalloc.c	2004-03-25 00:20:20.000000000 +0000
@@ -159,8 +159,8 @@ static inline int __vmalloc_area_pages (
 					struct page ***pages)
 {
 	pgd_t * dir;
+	unsigned long start = address;
 	unsigned long end = address + size;
-	int ret;
 
 	dir = pgd_offset_k(address);
 	spin_lock(&init_mm.page_table_lock);
@@ -168,22 +168,24 @@ static inline int __vmalloc_area_pages (
 		pmd_t *pmd;
 		
 		pmd = pmd_alloc(&init_mm, dir, address);
-		ret = -ENOMEM;
 		if (!pmd)
-			break;
+			goto err;
 
-		ret = -ENOMEM;
 		if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot, pages))
-			break;
+			goto err;	// The kernel NEVER reclaims pmds, so no need to undo pmd_alloc() here
 
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
-
-		ret = 0;
 	} while (address && (address < end));
 	spin_unlock(&init_mm.page_table_lock);
 	flush_cache_all();
-	return ret;
+	return 0;
+err:
+	spin_unlock(&init_mm.page_table_lock);
+	flush_cache_all();
+	if (address > start)
+		vmfree_area_pages(start, address - start);
+	return -ENOMEM;
 }
 
 int vmalloc_area_pages(unsigned long address, unsigned long size,
@@ -234,7 +236,7 @@ out:
 	return NULL;
 }
 
-void vfree(void * addr)
+void __vfree(void * addr, int free_area_pages)
 {
 	struct vm_struct **p, *tmp;
 
@@ -248,7 +250,8 @@ void vfree(void * addr)
 	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
 			*p = tmp->next;
-			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+			if (free_area_pages)
+				vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
 			write_unlock(&vmlist_lock);
 			kfree(tmp);
 			return;
@@ -258,6 +261,11 @@ void vfree(void * addr)
 	printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr);
 }
 
+void vfree(void * addr)
+{
+	__vfree(addr,1);
+}
+
 void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot)
 {
 	void * addr;
@@ -272,7 +280,7 @@ void * __vmalloc (unsigned long size, in
 	addr = area->addr;
 	if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask,
 				 prot, NULL)) {
-		vfree(addr);
+		__vfree(addr, 0);
 		return NULL;
 	}
 	return addr;
@@ -294,7 +302,7 @@ void * vmap(struct page **pages, int cou
 	addr = area->addr;
 	if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, 0,
 				 prot, &pages)) {
-		vfree(addr);
+		__vfree(addr, 0);
 		return NULL;
 	}
 	return addr;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/8021q/vlan_dev.c linux-2.4.26-pre6/net/8021q/vlan_dev.c
--- linux-2.4.25/net/8021q/vlan_dev.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/8021q/vlan_dev.c	2004-03-25 00:21:58.000000000 +0000
@@ -446,6 +446,7 @@ int vlan_dev_hard_start_xmit(struct sk_b
 	 */
 
 	if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) {
+		int orig_headroom = skb_headroom(skb);
 		unsigned short veth_TCI;
 
 		/* This is not a VLAN frame...but we can fix that! */
@@ -455,33 +456,7 @@ int vlan_dev_hard_start_xmit(struct sk_b
 		printk(VLAN_DBG "%s: proto to encap: 0x%hx (hbo)\n",
 			__FUNCTION__, htons(veth->h_vlan_proto));
 #endif
-
-		if (skb_headroom(skb) < VLAN_HLEN) {
-			struct sk_buff *sk_tmp = skb;
-			skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
-			kfree_skb(sk_tmp);
-			if (skb == NULL) {
-				stats->tx_dropped++;
-				return 0;
-			}
-			VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++;
-		} else {
-			if (!(skb = skb_unshare(skb, GFP_ATOMIC))) {
-				printk(KERN_ERR "vlan: failed to unshare skbuff\n");
-				stats->tx_dropped++;
-				return 0;
-			}
-		}
-		veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
-
-		/* Move the mac addresses to the beginning of the new header. */
-		memmove(skb->data, skb->data + VLAN_HLEN, 12);
-
-		/* first, the ethernet type */
-		/* put_unaligned(__constant_htons(ETH_P_8021Q), &veth->h_vlan_proto); */
-		veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
-
-		/* Now, construct the second two bytes. This field looks something
+		/* Construct the second two bytes. This field looks something
 		 * like:
 		 * usr_priority: 3 bits	 (high bits)
 		 * CFI		 1 bit
@@ -490,10 +465,16 @@ int vlan_dev_hard_start_xmit(struct sk_b
 		veth_TCI = VLAN_DEV_INFO(dev)->vlan_id;
 		veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
 
-		veth->h_vlan_TCI = htons(veth_TCI);
-	}
+		skb = __vlan_put_tag(skb, veth_TCI);
+		if (!skb) {
+			stats->tx_dropped++;
+			return 0;
+		}
 
-	skb->dev = VLAN_DEV_INFO(dev)->real_dev;
+		if (orig_headroom < VLAN_HLEN) {
+			VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++;
+		}
+	}
 
 #ifdef VLAN_DEBUG
 	printk(VLAN_DBG "%s: about to send skb: %p to dev: %s\n",
@@ -507,6 +488,7 @@ int vlan_dev_hard_start_xmit(struct sk_b
 	stats->tx_packets++; /* for statics only */
 	stats->tx_bytes += skb->len;
 
+	skb->dev = VLAN_DEV_INFO(dev)->real_dev;
 	dev_queue_xmit(skb);
 
 	return 0;
@@ -515,17 +497,22 @@ int vlan_dev_hard_start_xmit(struct sk_b
 int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_device_stats *stats = vlan_dev_get_stats(dev);
-	struct vlan_skb_tx_cookie *cookie;
+	unsigned short veth_TCI;
+
+	/* Construct the second two bytes. This field looks something
+	 * like:
+	 * usr_priority: 3 bits	 (high bits)
+	 * CFI		 1 bit
+	 * VLAN ID	 12 bits (low bits)
+	 */
+	veth_TCI = VLAN_DEV_INFO(dev)->vlan_id;
+	veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
+	skb = __vlan_hwaccel_put_tag(skb, veth_TCI);
 
 	stats->tx_packets++;
 	stats->tx_bytes += skb->len;
 
 	skb->dev = VLAN_DEV_INFO(dev)->real_dev;
-	cookie = VLAN_TX_SKB_CB(skb);
-	cookie->magic = VLAN_TX_COOKIE_MAGIC;
-	cookie->vlan_tag = (VLAN_DEV_INFO(dev)->vlan_id |
-			    vlan_dev_get_egress_qos_mask(dev, skb));
-
 	dev_queue_xmit(skb);
 
 	return 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/Makefile linux-2.4.26-pre6/net/Makefile
--- linux-2.4.25/net/Makefile	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/Makefile	2004-03-25 00:19:26.000000000 +0000
@@ -15,10 +15,10 @@ subdir-m :=	ipv4 # hum?
 
 
 subdir-$(CONFIG_NET)		+= 802 sched netlink
+subdir-$(CONFIG_IPV6)		+= ipv6
 subdir-$(CONFIG_INET)		+= ipv4
 subdir-$(CONFIG_NETFILTER)	+= ipv4/netfilter
 subdir-$(CONFIG_UNIX)		+= unix
-subdir-$(CONFIG_IPV6)		+= ipv6
 subdir-$(CONFIG_IP_SCTP)	+= sctp
 
 ifneq ($(CONFIG_IPV6),n)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/atm/lec.c linux-2.4.26-pre6/net/atm/lec.c
--- linux-2.4.25/net/atm/lec.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/atm/lec.c	2004-03-25 00:20:33.000000000 +0000
@@ -208,6 +208,22 @@ lec_open(struct net_device *dev)
         return 0;
 }
 
+static __inline__ void
+lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
+{
+	if (atm_may_send(vcc, skb->len)) {
+		atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
+	        ATM_SKB(skb)->vcc = vcc;
+	        ATM_SKB(skb)->atm_options = vcc->atm_options;
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len;
+		vcc->send(vcc, skb);
+	} else {
+		priv->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+	}
+}
+
 static int 
 lec_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
@@ -352,33 +368,10 @@ lec_send_packet(struct sk_buff *skb, str
                 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                         lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                         lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
-                ATM_SKB(skb2)->vcc = send_vcc;
-                ATM_SKB(skb2)->atm_options = send_vcc->atm_options;
-                DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name,
-                        send_vcc->vpi, send_vcc->vci);       
-                if (atm_may_send(send_vcc, skb2->len)) {
-			atomic_add(skb2->truesize, &send_vcc->sk->wmem_alloc);
-                        priv->stats.tx_packets++;
-                        priv->stats.tx_bytes += skb2->len;
-                        send_vcc->send(send_vcc, skb2);
-                } else {
-                        priv->stats.tx_dropped++;
-                        dev_kfree_skb(skb2);
-		}
+                lec_send(send_vcc, skb2, priv);
         }
 
-        ATM_SKB(skb)->vcc = send_vcc;
-        ATM_SKB(skb)->atm_options = send_vcc->atm_options;
-        if (atm_may_send(send_vcc, skb->len)) {
-                atomic_add(skb->truesize, &send_vcc->sk->wmem_alloc);
-                priv->stats.tx_packets++;
-                priv->stats.tx_bytes += skb->len;
-                send_vcc->send(send_vcc, skb);
-        } else {
-                priv->stats.tx_dropped++;
-                dev_kfree_skb(skb);
-	}
-
+        lec_send(send_vcc, skb, priv);
 #if 0
         /* Should we wait for card's device driver to notify us? */
         dev->tbusy=0;
@@ -1043,7 +1036,7 @@ static void lane2_associate_ind (struct 
 #define LEC_ARP_REFRESH_INTERVAL (3*HZ)
 
 static void lec_arp_check_expire(unsigned long data);
-static __inline__ void lec_arp_expire_arp(unsigned long data);
+static void lec_arp_expire_arp(unsigned long data);
 void dump_arp_table(struct lec_priv *priv);
 
 /* 
@@ -1383,7 +1376,7 @@ lec_arp_destroy(struct lec_priv *priv)
         struct lec_arp_table *entry, *next;
         int i;
 
-        del_timer(&priv->lec_arp_timer);
+        del_timer_sync(&priv->lec_arp_timer);
         
         /*
          * Remove all entries
@@ -1398,7 +1391,7 @@ lec_arp_destroy(struct lec_priv *priv)
         entry = priv->lec_arp_empty_ones;
         while(entry) {
                 next = entry->next;
-                del_timer(&entry->timer);
+                del_timer_sync(&entry->timer);
                 lec_arp_clear_vccs(entry);
                 kfree(entry);
                 entry = next;
@@ -1407,7 +1400,7 @@ lec_arp_destroy(struct lec_priv *priv)
         entry = priv->lec_no_forward;
         while(entry) {
                 next = entry->next;
-                del_timer(&entry->timer);
+                del_timer_sync(&entry->timer);
                 lec_arp_clear_vccs(entry);
                 kfree(entry);
                 entry = next;
@@ -1416,7 +1409,7 @@ lec_arp_destroy(struct lec_priv *priv)
         entry = priv->mcast_fwds;
         while(entry) {
                 next = entry->next;
-                del_timer(&entry->timer);
+                /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
                 lec_arp_clear_vccs(entry);
                 kfree(entry);
                 entry = next;
@@ -1490,8 +1483,6 @@ lec_arp_expire_arp(unsigned long data)
 
         entry = (struct lec_arp_table *)data;
 
-        del_timer(&entry->timer);
-
         DPRINTK("lec_arp_expire_arp\n");
         if (entry->status == ESI_ARP_PENDING) {
                 if (entry->no_tries <= entry->priv->max_retry_count) {
@@ -1501,8 +1492,7 @@ lec_arp_expire_arp(unsigned long data)
                                 send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
                         entry->no_tries++;
                 }
-                entry->timer.expires = jiffies + (1*HZ);
-                add_timer(&entry->timer);
+                mod_timer(&entry->timer, jiffies + (1*HZ));
         }
 }
 
@@ -1574,8 +1564,6 @@ lec_arp_check_expire(unsigned long data)
         unsigned long time_to_check;
         int i;
 
-        del_timer(&priv->lec_arp_timer);
-
         DPRINTK("lec_arp_check_expire %p,%d\n",priv,
                 atomic_read(&priv->lec_arp_users));
         DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
@@ -1619,6 +1607,10 @@ lec_arp_check_expire(unsigned long data)
                                            &&
                                            time_after_eq(now, entry->timestamp+
                                            priv->path_switching_delay)) {
+			                        struct sk_buff *skb;
+
+ 				                while ((skb = skb_dequeue(&entry->tx_wait)))
+					                lec_send(entry->vcc, skb, entry->priv);
                                                 entry->last_used = jiffies;
                                                 entry->status = 
                                                         ESI_FORWARD_DIRECT;
@@ -1629,8 +1621,8 @@ lec_arp_check_expire(unsigned long data)
                 }
                 lec_arp_put(priv);
         }
-        priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
-        add_timer(&priv->lec_arp_timer);
+
+        mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
 }
 /*
  * Try to find vcc where mac_address is attached.
@@ -2012,6 +2004,10 @@ lec_flush_complete(struct lec_priv *priv
                 for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) {
                         if (entry->flush_tran_id == tran_id &&
                             entry->status == ESI_FLUSH_PENDING) {
+			        struct sk_buff *skb;
+
+ 				while ((skb = skb_dequeue(&entry->tx_wait)))
+					lec_send(entry->vcc, skb, entry->priv);
                                 entry->status = ESI_FORWARD_DIRECT;
                                 DPRINTK("LEC_ARP: Flushed\n");
                         }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/af_bluetooth.c linux-2.4.26-pre6/net/bluetooth/af_bluetooth.c
--- linux-2.4.25/net/bluetooth/af_bluetooth.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/af_bluetooth.c	2004-03-25 00:18:03.000000000 +0000
@@ -218,15 +218,31 @@ int bluez_sock_recvmsg(struct socket *so
 	return err ? : copied;
 }
 
+static inline unsigned int bluez_accept_poll(struct sock *parent)
+{
+	struct list_head *p, *n;
+	struct sock *sk;
+
+	list_for_each_safe(p, n, &bluez_pi(parent)->accept_q) {
+		sk = (struct sock *) list_entry(p, struct bluez_pinfo, accept_q);
+		if (sk->state == BT_CONNECTED)
+			return POLLIN | POLLRDNORM;
+	}
+
+	return 0;
+}
+
 unsigned int bluez_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
 {
 	struct sock *sk = sock->sk;
-	unsigned int mask;
+	unsigned int mask = 0;
 
 	BT_DBG("sock %p, sk %p", sock, sk);
 
 	poll_wait(file, sk->sleep, wait);
-	mask = 0;
+
+	if (sk->state == BT_LISTEN)
+		return bluez_accept_poll(sk);
 
 	if (sk->err || !skb_queue_empty(&sk->error_queue))
 		mask |= POLLERR;
@@ -235,16 +251,17 @@ unsigned int bluez_sock_poll(struct file
 		mask |= POLLHUP;
 
 	if (!skb_queue_empty(&sk->receive_queue) || 
-			!list_empty(&bluez_pi(sk)->accept_q) ||
 			(sk->shutdown & RCV_SHUTDOWN))
 		mask |= POLLIN | POLLRDNORM;
 
 	if (sk->state == BT_CLOSED)
 		mask |= POLLHUP;
 
-	if (sk->state == BT_CONNECT || sk->state == BT_CONNECT2)
+	if (sk->state == BT_CONNECT ||
+			sk->state == BT_CONNECT2 ||
+			sk->state == BT_CONFIG)
 		return mask;
-	
+
 	if (sock_writeable(sk))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 	else
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/bnep/sock.c linux-2.4.26-pre6/net/bluetooth/bnep/sock.c
--- linux-2.4.25/net/bluetooth/bnep/sock.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/bnep/sock.c	2004-03-25 00:20:27.000000000 +0000
@@ -94,8 +94,10 @@ static int bnep_sock_ioctl(struct socket
 		if (!nsock)
 			return err;
 
-		if (nsock->sk->state != BT_CONNECTED)
+		if (nsock->sk->state != BT_CONNECTED) {
+			fput(nsock->file);
 			return -EBADFD;
+		}
 
 		err = bnep_add_connection(&ca, nsock);
 		if (!err) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/cmtp/sock.c linux-2.4.26-pre6/net/bluetooth/cmtp/sock.c
--- linux-2.4.25/net/bluetooth/cmtp/sock.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/cmtp/sock.c	2004-03-25 00:21:50.000000000 +0000
@@ -86,8 +86,10 @@ static int cmtp_sock_ioctl(struct socket
 		if (!nsock)
 			return err;
 
-		if (nsock->sk->state != BT_CONNECTED)
+		if (nsock->sk->state != BT_CONNECTED) {
+			fput(nsock->file);
 			return -EBADFD;
+		}
 
 		err = cmtp_add_connection(&ca, nsock);
 		if (!err) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/hci_conn.c linux-2.4.26-pre6/net/bluetooth/hci_conn.c
--- linux-2.4.25/net/bluetooth/hci_conn.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/hci_conn.c	2004-03-25 00:19:42.000000000 +0000
@@ -358,21 +358,24 @@ int hci_get_conn_list(unsigned long arg)
 	struct hci_conn_info *ci;
 	struct hci_dev *hdev;
 	struct list_head *p;
-	int n = 0, size;
+	int n = 0, size, err;
 
 	if (copy_from_user(&req, (void *) arg, sizeof(req)))
 		return -EFAULT;
 
-	if (!(hdev = hci_dev_get(req.dev_id)))
-		return -ENODEV;
-
-	size = req.conn_num * sizeof(struct hci_conn_info) + sizeof(req);
+	if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
+		return -EINVAL;
 
-	if (verify_area(VERIFY_WRITE, (void *)arg, size))
-		return -EFAULT;
+	size = sizeof(req) + req.conn_num * sizeof(*ci);
 
 	if (!(cl = (void *) kmalloc(size, GFP_KERNEL)))
 		return -ENOMEM;
+
+	if (!(hdev = hci_dev_get(req.dev_id))) {
+		kfree(cl);
+		return -ENODEV;
+	}
+
 	ci = cl->conn_info;
 
 	hci_dev_lock_bh(hdev);
@@ -386,20 +389,21 @@ int hci_get_conn_list(unsigned long arg)
 		(ci + n)->out   = c->out;
 		(ci + n)->state = c->state;
 		(ci + n)->link_mode = c->link_mode;
-		n++;
+		if (++n >= req.conn_num)
+			break;
 	}
 	hci_dev_unlock_bh(hdev);
 
 	cl->dev_id = hdev->id;
 	cl->conn_num = n;
-	size = n * sizeof(struct hci_conn_info) + sizeof(req);
+	size = sizeof(req) + n * sizeof(*ci);
 
 	hci_dev_put(hdev);
 
-	copy_to_user((void *) arg, cl, size);
+	err = copy_to_user((void *) arg, cl, size);
 	kfree(cl);
 
-	return 0;
+	return err ? -EFAULT : 0;
 }
 
 int hci_get_conn_info(struct hci_dev *hdev, unsigned long arg)
@@ -412,9 +416,6 @@ int hci_get_conn_info(struct hci_dev *hd
 	if (copy_from_user(&req, (void *) arg, sizeof(req)))
 		return -EFAULT;
 
-	if (verify_area(VERIFY_WRITE, ptr, sizeof(ci)))
-		return -EFAULT;
-
 	hci_dev_lock_bh(hdev);
 	conn = conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
 	if (conn) {
@@ -430,6 +431,5 @@ int hci_get_conn_info(struct hci_dev *hd
 	if (!conn)
 		return -ENOENT;
 
-	copy_to_user(ptr, &ci, sizeof(ci));
-	return 0;
+	return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/hci_core.c linux-2.4.26-pre6/net/bluetooth/hci_core.c
--- linux-2.4.25/net/bluetooth/hci_core.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/hci_core.c	2004-03-25 00:18:28.000000000 +0000
@@ -218,6 +218,10 @@ static void hci_init_req(struct hci_dev 
 
 	/* Mandatory initialization */
 
+	/* Reset */
+	if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks))
+		hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
+
 	/* Read Local Supported Features */
 	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
 
@@ -712,22 +716,20 @@ int hci_get_dev_list(unsigned long arg)
 	struct hci_dev_list_req *dl;
 	struct hci_dev_req *dr;
 	struct list_head *p;
-	int n = 0, size;
+	int n = 0, size, err;
 	__u16 dev_num;
 
 	if (get_user(dev_num, (__u16 *) arg))
 		return -EFAULT;
 
-	if (!dev_num)
+	if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr))
 		return -EINVAL;
-	
-	size = dev_num * sizeof(*dr) + sizeof(*dl);
 
-	if (verify_area(VERIFY_WRITE, (void *) arg, size))
-		return -EFAULT;
+	size = sizeof(*dl) + dev_num * sizeof(*dr);
 
 	if (!(dl = kmalloc(size, GFP_KERNEL)))
 		return -ENOMEM;
+
 	dr = dl->dev_req;
 
 	read_lock_bh(&hdev_list_lock);
@@ -742,12 +744,12 @@ int hci_get_dev_list(unsigned long arg)
 	read_unlock_bh(&hdev_list_lock);
 
 	dl->dev_num = n;
-	size = n * sizeof(*dr) + sizeof(*dl);
+	size = sizeof(*dl) + n * sizeof(*dr);
 
-	copy_to_user((void *) arg, dl, size);
+	err = copy_to_user((void *) arg, dl, size);
 	kfree(dl);
 
-	return 0;
+	return err ? -EFAULT : 0;
 }
 
 int hci_get_dev_info(unsigned long arg)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/l2cap.c linux-2.4.26-pre6/net/bluetooth/l2cap.c
--- linux-2.4.25/net/bluetooth/l2cap.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/l2cap.c	2004-03-25 00:19:30.000000000 +0000
@@ -1649,6 +1649,8 @@ static inline void l2cap_sig_channel(str
 	l2cap_cmd_hdr cmd;
 	int err = 0;
 
+	l2cap_raw_recv(conn, skb);
+
 	while (len >= L2CAP_CMD_HDR_SIZE) {
 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
 		data += L2CAP_CMD_HDR_SIZE;
@@ -1690,7 +1692,6 @@ static inline void l2cap_sig_channel(str
 
 		case L2CAP_COMMAND_REJ:
 			/* FIXME: We should process this */
-			l2cap_raw_recv(conn, skb);
 			break;
 
 		case L2CAP_ECHO_REQ:
@@ -1700,11 +1701,10 @@ static inline void l2cap_sig_channel(str
 		case L2CAP_ECHO_RSP:
 		case L2CAP_INFO_REQ:
 		case L2CAP_INFO_RSP:
-			l2cap_raw_recv(conn, skb);
 			break;
 
 		default:
-			BT_ERR("Uknown signaling command 0x%2.2x", cmd.code);
+			BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
 			err = -EINVAL;
 			break;
 		};
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/rfcomm/core.c linux-2.4.26-pre6/net/bluetooth/rfcomm/core.c
--- linux-2.4.25/net/bluetooth/rfcomm/core.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/rfcomm/core.c	2004-03-25 00:20:41.000000000 +0000
@@ -1654,9 +1654,10 @@ static inline void rfcomm_accept_connect
 	nsock->sk->state_change = rfcomm_l2state_change;
 
 	s = rfcomm_session_add(nsock, BT_OPEN);
-	if (s)
+	if (s) {
 		rfcomm_session_hold(s);
-	else
+		rfcomm_schedule(RFCOMM_SCHED_RX);
+	} else
 		sock_release(nsock);
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/bluetooth/rfcomm/tty.c linux-2.4.26-pre6/net/bluetooth/rfcomm/tty.c
--- linux-2.4.25/net/bluetooth/rfcomm/tty.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/net/bluetooth/rfcomm/tty.c	2004-03-25 00:18:24.000000000 +0000
@@ -109,6 +109,13 @@ static inline void rfcomm_dev_hold(struc
 
 static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
 {
+	/* The reason this isn't actually a race, as you no
+	   doubt have a little voice screaming at you in your
+	   head, is that the refcount should never actually
+	   reach zero unless the device has already been taken
+	   off the list, in rfcomm_dev_del(). And if that's not
+	   true, we'll hit the BUG() in rfcomm_dev_destruct()
+	   anyway. */
 	if (atomic_dec_and_test(&dev->refcnt))
 		rfcomm_dev_destruct(dev);
 }
@@ -132,10 +139,13 @@ static inline struct rfcomm_dev *rfcomm_
 	struct rfcomm_dev *dev;
 
 	read_lock(&rfcomm_dev_lock);
+
 	dev = __rfcomm_dev_get(id);
+	if (dev)
+		rfcomm_dev_hold(dev);
+
 	read_unlock(&rfcomm_dev_lock);
 
-	if (dev) rfcomm_dev_hold(dev);
 	return dev;
 }
 
@@ -347,7 +357,7 @@ static int rfcomm_get_dev_list(unsigned 
 	struct rfcomm_dev_list_req *dl;
 	struct rfcomm_dev_info *di;
 	struct list_head *p;
-	int n = 0, size;
+	int n = 0, size, err;
 	u16 dev_num;
 
 	BT_DBG("");
@@ -355,14 +365,11 @@ static int rfcomm_get_dev_list(unsigned 
 	if (get_user(dev_num, (u16 *) arg))
 		return -EFAULT;
 
-	if (!dev_num)
+	if (!dev_num || dev_num > (PAGE_SIZE * 4) / sizeof(*di))
 		return -EINVAL;
 
 	size = sizeof(*dl) + dev_num * sizeof(*di);
 
-	if (verify_area(VERIFY_WRITE, (void *)arg, size))
-		return -EFAULT;
-
 	if (!(dl = kmalloc(size, GFP_KERNEL)))
 		return -ENOMEM;
 
@@ -387,9 +394,10 @@ static int rfcomm_get_dev_list(unsigned 
 	dl->dev_num = n;
 	size = sizeof(*dl) + n * sizeof(*di);
 
-	copy_to_user((void *) arg, dl, size);
+	err = copy_to_user((void *) arg, dl, size);
 	kfree(dl);
-	return 0;
+
+	return err ? -EFAULT : 0;
 }
 
 static int rfcomm_get_dev_info(unsigned long arg)
@@ -486,7 +494,8 @@ static void rfcomm_dev_state_change(stru
 				rfcomm_dev_del(dev);
 
 				/* We have to drop DLC lock here, otherwise
-				 * rfcomm_dev_put() will dead lock if it's the last refference */
+				   rfcomm_dev_put() will dead lock if it's
+				   the last reference. */
 				rfcomm_dlc_unlock(dlc);
 				rfcomm_dev_put(dev);
 				rfcomm_dlc_lock(dlc);
@@ -541,6 +550,10 @@ static int rfcomm_tty_open(struct tty_st
 
 	BT_DBG("tty %p id %d", tty, id);
 
+	/* We don't leak this refcount. For reasons which are not entirely
+	   clear, the TTY layer will call our ->close() method even if the
+	   open fails. We decrease the refcount there, and decreasing it
+	   here too would cause breakage. */
 	dev = rfcomm_dev_get(id);
 	if (!dev)
 		return -ENODEV;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/core/dev.c linux-2.4.26-pre6/net/core/dev.c
--- linux-2.4.25/net/core/dev.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/core/dev.c	2004-03-25 00:20:02.000000000 +0000
@@ -1462,7 +1462,7 @@ int netif_receive_skb(struct sk_buff *sk
 {
 	struct packet_type *ptype, *pt_prev;
 	int ret = NET_RX_DROP;
-	unsigned short type = skb->protocol;
+	unsigned short type;
 
 	if (skb->stamp.tv_sec == 0)
 		do_gettimeofday(&skb->stamp);
@@ -1507,6 +1507,7 @@ int netif_receive_skb(struct sk_buff *sk
 	}
 #endif
 
+	type = skb->protocol;
 	for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
 		if (ptype->type == type &&
 		    (!ptype->dev || ptype->dev == skb->dev)) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/core/sock.c linux-2.4.26-pre6/net/core/sock.c
--- linux-2.4.25/net/core/sock.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.26-pre6/net/core/sock.c	2004-03-25 00:21:08.000000000 +0000
@@ -128,6 +128,16 @@
 #include <net/tcp.h>
 #endif
 
+/* Take into consideration the size of the struct sk_buff overhead in the
+ * determination of these values, since that is non-constant across
+ * platforms.  This makes socket queueing behavior and performance
+ * not depend upon such differences.
+ */
+#define _SK_MEM_PACKETS		256
+#define _SK_MEM_OVERHEAD	(sizeof(struct sk_buff) + 256)
+#define SK_WMEM_MAX		(_SK_MEM_OVERHEAD * _SK_MEM_PACKETS)
+#define SK_RMEM_MAX		(_SK_MEM_OVERHEAD * _SK_MEM_PACKETS)
+
 /* Run time adjustable parameters. */
 __u32 sysctl_wmem_max = SK_WMEM_MAX;
 __u32 sysctl_rmem_max = SK_RMEM_MAX;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/arp.c linux-2.4.26-pre6/net/ipv4/arp.c
--- linux-2.4.25/net/ipv4/arp.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/arp.c	2004-03-25 00:21:45.000000000 +0000
@@ -66,6 +66,10 @@
  *		Alexey Kuznetsov:	new arp state machine;
  *					now it is in net/core/neighbour.c.
  *		Krzysztof Halasa:	Added Frame Relay ARP support.
+ *		Shmulik Hen:		Split arp_send to arp_create and
+ *					arp_xmit so intermediate drivers like
+ *					bonding can change the skb before
+ *					sending (e.g. insert 8021q tag).
  */
 
 #include <linux/types.h>
@@ -317,15 +321,40 @@ static void arp_error_report(struct neig
 
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-	u32 saddr;
+	u32 saddr = 0;
 	u8  *dst_ha = NULL;
 	struct net_device *dev = neigh->dev;
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
+	struct in_device *in_dev = in_dev_get(dev);
+
+	if (!in_dev)
+		return;
 
-	if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+	default:
+	case 0:		/* By default announce any local IP */
+		if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+			saddr = skb->nh.iph->saddr;
+		break;
+	case 1:		/* Restrict announcements of saddr in same subnet */
+		if (!skb)
+			break;
 		saddr = skb->nh.iph->saddr;
-	else
+		if (inet_addr_type(saddr) == RTN_LOCAL) {
+			/* saddr should be known to target */
+			if (inet_addr_onlink(in_dev, target, saddr))
+				break;
+		}
+		saddr = 0;
+		break;
+	case 2:		/* Avoid secondary IPs, get a primary/preferred one */
+		break;
+	}
+
+	if (in_dev)
+		in_dev_put(in_dev);
+	if (!saddr)
 		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
 
 	if ((probes -= neigh->parms->ucast_probes) < 0) {
@@ -346,6 +375,42 @@ static void arp_solicit(struct neighbour
 		read_unlock_bh(&neigh->lock);
 }
 
+static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
+		      u32 sip, u32 tip)
+{
+	int scope;
+
+	switch (IN_DEV_ARP_IGNORE(in_dev)) {
+	case 0:	/* Reply, the tip is already validated */
+		return 0;
+	case 1:	/* Reply only if tip is configured on the incoming interface */
+		sip = 0;
+		scope = RT_SCOPE_HOST;
+		break;
+	case 2:	/*
+		 * Reply only if tip is configured on the incoming interface
+		 * and is in same subnet as sip
+		 */
+		scope = RT_SCOPE_HOST;
+		break;
+	case 3:	/* Do not reply for scope host addresses */
+		sip = 0;
+		scope = RT_SCOPE_LINK;
+		dev = NULL;
+		break;
+	case 4:	/* Reserved */
+	case 5:
+	case 6:
+	case 7:
+		return 0;
+	case 8:	/* Do not reply */
+		return 1;
+	default:
+		return 0;
+	}
+	return !inet_confirm_addr(dev, sip, tip, scope);
+}
+
 static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
 {
 	struct rtable *rt;
@@ -481,34 +546,26 @@ static inline int arp_fwd_proxy(struct i
  */
 
 /*
- *	Create and send an arp packet. If (dest_hw == NULL), we create a broadcast
+ *	Create an arp packet. If (dest_hw == NULL), we create a broadcast
  *	message.
  */
-
-void arp_send(int type, int ptype, u32 dest_ip, 
-	      struct net_device *dev, u32 src_ip, 
-	      unsigned char *dest_hw, unsigned char *src_hw,
-	      unsigned char *target_hw)
+struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
+			   struct net_device *dev, u32 src_ip,
+			   unsigned char *dest_hw, unsigned char *src_hw,
+			   unsigned char *target_hw)
 {
 	struct sk_buff *skb;
 	struct arphdr *arp;
 	unsigned char *arp_ptr;
 
 	/*
-	 *	No arp on this interface.
-	 */
-	
-	if (dev->flags&IFF_NOARP)
-		return;
-
-	/*
 	 *	Allocate a buffer
 	 */
 	
 	skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
 				+ dev->hard_header_len + 15, GFP_ATOMIC);
 	if (skb == NULL)
-		return;
+		return NULL;
 
 	skb_reserve(skb, (dev->hard_header_len+15)&~15);
 	skb->nh.raw = skb->data;
@@ -588,12 +645,46 @@ void arp_send(int type, int ptype, u32 d
 	arp_ptr+=dev->addr_len;
 	memcpy(arp_ptr, &dest_ip, 4);
 
-	/* Send it off, maybe filter it using firewalling first.  */
-	NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, dev, dev_queue_xmit);
-	return;
+	return skb;
 
 out:
 	kfree_skb(skb);
+	return NULL;
+}
+
+/*
+ *	Send an arp packet.
+ */
+void arp_xmit(struct sk_buff *skb)
+{
+	/* Send it off, maybe filter it using firewalling first.  */
+	NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
+}
+
+/*
+ *	Create and send an arp packet.
+ */
+void arp_send(int type, int ptype, u32 dest_ip, 
+	      struct net_device *dev, u32 src_ip, 
+	      unsigned char *dest_hw, unsigned char *src_hw,
+	      unsigned char *target_hw)
+{
+	struct sk_buff *skb;
+
+	/*
+	 *	No arp on this interface.
+	 */
+	
+	if (dev->flags&IFF_NOARP)
+		return;
+
+	skb = arp_create(type, ptype, dest_ip, dev, src_ip,
+			 dest_hw, src_hw, target_hw);
+	if (skb == NULL) {
+		return;
+	}
+
+	arp_xmit(skb);
 }
 
 static void parp_redo(struct sk_buff *skb)
@@ -756,7 +847,8 @@ int arp_process(struct sk_buff *skb)
 	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
 	if (sip == 0) {
 		if (arp->ar_op == htons(ARPOP_REQUEST) &&
-		    inet_addr_type(tip) == RTN_LOCAL)
+		    inet_addr_type(tip) == RTN_LOCAL &&
+		    !arp_ignore(in_dev,dev,sip,tip))
 			arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
 		goto out;
 	}
@@ -771,7 +863,10 @@ int arp_process(struct sk_buff *skb)
 			n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 			if (n) {
 				int dont_send = 0;
-				if (IN_DEV_ARPFILTER(in_dev))
+
+				if (!dont_send)
+					dont_send |= arp_ignore(in_dev,dev,sip,tip);
+				if (!dont_send && IN_DEV_ARPFILTER(in_dev))
 					dont_send |= arp_filter(sip,tip,dev); 
 				if (!dont_send)
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/devinet.c linux-2.4.26-pre6/net/ipv4/devinet.c
--- linux-2.4.25/net/ipv4/devinet.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/devinet.c	2004-03-25 00:18:22.000000000 +0000
@@ -772,6 +772,84 @@ u32 inet_select_addr(const struct net_de
 	return 0;
 }
 
+static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
+			      u32 local, int scope)
+{
+	int same = 0;
+	u32 addr = 0;
+
+	for_ifa(in_dev) {
+		if (!addr &&
+		    (local == ifa->ifa_local || !local) &&
+		    ifa->ifa_scope <= scope) {
+			addr = ifa->ifa_local;
+			if (same)
+				break;
+		}
+		if (!same) {
+			same = (!local || inet_ifa_match(local, ifa)) &&
+				(!dst || inet_ifa_match(dst, ifa));
+			if (same && addr) {
+				if (local || !dst)
+					break;
+				/* Is the selected addr into dst subnet? */
+				if (inet_ifa_match(addr, ifa))
+					break;
+				/* No, then can we use new local src? */
+				if (ifa->ifa_scope <= scope) {
+					addr = ifa->ifa_local;
+					break;
+				}
+				/* search for large dst subnet for addr */
+				same = 0;
+			}
+		}
+	} endfor_ifa(in_dev);
+
+	return same? addr : 0;
+}
+
+/*
+ * Confirm that local IP address exists using wildcards:
+ * - dev: only on this interface, 0=any interface
+ * - dst: only in the same subnet as dst, 0=any dst
+ * - local: address, 0=autoselect the local address
+ * - scope: maximum allowed scope value for the local address
+ */
+u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope)
+{
+	u32 addr = 0;
+	struct in_device *in_dev;
+
+	if (dev) {
+		read_lock(&inetdev_lock);
+		if ((in_dev = __in_dev_get(dev))) {
+			read_lock(&in_dev->lock);
+			addr = confirm_addr_indev(in_dev, dst, local, scope);
+			read_unlock(&in_dev->lock);
+		}
+		read_unlock(&inetdev_lock);
+
+		return addr;
+	}
+
+	read_lock(&dev_base_lock);
+	read_lock(&inetdev_lock);
+	for (dev = dev_base; dev; dev = dev->next) {
+		if ((in_dev = __in_dev_get(dev))) {
+			read_lock(&in_dev->lock);
+			addr = confirm_addr_indev(in_dev, dst, local, scope);
+			read_unlock(&in_dev->lock);
+			if (addr)
+				break;
+		}
+	}
+	read_unlock(&inetdev_lock);
+	read_unlock(&dev_base_lock);
+
+	return addr;
+}
+
 /*
  *	Device notifier
  */
@@ -1012,10 +1090,9 @@ static struct rtnetlink_link inet_rtnetl
 
 #ifdef CONFIG_SYSCTL
 
-void inet_forward_change()
+void inet_forward_change(int on)
 {
 	struct net_device *dev;
-	int on = ipv4_devconf.forwarding;
 
 	ipv4_devconf.accept_redirects = !on;
 	ipv4_devconf_dflt.forwarding = on;
@@ -1046,7 +1123,7 @@ int devinet_sysctl_forward(ctl_table *ct
 
 	if (write && *valp != val) {
 		if (valp == &ipv4_devconf.forwarding)
-			inet_forward_change();
+			inet_forward_change(*valp);
 		else if (valp != &ipv4_devconf_dflt.forwarding)
 			rt_cache_flush(0);
 	}
@@ -1057,7 +1134,7 @@ int devinet_sysctl_forward(ctl_table *ct
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[18];
+	ctl_table devinet_vars[20];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -1106,6 +1183,12 @@ static struct devinet_sysctl_table
 	{NET_IPV4_CONF_ARPFILTER, "arp_filter",
 	 &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
+	{NET_IPV4_CONF_ARP_ANNOUNCE, "arp_announce",
+	 &ipv4_devconf.arp_announce, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
+	{NET_IPV4_CONF_ARP_IGNORE, "arp_ignore",
+	 &ipv4_devconf.arp_ignore, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
 	{NET_IPV4_CONF_FORCE_IGMP_VERSION, "force_igmp_version",
 	 &ipv4_devconf.force_igmp_version, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/icmp.c linux-2.4.26-pre6/net/ipv4/icmp.c
--- linux-2.4.25/net/ipv4/icmp.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/icmp.c	2004-03-25 00:22:05.000000000 +0000
@@ -984,7 +984,13 @@ void __init icmp_init(struct net_proto_f
 			panic("Failed to create the ICMP control socket.\n");
 
 		icmp_socket_cpu(i)->sk->allocation=GFP_ATOMIC;
-		icmp_socket_cpu(i)->sk->sndbuf = SK_WMEM_MAX*2;
+
+		/* Enough space for 2 64K ICMP packets, including
+		 * sk_buff struct overhead.
+		 */
+		icmp_socket_cpu(i)->sk->sndbuf =
+			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
+
 		icmp_socket_cpu(i)->sk->protinfo.af_inet.ttl = MAXTTL;
 		icmp_socket_cpu(i)->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/igmp.c linux-2.4.26-pre6/net/ipv4/igmp.c
--- linux-2.4.25/net/ipv4/igmp.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/igmp.c	2004-03-25 00:22:20.000000000 +0000
@@ -101,7 +101,8 @@
 #endif
 
 
-#define IP_MAX_MEMBERSHIPS 20
+#define IP_MAX_MEMBERSHIPS	20
+#define IP_MAX_MSF		10
 
 #ifdef CONFIG_IP_MULTICAST
 /* Parameter names and values are taken from igmp-v2-06 draft */
@@ -1311,6 +1312,7 @@ static struct in_device * ip_mc_find_dev
  *	Join a socket to a group
  */
 int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;
+int sysctl_igmp_max_msf = IP_MAX_MSF;
 
 
 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
@@ -1772,6 +1774,10 @@ int ip_mc_source(int add, int omode, str
 	}
 	/* else, add a new source to the filter */
 
+	if (psl && psl->sl_count >= sysctl_igmp_max_msf) {
+		err = -ENOBUFS;
+		goto done;
+	}
 	if (!psl || psl->sl_count == psl->sl_max) {
 		struct ip_sf_socklist *newpsl;
 		int count = IP_SFBLOCK;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ip_sockglue.c linux-2.4.26-pre6/net/ipv4/ip_sockglue.c
--- linux-2.4.25/net/ipv4/ip_sockglue.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ip_sockglue.c	2004-03-25 00:18:40.000000000 +0000
@@ -608,10 +608,16 @@ int ip_setsockopt(struct sock *sk, int l
 		}
 		case IP_MSFILTER:
 		{
+			extern int sysctl_optmem_max;
+			extern int sysctl_igmp_max_msf;
 			struct ip_msfilter *msf;
 
 			if (optlen < IP_MSFILTER_SIZE(0))
 				goto e_inval;
+			if (optlen > sysctl_optmem_max) {
+				err = -ENOBUFS;
+				break;
+			}
 			msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL);
 			if (msf == 0) {
 				err = -ENOBUFS;
@@ -622,6 +628,18 @@ int ip_setsockopt(struct sock *sk, int l
 				kfree(msf);
 				break;
 			}
+			/* numsrc >= (1G-4) overflow in 32 bits */
+			if (msf->imsf_numsrc >= 0x3ffffffcU ||
+			    msf->imsf_numsrc > sysctl_igmp_max_msf) {
+				kfree(msf);
+				err = -ENOBUFS;
+				break;
+			}
+			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
+				kfree(msf);
+				err = -EINVAL;
+				break;
+			}
 			err = ip_mc_msfilter(sk, msf, 0);
 			kfree(msf);
 			break;
@@ -744,6 +762,8 @@ int ip_setsockopt(struct sock *sk, int l
 		}
 		case MCAST_MSFILTER:
 		{
+			extern int sysctl_optmem_max;
+			extern int sysctl_igmp_max_msf;
 			struct sockaddr_in *psin;
 			struct ip_msfilter *msf = 0;
 			struct group_filter *gsf = 0;
@@ -751,6 +771,10 @@ int ip_setsockopt(struct sock *sk, int l
 
 			if (optlen < GROUP_FILTER_SIZE(0))
 				goto e_inval;
+			if (optlen > sysctl_optmem_max) {
+				err = -ENOBUFS;
+				break;
+			}
 			gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
 			if (gsf == 0) {
 				err = -ENOBUFS;
@@ -760,7 +784,13 @@ int ip_setsockopt(struct sock *sk, int l
 			if (copy_from_user(gsf, optval, optlen)) {
 				goto mc_msf_out;
 			}
-			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < optlen) {
+			/* numsrc >= (4G-140)/128 overflow in 32 bits */
+			if (gsf->gf_numsrc >= 0x1ffffff ||
+			    gsf->gf_numsrc > sysctl_igmp_max_msf) {
+				err = -ENOBUFS;
+				goto mc_msf_out;
+			}
+			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
 				err = EINVAL;
 				goto mc_msf_out;
 			}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/Config.in linux-2.4.26-pre6/net/ipv4/ipvs/Config.in
--- linux-2.4.25/net/ipv4/ipvs/Config.in	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/Config.in	2004-03-25 00:18:13.000000000 +0000
@@ -11,7 +11,7 @@ if [ "$CONFIG_IP_VS" != "n" ]; then
   comment 'IPVS scheduler'
   dep_tristate '  round-robin scheduling' CONFIG_IP_VS_RR $CONFIG_IP_VS
   dep_tristate '  weighted round-robin scheduling' CONFIG_IP_VS_WRR $CONFIG_IP_VS
-  dep_tristate '  least-connection scheduling scheduling' CONFIG_IP_VS_LC $CONFIG_IP_VS
+  dep_tristate '  least-connection scheduling' CONFIG_IP_VS_LC $CONFIG_IP_VS
   dep_tristate '  weighted least-connection scheduling' CONFIG_IP_VS_WLC $CONFIG_IP_VS
   dep_tristate '  locality-based least-connection scheduling' CONFIG_IP_VS_LBLC $CONFIG_IP_VS
   dep_tristate '  locality-based least-connection with replication scheduling' CONFIG_IP_VS_LBLCR $CONFIG_IP_VS
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_app.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_app.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_app.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_app.c	2004-03-25 00:17:34.000000000 +0000
@@ -20,18 +20,12 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/init.h>
 #include <net/protocol.h>
-#include <net/tcp.h>
-#include <net/udp.h>
 #include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_conn.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_conn.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_conn.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_conn.c	2004-03-25 00:20:58.000000000 +0000
@@ -24,12 +24,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/compiler.h>
 #include <linux/vmalloc.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>                  /* for tcphdr */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_ctl.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_ctl.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_ctl.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_ctl.c	2004-03-25 00:19:01.000000000 +0000
@@ -20,12 +20,9 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
@@ -1694,7 +1691,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cm
 	 * len > 128000 is a sanity check.
 	 */
 	if (len < sizeof(struct ip_vs_rule_user)) {
-		IP_VS_ERR("set_ctl: len %u < %u\n",
+		IP_VS_ERR("set_ctl: len %u < %Zu\n",
 			  len, sizeof(struct ip_vs_rule_user));
 		return -EINVAL;
 	} else if (len > 128000) {
@@ -1740,9 +1737,9 @@ do_ip_vs_set_ctl(struct sock *sk, int cm
 	 * Check for valid protocol: TCP or UDP. Even for fwmark!=0
 	 */
 	if (urule->protocol!=IPPROTO_TCP && urule->protocol!=IPPROTO_UDP) {
-		IP_VS_INFO("vs_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s",
-			   ntohs(urule->protocol), NIPQUAD(urule->vaddr),
-			   ntohs(urule->vport), urule->sched_name);
+		IP_VS_ERR("set_ctl: invalid protocol %d %d.%d.%d.%d:%d %s\n",
+			  urule->protocol, NIPQUAD(urule->vaddr),
+			  ntohs(urule->vport), urule->sched_name);
 		ret = -EFAULT;
 		goto out_unlock;
 	}
@@ -1972,7 +1969,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 		struct ip_vs_get_services get;
 
 		if (*len < sizeof(get)) {
-			IP_VS_ERR("length: %u < %u\n", *len, sizeof(get));
+			IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(get));
 			ret = -EINVAL;
 			goto out;
 		}
@@ -1981,7 +1978,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 			goto out;
 		}
 		if (*len != (sizeof(get)+sizeof(struct ip_vs_service_user)*get.num_services)) {
-			IP_VS_ERR("length: %u != %u\n", *len,
+			IP_VS_ERR("length: %u != %Zu\n", *len,
 				  sizeof(get)+sizeof(struct ip_vs_service_user)*get.num_services);
 			ret = -EINVAL;
 			goto out;
@@ -1996,7 +1993,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 		struct ip_vs_service *svc;
 
 		if (*len != sizeof(get)) {
-			IP_VS_ERR("length: %u != %u\n", *len, sizeof(get));
+			IP_VS_ERR("length: %u != %Zu\n", *len, sizeof(get));
 			ret = -EINVAL;
 			goto out;
 		}
@@ -2030,7 +2027,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 		struct ip_vs_get_dests get;
 
 		if (*len < sizeof(get)) {
-			IP_VS_ERR("length: %u < %u\n", *len, sizeof(get));
+			IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(get));
 			ret = -EINVAL;
 			goto out;
 		}
@@ -2040,7 +2037,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 		}
 		if (*len != (sizeof(get) +
 			     sizeof(struct ip_vs_dest_user)*get.num_dests)) {
-			IP_VS_ERR("length: %u != %u\n", *len,
+			IP_VS_ERR("length: %u != %Zu\n", *len,
 				  sizeof(get)+sizeof(struct ip_vs_dest_user)*get.num_dests);
 			ret = -EINVAL;
 			goto out;
@@ -2054,7 +2051,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 		struct ip_vs_timeout_user u;
 
 		if (*len < sizeof(u)) {
-			IP_VS_ERR("length: %u < %u\n", *len, sizeof(u));
+			IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(u));
 			ret = -EINVAL;
 			goto out;
 		}
@@ -2069,7 +2066,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
 		struct ip_vs_daemon_user u;
 
 		if (*len < sizeof(u)) {
-			IP_VS_ERR("length: %u < %u\n", *len, sizeof(u));
+			IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(u));
 			ret = -EINVAL;
 			goto out;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_dh.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_dh.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_dh.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_dh.c	2004-03-25 00:19:52.000000000 +0000
@@ -37,12 +37,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_ftp.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_ftp.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_ftp.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_ftp.c	2004-03-25 00:20:53.000000000 +0000
@@ -24,15 +24,11 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <asm/system.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/init.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_lblc.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_lblc.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_lblc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_lblc.c	2004-03-25 00:20:00.000000000 +0000
@@ -41,14 +41,10 @@
  * me to write this module.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
-/* for systcl */
+/* for sysctl */
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 
@@ -69,7 +65,7 @@
  *    entries that haven't been touched for a day.
  */
 #define COUNT_FOR_FULL_EXPIRATION   30
-int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ;
+static int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ;
 
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_lblcr.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_lblcr.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_lblcr.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_lblcr.c	2004-03-25 00:20:41.000000000 +0000
@@ -39,14 +39,10 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
-/* for systcl */
+/* for sysctl */
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 /* for proc_net_create/proc_net_remove */
@@ -69,7 +65,7 @@
  *    entries that haven't been touched for a day.
  */
 #define COUNT_FOR_FULL_EXPIRATION   30
-int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ;
+static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ;
 
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_lc.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_lc.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_lc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_lc.c	2004-03-25 00:19:32.000000000 +0000
@@ -16,12 +16,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_nq.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_nq.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_nq.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_nq.c	2004-03-25 00:18:23.000000000 +0000
@@ -33,12 +33,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_rr.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_rr.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_rr.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_rr.c	2004-03-25 00:20:46.000000000 +0000
@@ -21,12 +21,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sched.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sched.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_sched.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sched.c	2004-03-25 00:18:37.000000000 +0000
@@ -19,10 +19,7 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <asm/softirq.h>                /* for local_bh_* */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sed.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sed.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_sed.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sed.c	2004-03-25 00:18:11.000000000 +0000
@@ -37,12 +37,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sh.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sh.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_sh.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sh.c	2004-03-25 00:20:21.000000000 +0000
@@ -34,12 +34,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sync.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sync.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_sync.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_sync.c	2004-03-25 00:20:40.000000000 +0000
@@ -13,17 +13,9 @@
  *              through multicast
  */
 
-#define __KERNEL_SYSCALLS__             /*  for waitpid */
-
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/unistd.h>
 
 #include <linux/skbuff.h>
 #include <linux/in.h>
@@ -559,8 +551,6 @@ ip_vs_receive(struct socket *sock, char 
 }
 
 
-static int errno;
-
 static DECLARE_WAIT_QUEUE_HEAD(sync_wait);
 static pid_t sync_pid = 0;
 
@@ -679,9 +669,9 @@ static int sync_thread(void *startup)
 	set_fs(KERNEL_DS);
 
 	if (ip_vs_sync_state == IP_VS_STATE_MASTER)
-		sprintf(current->comm, "ipvs syncmaster");
+		sprintf(current->comm, "ipvs_syncmaster");
 	else if (ip_vs_sync_state == IP_VS_STATE_BACKUP)
-		sprintf(current->comm, "ipvs syncbackup");
+		sprintf(current->comm, "ipvs_syncbackup");
 	else IP_VS_BUG();
 
 	spin_lock_irq(&current->sigmask_lock);
@@ -726,10 +716,19 @@ static int sync_thread(void *startup)
 
 static int fork_sync_thread(void *startup)
 {
+	pid_t pid;
+
 	/* fork the sync thread here, then the parent process of the
 	   sync thread is the init process after this thread exits. */
-	if (kernel_thread(sync_thread, startup, 0) < 0)
-		IP_VS_BUG();
+  repeat:
+	if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
+		IP_VS_ERR("could not create sync_thread due to %d... "
+			  "retrying.\n", pid);
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ);
+		goto repeat;
+	}
+
 	return 0;
 }
 
@@ -738,7 +737,6 @@ int start_sync_thread(int state, char *m
 {
 	DECLARE_COMPLETION(startup);
 	pid_t pid;
-	int waitpid_result;
 
 	if (sync_pid)
 		return -EEXIST;
@@ -750,12 +748,13 @@ int start_sync_thread(int state, char *m
 	ip_vs_sync_state = state;
 	strcpy(ip_vs_mcast_ifn, mcast_ifn);
 
-	if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0)
-		IP_VS_BUG();
-
-	if ((waitpid_result = waitpid(pid, NULL, __WCLONE)) != pid) {
-		IP_VS_ERR("%s: waitpid(%d,...) failed, errno %d\n",
-			  __FUNCTION__, pid, -waitpid_result);
+  repeat:
+	if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
+		IP_VS_ERR("could not create fork_sync_thread due to %d... "
+			  "retrying.\n", pid);
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ);
+		goto repeat;
 	}
 
 	wait_for_completion(&startup);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_wlc.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_wlc.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_wlc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_wlc.c	2004-03-25 00:22:20.000000000 +0000
@@ -21,12 +21,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_wrr.c linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_wrr.c
--- linux-2.4.25/net/ipv4/ipvs/ip_vs_wrr.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/ipvs/ip_vs_wrr.c	2004-03-25 00:21:23.000000000 +0000
@@ -20,12 +20,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/netfilter/ipt_ECN.c linux-2.4.26-pre6/net/ipv4/netfilter/ipt_ECN.c
--- linux-2.4.25/net/ipv4/netfilter/ipt_ECN.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/netfilter/ipt_ECN.c	2004-03-25 00:21:34.000000000 +0000
@@ -4,7 +4,7 @@
  * 
  * This software is distributed under GNU GPL v2, 1991
  * 
- * ipt_ECN.c,v 1.4 2002/08/05 19:36:51 laforge Exp
+ * ipt_ECN.c,v 1.7 2003/12/15 15:18:06 laforge Exp 
 */
 
 #include <linux/module.h>
@@ -59,8 +59,8 @@ set_ect_tcp(struct sk_buff **pskb, struc
 	    const struct ipt_ECN_info *einfo)
 {
 
-	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
-	u_int16_t *tcpflags = (u_int16_t *)tcph + 6;
+	struct tcphdr *tcph;
+	u_int16_t *tcpflags;
 	u_int16_t diffs[2];
 
 	/* raw socket (tcpdump) may have clone of incoming
@@ -71,9 +71,12 @@ set_ect_tcp(struct sk_buff **pskb, struc
 			return NF_DROP;
 		kfree_skb(*pskb);
 		*pskb = nskb;
-		iph = (*pskb)->nh.iph;
 	}
 
+	iph = (*pskb)->nh.iph;
+	tcph = (void *) iph + iph->ihl * 4;
+	tcpflags = (u_int16_t *)tcph + 6;
+
 	diffs[0] = *tcpflags;
 
 	if (einfo->operation & IPT_ECN_OP_SET_ECE
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/sysctl_net_ipv4.c linux-2.4.26-pre6/net/ipv4/sysctl_net_ipv4.c
--- linux-2.4.25/net/ipv4/sysctl_net_ipv4.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/sysctl_net_ipv4.c	2004-03-25 00:21:08.000000000 +0000
@@ -38,6 +38,7 @@ extern int sysctl_icmp_ratemask;
 
 /* From igmp.c */
 extern int sysctl_igmp_max_memberships;
+extern int sysctl_igmp_max_msf;
 
 /* From inetpeer.c */
 extern int inet_peer_threshold;
@@ -52,6 +53,9 @@ static int ip_local_port_range_min[] = {
 static int ip_local_port_range_max[] = { 65535, 65535 };
 #endif
 
+/* From tcp_input.c */
+extern int sysctl_tcp_westwood;
+
 struct ipv4_config ipv4_config;
 
 extern ctl_table ipv4_route_table[];
@@ -68,7 +72,7 @@ int ipv4_sysctl_forward(ctl_table *ctl, 
 	ret = proc_dointvec(ctl, write, filp, buffer, lenp);
 
 	if (write && ipv4_devconf.forwarding != val)
-		inet_forward_change();
+		inet_forward_change(ipv4_devconf.forwarding);
 
 	return ret;
 }
@@ -84,7 +88,7 @@ static int ipv4_sysctl_forward_strategy(
 	if (get_user(new,(int *)newval))
 		return -EFAULT; 
 	if (new != ipv4_devconf.forwarding) 
-		inet_forward_change(); 
+		inet_forward_change(new); 
 	return 0; /* caller does change again and handles handles oldval */ 
 }
 
@@ -182,6 +186,8 @@ ctl_table ipv4_table[] = {
 	{NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships",
 	 &sysctl_igmp_max_memberships, sizeof(int), 0644, NULL, &proc_dointvec},
 #endif
+	{NET_IPV4_IGMP_MAX_MSF, "igmp_max_msf",
+	 &sysctl_igmp_max_msf, sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_IPV4_INET_PEER_THRESHOLD, "inet_peer_threshold",
 	 &inet_peer_threshold, sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_IPV4_INET_PEER_MINTTL, "inet_peer_minttl",
@@ -229,6 +235,9 @@ ctl_table ipv4_table[] = {
 	{NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval",
 	 &sysctl_ipfrag_secret_interval, sizeof(int), 0644, NULL, &proc_dointvec_jiffies, 
 	 &sysctl_jiffies},
+        {NET_TCP_WESTWOOD, "tcp_westwood",
+         &sysctl_tcp_westwood, sizeof(int), 0644, NULL,
+         &proc_dointvec},
 	{0}
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/tcp_input.c linux-2.4.26-pre6/net/ipv4/tcp_input.c
--- linux-2.4.25/net/ipv4/tcp_input.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/tcp_input.c	2004-03-25 00:18:10.000000000 +0000
@@ -61,6 +61,7 @@
  *		Panu Kuhlberg:		Experimental audit of TCP (re)transmission
  *					engine. Lots of bugs are found.
  *		Pasi Sarolahti:		F-RTO for dealing with spurious RTOs
+ *		Angelo Dell'Aera:	TCP Westwood+ support
  */
 
 #include <linux/config.h>
@@ -89,6 +90,8 @@ int sysctl_tcp_rfc1337 = 0;
 int sysctl_tcp_max_orphans = NR_FILE;
 int sysctl_tcp_frto = 0;
 
+int sysctl_tcp_westwood = 0;
+
 #define FLAG_DATA		0x01 /* Incoming frame contained data.		*/
 #define FLAG_WIN_UPDATE		0x02 /* Incoming ACK was a window update.	*/
 #define FLAG_DATA_ACKED		0x04 /* This ACK acknowledged new data.		*/
@@ -470,6 +473,8 @@ static __inline__ void tcp_rtt_estimator
 		tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
 		tp->rtt_seq = tp->snd_nxt;
 	}
+
+	tcp_westwood_update_rtt(tp, tp->srtt >> 3);
 }
 
 /* Calculate rto without backoff.  This is the second half of Van Jacobson's
@@ -1068,7 +1073,9 @@ void tcp_enter_loss(struct sock *sk, int
 	    tp->snd_una == tp->high_seq ||
 	    (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
 		tp->prior_ssthresh = tcp_current_ssthresh(tp);
-		tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+
+		if (!(tcp_westwood_ssthresh(tp)))
+			tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
 	}
 	tp->snd_cwnd = 1;
 	tp->snd_cwnd_cnt = 0;
@@ -1380,11 +1387,24 @@ static __inline__ void tcp_moderate_cwnd
 static void tcp_cwnd_down(struct tcp_opt *tp)
 {
 	int decr = tp->snd_cwnd_cnt + 1;
+	__u32 limit;
+
+	/*
+	 * TCP Westwood
+	 * Here limit is evaluated as BWestimation*RTTmin (for obtaining it
+	 * in packets we use mss_cache). If sysctl_tcp_westwood is off
+	 * tcp_westwood_bw_rttmin() returns 0. In such case snd_ssthresh is
+	 * still used as usual. It prevents other strange cases in which
+	 * BWE*RTTmin could assume value 0. It should not happen but...
+	 */ 
+
+	if (!(limit = tcp_westwood_bw_rttmin(tp)))
+		limit = tp->snd_ssthresh/2;
 
 	tp->snd_cwnd_cnt = decr&1;
 	decr >>= 1;
 
-	if (decr && tp->snd_cwnd > tp->snd_ssthresh/2)
+	if (decr && tp->snd_cwnd > limit)
 		tp->snd_cwnd -= decr;
 
 	tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
@@ -1528,7 +1548,8 @@ static int tcp_try_undo_loss(struct sock
 
 static __inline__ void tcp_complete_cwr(struct tcp_opt *tp)
 {
-	tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+	if (!(tcp_westwood_complete_cwr(tp)))
+		tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
@@ -2016,6 +2037,234 @@ static void tcp_process_frto(struct sock
 	tp->frto_counter = (tp->frto_counter + 1) % 3;
 }
 
+/*
+ * TCP Westwood+
+ */
+
+/*
+ * @westwood_do_filter
+ * Low-pass filter. Implemented using constant coeffients.
+ */
+
+static inline __u32 westwood_do_filter(__u32 a, __u32 b)
+{
+	return (((7 * a) + b) >> 3);
+}
+
+static void westwood_filter(struct sock *sk, __u32 delta)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	tp->westwood.bw_ns_est =
+		westwood_do_filter(tp->westwood.bw_ns_est, 
+				   tp->westwood.bk / delta);
+	tp->westwood.bw_est =
+		westwood_do_filter(tp->westwood.bw_est,
+				   tp->westwood.bw_ns_est);
+}
+
+/* @westwood_update_rttmin
+ * It is used to update RTTmin. In this case we MUST NOT use
+ * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN!
+ */
+
+static inline __u32 westwood_update_rttmin(struct sock *sk)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	__u32 rttmin = tp->westwood.rtt_min;
+
+	if (tp->westwood.rtt == 0)
+		return rttmin;
+
+	if (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin)
+		rttmin = tp->westwood.rtt;
+
+	return rttmin;
+}
+
+/*
+ * @westwood_acked
+ * Evaluate increases for dk. 
+ */
+
+static __u32 westwood_acked(struct sock *sk)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	return ((tp->snd_una) - (tp->westwood.snd_una));
+}
+
+/*
+ * @westwood_new_window
+ * It evaluates if we are receiving data inside the same RTT window as
+ * when we started.
+ * Return value:
+ * It returns 0 if we are still evaluating samples in the same RTT
+ * window, 1 if the sample has to be considered in the next window.
+ */
+
+static int westwood_new_window(struct sock *sk)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	__u32 left_bound;
+	__u32 rtt;
+	int ret = 0;
+
+	left_bound = tp->westwood.rtt_win_sx;
+	rtt = max(tp->westwood.rtt, (__u32)TCP_WESTWOOD_RTT_MIN);
+
+	/*
+	 * A RTT-window has passed. Be careful since if RTT is less than
+	 * 50ms we don't filter but we continue 'building the sample'.
+	 * This minimum limit was choosen since an estimation on small
+	 * time intervals is better to avoid...
+	 * Obvioulsy on a LAN we reasonably will always have
+	 * right_bound = left_bound + WESTWOOD_RTT_MIN
+         */
+
+	if ((left_bound + rtt) < tcp_time_stamp)
+		ret = 1;
+
+	return ret;
+}
+
+/*
+ * @westwood_update_window
+ * It updates RTT evaluation window if it is the right moment to do
+ * it. If so it calls filter for evaluating bandwidth. 
+ */
+ 
+static void __westwood_update_window(struct sock *sk, __u32 now)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	__u32 delta = now - tp->westwood.rtt_win_sx;
+
+	if (!delta)
+		return;
+
+	if (tp->westwood.rtt)
+		westwood_filter(sk, delta);
+
+	tp->westwood.bk = 0;
+	tp->westwood.rtt_win_sx = tcp_time_stamp;
+}
+
+static void westwood_update_window(struct sock *sk, __u32 now)
+{
+	if (westwood_new_window(sk))
+		__westwood_update_window(sk, now);
+}
+
+/*
+ * @__tcp_westwood_fast_bw
+ * It is called when we are in fast path. In particular it is called when
+ * header prediction is successfull. In such case infact update is
+ * straight forward and doesn't need any particular care.
+ */
+
+void __tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	westwood_update_window(sk, tcp_time_stamp);
+
+	tp->westwood.bk += westwood_acked(sk);
+	tp->westwood.snd_una = tp->snd_una;
+	tp->westwood.rtt_min = westwood_update_rttmin(sk);
+}
+
+/*
+ * @westwood_mss
+ * This function was inserted just to have the possibility to evaluate
+ * which value of MSS is better. Infact we can use neither mss_cache or
+ * mss_cache. Just testing we will know it!
+ */
+
+static inline __u32 westwood_mss(struct tcp_opt *tp)
+{
+	return ((__u32)(tp->mss_cache));
+}
+
+/*
+ * @tcp_westwood_dupack_update
+ * It updates accounted and cumul_ack when receiving a dupack.
+ */
+
+static void westwood_dupack_update(struct sock *sk)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	tp->westwood.accounted += westwood_mss(tp);
+	tp->westwood.cumul_ack = westwood_mss(tp);
+}
+
+static inline int westwood_may_change_cumul(struct tcp_opt *tp)
+{
+	return ((tp->westwood.cumul_ack) > westwood_mss(tp));
+}
+
+static inline void westwood_partial_update(struct tcp_opt *tp)
+{
+	tp->westwood.accounted -= tp->westwood.cumul_ack;
+	tp->westwood.cumul_ack = westwood_mss(tp);
+}
+
+static inline void westwood_complete_update(struct tcp_opt *tp)
+{
+	tp->westwood.cumul_ack -= tp->westwood.accounted;
+	tp->westwood.accounted = 0;
+}
+
+/*
+ * @westwood_acked_count
+ * This function evaluates cumul_ack for evaluating dk in case of
+ * delayed or partial acks.
+ */
+
+static __u32 westwood_acked_count(struct sock *sk)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	tp->westwood.cumul_ack = westwood_acked(sk);
+
+	/* If cumul_ack is 0 this is a dupack since it's not moving
+	 * tp->snd_una.
+	 */
+	if (!(tp->westwood.cumul_ack))
+		westwood_dupack_update(sk);
+
+	if (westwood_may_change_cumul(tp)) {
+		/* Partial or delayed ack */
+		if ((tp->westwood.accounted) >= (tp->westwood.cumul_ack))
+			westwood_partial_update(tp);
+		else 
+			westwood_complete_update(tp);
+	}
+
+	tp->westwood.snd_una = tp->snd_una;
+
+	return tp->westwood.cumul_ack;
+}
+
+/*
+ * @__tcp_westwood_slow_bw
+ * It is called when something is going wrong..even if there could
+ * be no problems! Infact a simple delayed packet may trigger a
+ * dupack. But we need to be careful in such case.
+ */
+
+void __tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	westwood_update_window(sk, tcp_time_stamp);
+
+	tp->westwood.bk += westwood_acked_count(sk);
+	tp->westwood.rtt_min = westwood_update_rttmin(sk);
+}
+
+/* TCP Westwood+ routines end here */
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
 {
@@ -2042,6 +2291,7 @@ static int tcp_ack(struct sock *sk, stru
 		 */
 		tcp_update_wl(tp, ack, ack_seq);
 		tp->snd_una = ack;
+		tcp_westwood_fast_bw(sk, skb);
 		flag |= FLAG_WIN_UPDATE;
 
 		NET_INC_STATS_BH(TCPHPAcks);
@@ -2058,6 +2308,8 @@ static int tcp_ack(struct sock *sk, stru
 
 		if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th))
 			flag |= FLAG_ECE;
+
+		tcp_westwood_slow_bw(sk, skb);
 	}
 
 	/* We passed data and got it acked, remove any soft error
@@ -3796,7 +4048,6 @@ reset_and_undo:
 	return 1;
 }
 
-
 /*
  *	This function implements the receiving procedure of RFC 793 for
  *	all states except ESTABLISHED and TIME_WAIT. 
@@ -3827,6 +4078,8 @@ int tcp_rcv_state_process(struct sock *s
 			if(tp->af_specific->conn_request(sk, skb) < 0)
 				return 1;
 
+			tcp_init_westwood(sk);
+
 			/* Now we have several options: In theory there is 
 			 * nothing else in the frame. KA9Q has an option to 
 			 * send data with the syn, BSD accepts data with the
@@ -3848,6 +4101,8 @@ int tcp_rcv_state_process(struct sock *s
 		goto discard;
 
 	case TCP_SYN_SENT:
+		tcp_init_westwood(sk);
+
 		queued = tcp_rcv_synsent_state_process(sk, skb, th, len);
 		if (queued >= 0)
 			return queued;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/udp.c linux-2.4.26-pre6/net/ipv4/udp.c
--- linux-2.4.25/net/ipv4/udp.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv4/udp.c	2004-03-25 00:17:58.000000000 +0000
@@ -657,6 +657,7 @@ int udp_recvmsg(struct sock *sk, struct 
 	if (flags & MSG_ERRQUEUE)
 		return ip_recv_error(sk, msg, len);
 
+try_again:
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -722,7 +723,9 @@ csum_copy_err:
 
 	skb_free_datagram(sk, skb);
 
-	return -EAGAIN;	
+	if (noblock)
+		return -EAGAIN;	
+	goto try_again;
 }
 
 int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/exthdrs.c linux-2.4.26-pre6/net/ipv6/exthdrs.c
--- linux-2.4.25/net/ipv6/exthdrs.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/exthdrs.c	2004-03-25 00:17:15.000000000 +0000
@@ -798,8 +798,16 @@ int ipv6_skip_exthdr(struct sk_buff *skb
 		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
 			BUG();
 		if (nexthdr == NEXTHDR_FRAGMENT) {
-			struct frag_hdr *fhdr = (struct frag_hdr *) &hdr;
-			if (ntohs(fhdr->frag_off) & ~0x7)
+			unsigned short frag_off;
+			if (skb_copy_bits(skb,
+					  start+offsetof(struct frag_hdr,
+							 frag_off),
+					  &frag_off,
+					  sizeof(frag_off))) {
+				return -1;
+			}
+
+			if (ntohs(frag_off) & ~0x7)
 				break;
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/icmp.c linux-2.4.26-pre6/net/ipv6/icmp.c
--- linux-2.4.25/net/ipv6/icmp.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/icmp.c	2004-03-25 00:18:41.000000000 +0000
@@ -648,7 +648,13 @@ int __init icmpv6_init(struct net_proto_
 
 		sk = icmpv6_socket_cpu(i)->sk;
 		sk->allocation = GFP_ATOMIC;
-		sk->sndbuf = SK_WMEM_MAX*2;
+
+		/* Enough space for 2 64K ICMP packets, including
+		 * sk_buff struct overhead.
+		 */
+		sk->sndbuf =
+			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
+
 		sk->prot->unhash(sk);
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/ipv6_sockglue.c linux-2.4.26-pre6/net/ipv6/ipv6_sockglue.c
--- linux-2.4.25/net/ipv6/ipv6_sockglue.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/ipv6_sockglue.c	2004-03-25 00:17:25.000000000 +0000
@@ -452,10 +452,16 @@ done:
 	}
 	case MCAST_MSFILTER:
 	{
+		extern int sysctl_optmem_max;
+		extern int sysctl_mld_max_msf;
 		struct group_filter *gsf;
 
 		if (optlen < GROUP_FILTER_SIZE(0))
 			goto e_inval;
+		if (optlen > sysctl_optmem_max) {
+			retv = -ENOBUFS;
+			break;
+		}
 		gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
 		if (gsf == 0) {
 			retv = -ENOBUFS;
@@ -466,6 +472,18 @@ done:
 			kfree(gsf);
 			break;
 		}
+		/* numsrc >= (4G-140)/128 overflow in 32 bits */
+		if (gsf->gf_numsrc >= 0x1ffffffU ||
+		    gsf->gf_numsrc > sysctl_mld_max_msf) {
+			kfree(gsf);
+			retv = -ENOBUFS;
+			break;
+		}
+		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
+			kfree(gsf);
+			retv = -EINVAL;
+			break;
+		}
 		retv = ip6_mc_msfilter(sk, gsf);
 		kfree(gsf);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/ipv6_syms.c linux-2.4.26-pre6/net/ipv6/ipv6_syms.c
--- linux-2.4.25/net/ipv6/ipv6_syms.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/ipv6_syms.c	2004-03-25 00:19:21.000000000 +0000
@@ -33,3 +33,5 @@ EXPORT_SYMBOL(inet6_ioctl);
 EXPORT_SYMBOL(ipv6_get_saddr);
 EXPORT_SYMBOL(ipv6_chk_addr);
 EXPORT_SYMBOL(in6_dev_finish_destroy);
+EXPORT_SYMBOL(ipv6_skip_exthdr);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/mcast.c linux-2.4.26-pre6/net/ipv6/mcast.c
--- linux-2.4.25/net/ipv6/mcast.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/mcast.c	2004-03-25 00:21:45.000000000 +0000
@@ -163,6 +163,10 @@ int ip6_mc_leave_src(struct sock *sk, st
 #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
 #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value)
 
+#define IPV6_MLD_MAX_MSF	10
+
+int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF;
+
 /*
  *	socket join on multicast group
  */
@@ -401,6 +405,10 @@ int ip6_mc_source(int add, int omode, st
 	}
 	/* else, add a new source to the filter */
 
+	if (psl && psl->sl_count >= sysctl_mld_max_msf) {
+		err = -ENOBUFS;
+		goto done;
+	}
 	if (!psl || psl->sl_count == psl->sl_max) {
 		struct ip6_sf_socklist *newpsl;
 		int count = IP6_SFBLOCK;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/ndisc.c linux-2.4.26-pre6/net/ipv6/ndisc.c
--- linux-2.4.25/net/ipv6/ndisc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/ndisc.c	2004-03-25 00:20:29.000000000 +0000
@@ -1002,7 +1002,7 @@ static void ndisc_router_discovery(struc
 	 */
 
 	if (in6_dev->nd_parms) {
-		__u32 rtime = ntohl(ra_msg->retrans_timer);
+		unsigned long rtime = ntohl(ra_msg->retrans_timer);
 
 		if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
 			rtime = (rtime*HZ)/1000;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/netfilter/ip6_tables.c linux-2.4.26-pre6/net/ipv6/netfilter/ip6_tables.c
--- linux-2.4.25/net/ipv6/netfilter/ip6_tables.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/netfilter/ip6_tables.c	2004-03-25 00:21:50.000000000 +0000
@@ -1568,8 +1568,10 @@ tcp_match(const struct sk_buff *skb,
 	  u_int16_t datalen,
 	  int *hotdrop)
 {
-	const struct tcphdr *tcp = hdr;
+	const struct tcphdr *tcp;
 	const struct ip6t_tcp *tcpinfo = matchinfo;
+	int tcpoff;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
 	/* To quote Alan:
 
@@ -1590,6 +1592,24 @@ tcp_match(const struct sk_buff *skb,
 		return 0;
 	}
 
+	tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
+	if (tcpoff < 0 || tcpoff > skb->len) {
+		duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (nexthdr == IPPROTO_FRAGMENT)
+		return 0;
+	else if (nexthdr != IPPROTO_TCP ||
+		 skb->len - tcpoff < sizeof(struct tcphdr)) {
+		/* cannot be occured */
+		duprintf("tcp_match: cannot get TCP header. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	tcp = (struct tcphdr *)(skb->data + tcpoff);
+
 	/* FIXME: Try tcp doff >> packet len against various stacks --RR */
 
 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
@@ -1640,8 +1660,10 @@ udp_match(const struct sk_buff *skb,
 	  u_int16_t datalen,
 	  int *hotdrop)
 {
-	const struct udphdr *udp = hdr;
+	const struct udphdr *udp;
 	const struct ip6t_udp *udpinfo = matchinfo;
+	int udpoff;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
 	if (offset == 0 && datalen < sizeof(struct udphdr)) {
 		/* We've been asked to examine this packet, and we
@@ -1651,6 +1673,23 @@ udp_match(const struct sk_buff *skb,
 		return 0;
 	}
 
+	udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
+	if (udpoff < 0 || udpoff > skb->len) {
+		duprintf("udp_match: cannot skip exthdr. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (nexthdr == IPPROTO_FRAGMENT)
+		return 0;
+	else if (nexthdr != IPPROTO_UDP ||
+		 skb->len - udpoff < sizeof(struct udphdr)) {
+		duprintf("udp_match: cannot get UDP header. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	udp = (struct udphdr *)(skb->data + udpoff);
+
 	/* Must not be a fragment. */
 	return !offset
 		&& port_match(udpinfo->spts[0], udpinfo->spts[1],
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/sysctl_net_ipv6.c linux-2.4.26-pre6/net/ipv6/sysctl_net_ipv6.c
--- linux-2.4.25/net/ipv6/sysctl_net_ipv6.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/sysctl_net_ipv6.c	2004-03-25 00:17:26.000000000 +0000
@@ -24,6 +24,8 @@ ctl_table ipv6_table[] = {
 	{NET_IPV6_ICMP, "icmp", NULL, 0, 0500, ipv6_icmp_table},
 	{NET_IPV6_BINDV6ONLY, "bindv6only",
 	 &sysctl_ipv6_bindv6only, sizeof(int), 0644, NULL, &proc_dointvec},
+	{NET_IPV6_MLD_MAX_MSF, "mld_max_msf",
+	 &sysctl_mld_max_msf, sizeof(int), 0644, NULL, &proc_dointvec},
 	{0}
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/udp.c linux-2.4.26-pre6/net/ipv6/udp.c
--- linux-2.4.25/net/ipv6/udp.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/ipv6/udp.c	2004-03-25 00:21:31.000000000 +0000
@@ -400,6 +400,7 @@ int udpv6_recvmsg(struct sock *sk, struc
 	if (flags & MSG_ERRQUEUE)
 		return ipv6_recv_error(sk, msg, len);
 
+try_again:
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -476,12 +477,13 @@ csum_copy_err:
 			kfree_skb(skb);
 	}
 
-	/* Error for blocking case is chosen to masquerade
-	   as some normal condition.
-	 */
-	err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
-	UDP6_INC_STATS_USER(UdpInErrors);
-	goto out_free;
+	skb_free_datagram(sk, skb);
+
+	if (flags & MSG_DONTWAIT) {
+		UDP6_INC_STATS_USER(UdpInErrors);
+		return -EAGAIN;
+	}
+	goto try_again;
 }
 
 void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/netsyms.c linux-2.4.26-pre6/net/netsyms.c
--- linux-2.4.25/net/netsyms.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/netsyms.c	2004-03-25 00:19:21.000000000 +0000
@@ -40,6 +40,7 @@
 #ifdef CONFIG_NET
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
+extern int sysctl_optmem_max;
 #endif
 
 #ifdef CONFIG_INET
@@ -261,6 +262,8 @@ EXPORT_SYMBOL(icmp_statistics);
 EXPORT_SYMBOL(icmp_err_convert);
 EXPORT_SYMBOL(ip_options_compile);
 EXPORT_SYMBOL(ip_options_undo);
+EXPORT_SYMBOL(arp_create);
+EXPORT_SYMBOL(arp_xmit);
 EXPORT_SYMBOL(arp_send);
 EXPORT_SYMBOL(arp_broken_ops);
 EXPORT_SYMBOL(__ip_select_ident);
@@ -548,6 +551,7 @@ EXPORT_SYMBOL(netdev_fastroute);
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_wmem_max);
 EXPORT_SYMBOL(sysctl_rmem_max);
+EXPORT_SYMBOL(sysctl_optmem_max);
 #ifdef CONFIG_INET
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sched/sch_htb.c linux-2.4.26-pre6/net/sched/sch_htb.c
--- linux-2.4.25/net/sched/sch_htb.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/sched/sch_htb.c	2004-03-25 00:17:00.000000000 +0000
@@ -433,13 +433,13 @@ static void htb_add_to_wait_tree (struct
 		cl->pq_key++;
 
 	/* update the nearest event cache */
-	if (q->near_ev_cache[cl->level] - cl->pq_key < 0x80000000)
+	if (time_after(q->near_ev_cache[cl->level], cl->pq_key))
 		q->near_ev_cache[cl->level] = cl->pq_key;
 	
 	while (*p) {
 		struct htb_class *c; parent = *p;
 		c = rb_entry(parent, struct htb_class, pq_node);
-		if (cl->pq_key - c->pq_key < 0x80000000)
+		if (time_after_eq(cl->pq_key, c->pq_key))
 			p = &parent->rb_right;
 		else 
 			p = &parent->rb_left;
@@ -878,7 +878,7 @@ static long htb_do_events(struct htb_sch
 		while (p->rb_left) p = p->rb_left;
 
 		cl = rb_entry(p, struct htb_class, pq_node);
-		if (cl->pq_key - (q->jiffies+1) < 0x80000000) {
+		if (time_after(cl->pq_key, q->jiffies)) {
 			HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - q->jiffies);
 			return cl->pq_key - q->jiffies;
 		}
@@ -1057,7 +1057,7 @@ static struct sk_buff *htb_dequeue(struc
 		/* common case optimization - skip event handler quickly */
 		int m;
 		long delay;
-		if (q->jiffies - q->near_ev_cache[level] < 0x80000000 || 0) {
+		if (time_after_eq(q->jiffies, q->near_ev_cache[level])) {
 			delay = htb_do_events(q,level);
 			q->near_ev_cache[level] = q->jiffies + (delay ? delay : HZ);
 #ifdef HTB_DEBUG
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sched/sch_red.c linux-2.4.26-pre6/net/sched/sch_red.c
--- linux-2.4.25/net/sched/sch_red.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/sched/sch_red.c	2004-03-25 00:22:21.000000000 +0000
@@ -41,9 +41,6 @@
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
 
-#define RED_ECN_ECT  0x02
-#define RED_ECN_CE   0x01
-
 
 /*	Random Early Detection (RED) algorithm.
 	=======================================
@@ -165,28 +162,16 @@ static int red_ecn_mark(struct sk_buff *
 
 	switch (skb->protocol) {
 	case __constant_htons(ETH_P_IP):
-	{
-		u8 tos = skb->nh.iph->tos;
-
-		if (!(tos & RED_ECN_ECT))
+		if (!INET_ECN_is_capable(skb->nh.iph->tos))
 			return 0;
-
-		if (!(tos & RED_ECN_CE))
+		if (INET_ECN_is_not_ce(skb->nh.iph->tos))
 			IP_ECN_set_ce(skb->nh.iph);
-
 		return 1;
-	}
-
 	case __constant_htons(ETH_P_IPV6):
-	{
-		u32 label = *(u32*)skb->nh.raw;
-
-		if (!(label & __constant_htonl(RED_ECN_ECT<<20)))
+		if (!INET_ECN_is_capable(ip6_get_dsfield(skb->nh.ipv6h)))
 			return 0;
-		label |= __constant_htonl(RED_ECN_CE<<20);
+		IP6_ECN_set_ce(skb->nh.ipv6h);
 		return 1;
-	}
-
 	default:
 		return 0;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/Config.in linux-2.4.26-pre6/net/sctp/Config.in
--- linux-2.4.25/net/sctp/Config.in	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/Config.in	2004-03-25 00:21:20.000000000 +0000
@@ -12,9 +12,33 @@ fi
 
 dep_tristate '  The SCTP Protocol (EXPERIMENTAL)' CONFIG_IP_SCTP $CONFIG_IPV6_SCTP__
 if [ "$CONFIG_IP_SCTP" != "n" ]; then
-   bool '    SCTP: Use old checksum (Adler-32)' CONFIG_SCTP_ADLER32
    bool '    SCTP: Debug messages' CONFIG_SCTP_DBG_MSG
    bool '    SCTP: Debug object counts' CONFIG_SCTP_DBG_OBJCNT
 fi
-
+if [ "$CONFIG_CRYPTO_HMAC" = "n" ]; then
+  choice '    SCTP: Cookie HMAC Algorithm' \
+        "HMAC-NONE		CONFIG_SCTP_HMAC_NONE" HMAC-NONE
+else
+  if [ "$CONFIG_CRYPTO_MD5" = "n" -a "$CONFIG_CRYPTO_SHA1" = "n" ]; then
+    choice '    SCTP: Cookie HMAC Algorithm' \
+        "HMAC-NONE		CONFIG_SCTP_HMAC_NONE" HMAC-NONE
+  else
+    if [ "$CONFIG_CRYPTO_MD5" != "n" -a "$CONFIG_CRYPTO_SHA1" != "n" ]; then
+      choice '    SCTP: Cookie HMAC Algorithm' \
+        "HMAC-NONE		CONFIG_SCTP_HMAC_NONE \
+         HMAC-SHA1              CONFIG_SCTP_HMAC_SHA1 \
+         HMAC-MD5		CONFIG_SCTP_HMAC_MD5"	HMAC-SHA1
+    else
+      if [ "$CONFIG_CRYPTO_MD5" != "n" ]; then
+        choice 'SCTP: Cookie HMAC Algorithm' \
+        "HMAC-NONE		CONFIG_SCTP_HMAC_NONE \
+         HMAC-MD5		CONFIG_SCTP_HMAC_MD5"	HMAC-MD5
+      else
+        choice 'SCTP: Cookie HMAC Algorithm' \
+        "HMAC-NONE		CONFIG_SCTP_HMAC_NONE \
+         HMAC-SHA1		CONFIG_SCTP_HMAC_SHA1"	HMAC-SHA1
+      fi
+    fi
+  fi
+fi
 endmenu
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/Makefile linux-2.4.26-pre6/net/sctp/Makefile
--- linux-2.4.25/net/sctp/Makefile	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/Makefile	2004-03-25 00:18:59.000000000 +0000
@@ -6,16 +6,11 @@ O_TARGET := sctp.o
 
 obj-$(CONFIG_IP_SCTP) += sctp.o
 
-obj-y := endpointola.o output.o sm_make_chunk.o associola.o hashdriver.o \
+obj-y := endpointola.o output.o sm_make_chunk.o associola.o \
 	outqueue.o sm_sideeffect.o transport.o bind_addr.o input.o primitive.o \
 	sm_statefuns.o tsnmap.o command.o inqueue.o proc.o sm_statetable.o \
-	ulpevent.o protocol.o socket.o ulpqueue.o debug.o sla1.o ssnmap.o
-
-ifeq ($(CONFIG_SCTP_ADLER32), y)
-obj-y += adler32.o
-else
-obj-y += crc32c.o
-endif
+	ulpevent.o protocol.o socket.o ulpqueue.o debug.o ssnmap.o \
+	crc32c.o chunk.o
 
 obj-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/associola.c linux-2.4.26-pre6/net/sctp/associola.c
--- linux-2.4.25/net/sctp/associola.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/associola.c	2004-03-25 00:19:15.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 International Business Machines Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
@@ -41,6 +41,8 @@
  *    Hui Huang             <hui.huang@nokia.com>
  *    Sridhar Samudrala	    <sri@us.ibm.com>
  *    Daisy Chang	    <daisyc@us.ibm.com>
+ *    Ryan Layer	    <rmlayer@us.ibm.com>
+ *    Kevin Gao             <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -97,7 +99,6 @@ struct sctp_association *sctp_associatio
 					  int gfp)
 {
 	struct sctp_opt *sp;
-	struct sctp_protocol *proto = sctp_get_protocol();
 	int i;
 
 	/* Retrieve the SCTP per socket area.  */
@@ -127,29 +128,30 @@ struct sctp_association *sctp_associatio
 	asoc->base.addr_lock = RW_LOCK_UNLOCKED;
 
 	asoc->state = SCTP_STATE_CLOSED;
-	asoc->state_timestamp = jiffies;
-
-	/* Set things that have constant value.  */
-	asoc->cookie_life.tv_sec = sctp_proto.valid_cookie_life / HZ;
-	asoc->cookie_life.tv_usec = (sctp_proto.valid_cookie_life % HZ) *
-					1000000L / HZ;
 
+	/* Set these values from the socket values, a conversion between
+	 * millsecons to seconds/microseconds must also be done.
+	 */
+	asoc->cookie_life.tv_sec = sp->assocparams.sasoc_cookie_life / 1000;
+	asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
+					* 1000;
 	asoc->pmtu = 0;
 	asoc->frag_point = 0;
 
-	/* Initialize the default association max_retrans and RTO values.  */
-	asoc->max_retrans = proto->max_retrans_association;
-	asoc->rto_initial = proto->rto_initial;
-	asoc->rto_max = proto->rto_max;
-	asoc->rto_min = proto->rto_min;
+	/* Set the association max_retrans and RTO values from the
+	 * socket values.
+	 */
+	asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
+	asoc->rto_initial = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
+	asoc->rto_max = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
+	asoc->rto_min = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_min);
 
-	asoc->overall_error_threshold = 0;
 	asoc->overall_error_count = 0;
 
 	/* Initialize the maximum mumber of new data packets that can be sent
 	 * in a burst.
 	 */
-	asoc->max_burst = proto->max_burst;
+	asoc->max_burst = sctp_max_burst;
 
 	/* Copy things from the endpoint.  */
 	for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
@@ -166,7 +168,9 @@ struct sctp_association *sctp_associatio
 	asoc->c.sinit_max_instreams = sp->initmsg.sinit_max_instreams;
 	asoc->c.sinit_num_ostreams  = sp->initmsg.sinit_num_ostreams;
 	asoc->max_init_attempts	= sp->initmsg.sinit_max_attempts;
-	asoc->max_init_timeo    = sp->initmsg.sinit_max_init_timeo * HZ;
+
+	asoc->max_init_timeo =
+		 SCTP_MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo);
 
 	/* Allocate storage for the ssnmap after the inbound and outbound
 	 * streams have been negotiated during Init.
@@ -178,10 +182,10 @@ struct sctp_association *sctp_associatio
 	 * RFC 6 - A SCTP receiver MUST be able to receive a minimum of
 	 * 1500 bytes in one SCTP packet.
 	 */
-	if (sk->rcvbuf < SCTP_DEFAULT_MINWINDOW)
+	if (sk->sk_rcvbuf < SCTP_DEFAULT_MINWINDOW)
 		asoc->rwnd = SCTP_DEFAULT_MINWINDOW;
 	else
-		asoc->rwnd = sk->rcvbuf;
+		asoc->rwnd = sk->sk_rcvbuf;
 
 	asoc->a_rwnd = asoc->rwnd;
 
@@ -220,12 +224,14 @@ struct sctp_association *sctp_associatio
 	 * remote endpoint it should do the following:
 	 * ...
 	 * A2) a serial number should be assigned to the chunk. The serial
-	 * number should be a monotonically increasing number. All serial
-	 * numbers are defined to be initialized at the start of the
+	 * number SHOULD be a monotonically increasing number. The serial
+	 * numbers SHOULD be initialized at the start of the
 	 * association to the same value as the initial TSN.
 	 */
 	asoc->addip_serial = asoc->c.initial_tsn;
 
+	skb_queue_head_init(&asoc->addip_chunks);
+
 	/* Make an empty list of remote transport addresses.  */
 	INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
 
@@ -242,6 +248,11 @@ struct sctp_association *sctp_associatio
 	 */
 	asoc->peer.sack_needed = 1;
 
+	/* Assume that the peer recongizes ASCONF until reported otherwise
+	 * via an ERROR chunk.
+	 */
+	asoc->peer.asconf_capable = 1;
+
 	/* Create an input queue.  */
 	sctp_inq_init(&asoc->base.inqueue);
 	sctp_inq_set_th_handler(&asoc->base.inqueue,
@@ -257,17 +268,14 @@ struct sctp_association *sctp_associatio
 				      sctp_packet_transmit_chunk,
 				      sctp_packet_transmit);
 
-	if (NULL == sctp_ulpq_init(&asoc->ulpq, asoc))
+	if (!sctp_ulpq_init(&asoc->ulpq, asoc))
 		goto fail_init;
 
 	/* Set up the tsn tracking. */
 	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, 0);
 
-	skb_queue_head_init(&asoc->addip_chunks);
-
 	asoc->need_ecne = 0;
 
-	asoc->debug_name = "unnamedasoc";
 	asoc->eyecatcher = SCTP_ASSOC_EYECATCHER;
 
 	/* Assume that peer would support both address types unless we are
@@ -279,6 +287,12 @@ struct sctp_association *sctp_associatio
 
 	asoc->autoclose = sp->autoclose;
 
+	asoc->default_stream = sp->default_stream;
+	asoc->default_ppid = sp->default_ppid;
+	asoc->default_flags = sp->default_flags;
+	asoc->default_context = sp->default_context;
+	asoc->default_timetolive = sp->default_timetolive;
+
 	return asoc;
 
 fail_init:
@@ -300,9 +314,8 @@ void sctp_association_free(struct sctp_a
 	list_del(&asoc->asocs);
 
 	/* Decrement the backlog value for a TCP-style listening socket. */
-	if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) &&
-	    (SCTP_SS_LISTENING == sk->state))
-		sk->ack_backlog--;
+	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
+		sk->sk_ack_backlog--;
 
 	/* Mark as dead, so other users can know this structure is
 	 * going away.
@@ -349,6 +362,14 @@ void sctp_association_free(struct sctp_a
 
 	asoc->eyecatcher = 0;
 
+	/* Free any cached ASCONF_ACK chunk. */
+	if (asoc->addip_last_asconf_ack)
+		sctp_chunk_free(asoc->addip_last_asconf_ack);
+
+	/* Free any cached ASCONF chunk. */
+	if (asoc->addip_last_asconf)
+		sctp_chunk_free(asoc->addip_last_asconf);
+
 	sctp_association_put(asoc);
 }
 
@@ -381,6 +402,30 @@ void sctp_assoc_set_primary(struct sctp_
 	 */
 	if (transport->active)
 		asoc->peer.active_path = transport;
+
+	/*
+	 * SFR-CACC algorithm:
+	 * Upon the receipt of a request to change the primary
+	 * destination address, on the data structure for the new
+	 * primary destination, the sender MUST do the following:
+	 *
+	 * 1) If CHANGEOVER_ACTIVE is set, then there was a switch
+	 * to this destination address earlier. The sender MUST set
+	 * CYCLING_CHANGEOVER to indicate that this switch is a
+	 * double switch to the same destination address.
+	 */
+	if (transport->cacc.changeover_active)
+		transport->cacc.cycling_changeover = 1;
+
+	/* 2) The sender MUST set CHANGEOVER_ACTIVE to indicate that
+	 * a changeover has occurred.
+	 */
+	transport->cacc.changeover_active = 1;
+
+	/* 3) The sender MUST store the next TSN to be sent in
+	 * next_tsn_at_change.
+	 */
+	transport->cacc.next_tsn_at_change = asoc->next_tsn;
 }
 
 /* Add a transport address to an association.  */
@@ -392,13 +437,14 @@ struct sctp_transport *sctp_assoc_add_pe
 	struct sctp_opt *sp;
 	unsigned short port;
 
+	sp = sctp_sk(asoc->base.sk);
+
 	/* AF_INET and AF_INET6 share common port field. */
 	port = addr->v4.sin_port;
 
 	/* Set the port if it has not been set yet.  */
-	if (0 == asoc->peer.port) {
+	if (0 == asoc->peer.port)
 		asoc->peer.port = port;
-	}
 
 	/* Check to see if this is a duplicate. */
 	peer = sctp_assoc_lookup_paddr(asoc, addr);
@@ -427,7 +473,7 @@ struct sctp_transport *sctp_assoc_add_pe
 	SCTP_DEBUG_PRINTK("sctp_assoc_add_peer:association %p PMTU set to "
 			  "%d\n", asoc, asoc->pmtu);
 
-	asoc->frag_point = sctp_frag_point(asoc->pmtu);
+	asoc->frag_point = sctp_frag_point(sp, asoc->pmtu);
 
 	/* The asoc->peer.port might not be meaningful yet, but
 	 * initialize the packet structure anyway.
@@ -456,30 +502,27 @@ struct sctp_transport *sctp_assoc_add_pe
 
 	peer->partial_bytes_acked = 0;
 	peer->flight_size = 0;
-
 	peer->error_threshold = peer->max_retrans;
 
-	/* Update the overall error threshold value of the association
-	 * taking the new peer's error threshold into account.
-	 */
-	asoc->overall_error_threshold =
-		min(asoc->overall_error_threshold + peer->error_threshold,
-		    asoc->max_retrans);
-
 	/* By default, enable heartbeat for peer address. */
 	peer->hb_allowed = 1;
 
 	/* Initialize the peer's heartbeat interval based on the
 	 * sock configured value.
 	 */
-	sp = sctp_sk(asoc->base.sk);
-	peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ;
+	peer->hb_interval = SCTP_MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval);
+
+	/* Set the path max_retrans.  */
+	peer->max_retrans = asoc->max_retrans;
+
+	/* Set the transport's RTO.initial value */
+	peer->rto = asoc->rto_initial;
 
 	/* Attach the remote transport to our asoc.  */
 	list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
 
 	/* If we do not yet have a primary path, set one.  */
-	if (NULL == asoc->peer.primary_path) {
+	if (!asoc->peer.primary_path) {
 		sctp_assoc_set_primary(asoc, peer);
 		asoc->peer.retran_path = peer;
 	}
@@ -490,6 +533,45 @@ struct sctp_transport *sctp_assoc_add_pe
 	return peer;
 }
 
+/* Delete a transport address from an association.  */
+void sctp_assoc_del_peer(struct sctp_association *asoc,
+			 const union sctp_addr *addr)
+{
+	struct list_head	*pos;
+	struct list_head	*temp;
+	struct sctp_transport	*peer = NULL;
+	struct sctp_transport	*transport;
+
+	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+		transport = list_entry(pos, struct sctp_transport, transports);
+		if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) {
+			peer = transport;
+			list_del(pos);
+			break;
+		}
+	}
+
+	/* The address we want delete is not in the association. */
+	if (!peer)
+		return;
+
+	/* Get the first transport of asoc. */ 
+	pos = asoc->peer.transport_addr_list.next;
+	transport = list_entry(pos, struct sctp_transport, transports);
+
+	/* Update any entries that match the peer to be deleted. */  
+	if (asoc->peer.primary_path == peer)
+		sctp_assoc_set_primary(asoc, transport);
+	if (asoc->peer.active_path == peer)
+		asoc->peer.active_path = transport;
+	if (asoc->peer.retran_path == peer)
+		asoc->peer.retran_path = transport;
+	if (asoc->peer.last_data_from == peer)
+		asoc->peer.last_data_from = transport;
+
+	sctp_transport_free(peer);
+}
+
 /* Lookup a transport by address. */
 struct sctp_transport *sctp_assoc_lookup_paddr(
 					const struct sctp_association *asoc,
@@ -528,13 +610,13 @@ void sctp_assoc_control_transport(struct
 	/* Record the transition on the transport.  */
 	switch (command) {
 	case SCTP_TRANSPORT_UP:
-		transport->active = 1;
-		spc_state = ADDRESS_AVAILABLE;
+		transport->active = SCTP_ACTIVE;
+		spc_state = SCTP_ADDR_REACHABLE;
 		break;
 
 	case SCTP_TRANSPORT_DOWN:
-		transport->active = 0;
-		spc_state = ADDRESS_UNREACHABLE;
+		transport->active = SCTP_INACTIVE;
+		spc_state = SCTP_ADDR_UNREACHABLE;
 		break;
 
 	default:
@@ -592,7 +674,7 @@ void sctp_assoc_control_transport(struct
 	/* If we failed to find a usable transport, just camp on the
 	 * primary, even if it is inactive.
 	 */
-	if (NULL == first) {
+	if (!first) {
 		first = asoc->peer.primary_path;
 		second = asoc->peer.primary_path;
 	}
@@ -665,7 +747,7 @@ int sctp_cmp_addr_exact(const union sctp
  * Note:  We are sly and return a shared, prealloced chunk.  FIXME:
  * No we don't, but we could/should.
  */
-sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc)
+struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc)
 {
 	struct sctp_chunk *chunk;
 
@@ -683,7 +765,7 @@ sctp_chunk_t *sctp_get_ecne_prepend(stru
 /* Use this function for the packet prepend callback when no ECNE
  * packet is desired (e.g. some packets don't like to be bundled).
  */
-sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc)
+struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc)
 {
 	return NULL;
 }
@@ -691,13 +773,14 @@ sctp_chunk_t *sctp_get_no_prepend(struct
 /*
  * Find which transport this TSN was sent on.
  */
-struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u32 tsn)
+struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+					     __u32 tsn)
 {
 	struct sctp_transport *active;
 	struct sctp_transport *match;
 	struct list_head *entry, *pos;
 	struct sctp_transport *transport;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	__u32 key = htonl(tsn);
 
 	match = NULL;
@@ -720,7 +803,7 @@ struct sctp_transport *sctp_assoc_lookup
 	active = asoc->peer.active_path;
 
 	list_for_each(entry, &active->transmitted) {
-		chunk = list_entry(entry, sctp_chunk_t, transmitted_list);
+		chunk = list_entry(entry, struct sctp_chunk, transmitted_list);
 
 		if (key == chunk->subh.data_hdr->tsn) {
 			match = active;
@@ -735,7 +818,7 @@ struct sctp_transport *sctp_assoc_lookup
 		if (transport == active)
 			break;
 		list_for_each(entry, &transport->transmitted) {
-			chunk = list_entry(entry, sctp_chunk_t,
+			chunk = list_entry(entry, struct sctp_chunk,
 					   transmitted_list);
 			if (key == chunk->subh.data_hdr->tsn) {
 				match = transport;
@@ -773,15 +856,34 @@ out:
 	return transport;
 }
 
+/*  Is this a live association structure. */
+int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc)
+{
+
+	/* First, verify that this is a kernel address. */
+	if (!sctp_is_valid_kaddr((unsigned long) asoc))
+		return 0;
+
+	/* Verify that this _is_ an sctp_association
+	 * data structure and if so, that the socket matches.
+	 */
+	if (SCTP_ASSOC_EYECATCHER != asoc->eyecatcher)
+		return 0;
+	if (asoc->base.sk != sk)
+		return 0;
+
+	/* The association is valid. */
+	return 1;
+}
+
 /* Do delayed input processing.  This is scheduled by sctp_rcv(). */
 static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
 {
 	struct sctp_endpoint *ep;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	struct sock *sk;
 	struct sctp_inq *inqueue;
 	int state, subtype;
-	sctp_assoc_t associd = sctp_assoc2id(asoc);
 	int error = 0;
 
 	/* The association should be held so we should be safe. */
@@ -811,7 +913,7 @@ static void sctp_assoc_bh_rcv(struct sct
 		/* Check to see if the association is freed in response to
 		 * the incoming chunk.  If so, get out of the while loop.
 		 */
-		if (!sctp_id2assoc(sk, associd))
+		if (!sctp_assoc_valid(sk, asoc))
 			break;
 
 		/* If there is an error on chunk, discard this packet. */
@@ -830,11 +932,11 @@ void sctp_assoc_migrate(struct sctp_asso
 	/* Delete the association from the old endpoint's list of
 	 * associations.
 	 */
-	list_del(&assoc->asocs);
+	list_del_init(&assoc->asocs);
 
 	/* Decrement the backlog value for a TCP-style socket. */
-	if (SCTP_SOCKET_TCP == sctp_sk(oldsk)->type)
-		oldsk->ack_backlog--;
+	if (sctp_style(oldsk, TCP))
+		oldsk->sk_ack_backlog--;
 
 	/* Release references to the old endpoint and the sock.  */
 	sctp_endpoint_put(assoc->ep);
@@ -853,7 +955,8 @@ void sctp_assoc_migrate(struct sctp_asso
 }
 
 /* Update an association (possibly from unexpected COOKIE-ECHO processing).  */
-void sctp_assoc_update(struct sctp_association *asoc, struct sctp_association *new)
+void sctp_assoc_update(struct sctp_association *asoc,
+		       struct sctp_association *new)
 {
 	/* Copy in new parameters of peer. */
 	asoc->c = new->c;
@@ -875,7 +978,7 @@ void sctp_assoc_update(struct sctp_assoc
 	 * current next_tsn in case data sent to peer
 	 * has been discarded and needs retransmission.
 	 */
-	if (SCTP_STATE_ESTABLISHED == asoc->state) {
+	if (sctp_state(asoc, ESTABLISHED)) {
 
 		asoc->next_tsn = new->next_tsn;
 		asoc->ctsn_ack_point = new->ctsn_ack_point;
@@ -947,7 +1050,8 @@ void sctp_assoc_update_retran_path(struc
 }
 
 /* Choose the transport for sending a SHUTDOWN packet.  */
-struct sctp_transport *sctp_assoc_choose_shutdown_transport(struct sctp_association *asoc)
+struct sctp_transport *sctp_assoc_choose_shutdown_transport(
+	struct sctp_association *asoc)
 {
 	/* If this is the first time SHUTDOWN is sent, use the active path,
 	 * else use the retran path. If the last SHUTDOWN was sent over the
@@ -983,8 +1087,9 @@ void sctp_assoc_sync_pmtu(struct sctp_as
 	}
 
 	if (pmtu) {
+		struct sctp_opt *sp = sctp_sk(asoc->base.sk);
 		asoc->pmtu = pmtu;
-		asoc->frag_point = sctp_frag_point(pmtu);
+		asoc->frag_point = sctp_frag_point(sp, pmtu);
 	}
 
 	SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",
@@ -1000,7 +1105,7 @@ static inline int sctp_peer_needs_update
 	case SCTP_STATE_SHUTDOWN_RECEIVED:
 		if ((asoc->rwnd > asoc->a_rwnd) &&
 		    ((asoc->rwnd - asoc->a_rwnd) >=
-		     min_t(__u32, (asoc->base.sk->rcvbuf >> 1), asoc->pmtu)))
+		     min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu)))
 			return 1;
 		break;
 	default:
@@ -1010,9 +1115,9 @@ static inline int sctp_peer_needs_update
 }
 
 /* Increase asoc's rwnd by len and send any window update SACK if needed. */
-void sctp_assoc_rwnd_increase(struct sctp_association *asoc, int len)
+void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
 {
-	sctp_chunk_t *sack;
+	struct sctp_chunk *sack;
 	struct timer_list *timer;
 
 	if (asoc->rwnd_over) {
@@ -1056,7 +1161,7 @@ void sctp_assoc_rwnd_increase(struct sct
 }
 
 /* Decrease asoc's rwnd by len. */
-void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, int len)
+void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
 {
 	SCTP_ASSERT(asoc->rwnd, "rwnd zero", return);
 	SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return);
@@ -1083,7 +1188,7 @@ int sctp_assoc_set_bind_addr_from_ep(str
 	 * the endpoint.
 	 */
 	scope = sctp_scope(&asoc->peer.active_path->ipaddr);
-	flags = (PF_INET6 == asoc->base.sk->family) ? SCTP_ADDR6_ALLOWED : 0;
+	flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
 	if (asoc->peer.ipv4_address)
 		flags |= SCTP_ADDR4_PEERSUPP;
 	if (asoc->peer.ipv6_address)
@@ -1096,12 +1201,32 @@ int sctp_assoc_set_bind_addr_from_ep(str
 
 /* Build the association's bind address list from the cookie.  */
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
-					 sctp_cookie_t *cookie, int gfp)
+					 struct sctp_cookie *cookie, int gfp)
 {
 	int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length);
 	int var_size3 = cookie->raw_addr_list_len;
-	__u8 *raw = (__u8 *)cookie + sizeof(sctp_cookie_t) + var_size2;
+	__u8 *raw = (__u8 *)cookie + sizeof(struct sctp_cookie) + var_size2;
 
 	return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3,
 				      asoc->ep->base.bind_addr.port, gfp);
 }
+
+/* Lookup laddr in the bind address list of an association. */ 
+int sctp_assoc_lookup_laddr(struct sctp_association *asoc, 
+			    const union sctp_addr *laddr)
+{
+	int found;
+
+	sctp_read_lock(&asoc->base.addr_lock);
+	if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) &&
+	    sctp_bind_addr_match(&asoc->base.bind_addr, laddr,
+			         sctp_sk(asoc->base.sk))) {
+		found = 1;
+		goto out;
+	}
+
+	found = 0;
+out:
+	sctp_read_unlock(&asoc->base.addr_lock);
+	return found;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/bind_addr.c linux-2.4.26-pre6/net/sctp/bind_addr.c
--- linux-2.4.25/net/sctp/bind_addr.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/bind_addr.c	2004-03-25 00:20:12.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) Cisco 1999,2000
  * Copyright (c) Motorola 1999,2000,2001
- * Copyright (c) International Business Machines Corp., 2001,2002
  * Copyright (c) La Monte H.P. Yarroll 2001
  *
  * This file is part of the SCTP kernel reference implementation.
@@ -52,19 +52,20 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers. */
-static int sctp_copy_one_addr(sctp_bind_addr_t *, union sctp_addr *,
+static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
 			      sctp_scope_t scope, int gfp, int flags);
-static void sctp_bind_addr_clean(sctp_bind_addr_t *);
+static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 
 /* First Level Abstractions. */
 
 /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
  * in 'src' which have a broader scope than 'scope'.
  */
-int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
+int sctp_bind_addr_copy(struct sctp_bind_addr *dest, 
+			const struct sctp_bind_addr *src,
 			sctp_scope_t scope, int gfp, int flags)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos;
 	int error = 0;
 
@@ -73,7 +74,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t
 
 	/* Extract the addresses which are relevant for this scope.  */
 	list_for_each(pos, &src->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		error = sctp_copy_one_addr(dest, &addr->a, scope,
 					   gfp, flags);
 		if (error < 0)
@@ -86,7 +87,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t
 	 */
 	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
 		list_for_each(pos, &src->address_list) {
-			addr = list_entry(pos, struct sockaddr_storage_list,
+			addr = list_entry(pos, struct sctp_sockaddr_entry,
 					  list);
 			error = sctp_copy_one_addr(dest, &addr->a,
 						   SCTP_SCOPE_LINK, gfp,
@@ -104,11 +105,11 @@ out:
 }
 
 /* Create a new SCTP_bind_addr from nothing.  */
-sctp_bind_addr_t *sctp_bind_addr_new(int gfp)
+struct sctp_bind_addr *sctp_bind_addr_new(int gfp)
 {
-	sctp_bind_addr_t *retval;
+	struct sctp_bind_addr *retval;
 
-	retval = t_new(sctp_bind_addr_t, gfp);
+	retval = t_new(struct sctp_bind_addr, gfp);
 	if (!retval)
 		goto nomem;
 
@@ -123,7 +124,7 @@ nomem:
 /* Initialize the SCTP_bind_addr structure for either an endpoint or
  * an association.
  */
-void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port)
+void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
 {
 	bp->malloced = 0;
 
@@ -132,14 +133,14 @@ void sctp_bind_addr_init(sctp_bind_addr_
 }
 
 /* Dispose of the address list. */
-static void sctp_bind_addr_clean(sctp_bind_addr_t *bp)
+static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos, *temp;
 
 	/* Empty the bind address list. */
 	list_for_each_safe(pos, temp, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		list_del(pos);
 		kfree(addr);
 		SCTP_DBG_OBJCNT_DEC(addr);
@@ -147,7 +148,7 @@ static void sctp_bind_addr_clean(sctp_bi
 }
 
 /* Dispose of an SCTP_bind_addr structure  */
-void sctp_bind_addr_free(sctp_bind_addr_t *bp)
+void sctp_bind_addr_free(struct sctp_bind_addr *bp)
 {
 	/* Empty the bind address list. */
 	sctp_bind_addr_clean(bp);
@@ -159,17 +160,17 @@ void sctp_bind_addr_free(sctp_bind_addr_
 }
 
 /* Add an address to the bind address list in the SCTP_bind_addr structure. */
-int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new,
+int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
 		       int gfp)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 
 	/* Add the address to the bind address list.  */
-	addr = t_new(struct sockaddr_storage_list, gfp);
+	addr = t_new(struct sctp_sockaddr_entry, gfp);
 	if (!addr)
 		return -ENOMEM;
 
-	addr->a = *new;
+	memcpy(&addr->a, new, sizeof(*new));
 
 	/* Fix up the port if it has not yet been set.
 	 * Both v4 and v6 have the port at the same offset.
@@ -187,13 +188,13 @@ int sctp_add_bind_addr(sctp_bind_addr_t 
 /* Delete an address from the bind address list in the SCTP_bind_addr
  * structure.
  */
-int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr)
+int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
 {
 	struct list_head *pos, *temp;
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 
 	list_for_each_safe(pos, temp, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
 			/* Found the exact match. */
 			list_del(pos);
@@ -212,28 +213,30 @@ int sctp_del_bind_addr(sctp_bind_addr_t 
  *
  * The second argument is the return value for the length.
  */
-union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
+union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
 					 int *addrs_len, int gfp)
 {
 	union sctp_params addrparms;
 	union sctp_params retval;
 	int addrparms_len;
-	sctp_addr_param_t rawaddr;
+	union sctp_addr_param rawaddr;
 	int len;
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos;
+	struct sctp_af *af;
+
 	addrparms_len = 0;
 	len = 0;
 
 	/* Allocate enough memory at once. */
 	list_for_each(pos, &bp->address_list) {
-		len += sizeof(sctp_addr_param_t);
+		len += sizeof(union sctp_addr_param);
 	}
 
 	/* Don't even bother embedding an address if there
 	 * is only one.
 	 */
-	if (len == sizeof(sctp_addr_param_t)) {
+	if (len == sizeof(union sctp_addr_param)) {
 		retval.v = NULL;
 		goto end_raw;
 	}
@@ -245,8 +248,9 @@ union sctp_params sctp_bind_addrs_to_raw
 	addrparms = retval;
 
 	list_for_each(pos, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
-		len = sockaddr2sctp_addr(&addr->a, &rawaddr);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+		af = sctp_get_af_specific(addr->a.v4.sin_family);
+		len = af->to_addr_param(&addr->a, &rawaddr);
 		memcpy(addrparms.v, &rawaddr, len);
 		addrparms.v += len;
 		addrparms_len += len;
@@ -261,42 +265,39 @@ end_raw:
  * Create an address list out of the raw address list format (IPv4 and IPv6
  * address parameters).
  */
-int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
+int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
 			   int addrs_len, __u16 port, int gfp)
 {
-	sctp_addr_param_t *rawaddr;
-	sctp_paramhdr_t *param;
+	union sctp_addr_param *rawaddr;
+	struct sctp_paramhdr *param;
 	union sctp_addr addr;
 	int retval = 0;
 	int len;
+	struct sctp_af *af;
 
 	/* Convert the raw address to standard address format */
 	while (addrs_len) {
-		param = (sctp_paramhdr_t *)raw_addr_list;
-		rawaddr = (sctp_addr_param_t *)raw_addr_list;
+		param = (struct sctp_paramhdr *)raw_addr_list;
+		rawaddr = (union sctp_addr_param *)raw_addr_list;
 
-		switch (param->type) {
-		case SCTP_PARAM_IPV4_ADDRESS:
-		case SCTP_PARAM_IPV6_ADDRESS:
-			sctp_param2sockaddr(&addr, rawaddr, port, 0);
-			retval = sctp_add_bind_addr(bp, &addr, gfp);
-			if (retval) {
-				/* Can't finish building the list, clean up. */
-				sctp_bind_addr_clean(bp);
-				break;;
-			}
-			len = ntohs(param->length);
-			addrs_len -= len;
-			raw_addr_list += len;
-			break;
-		default:
-			/* Corrupted raw addr list! */
+		af = sctp_get_af_specific(param_type2af(param->type));
+		if (unlikely(!af)) {
 			retval = -EINVAL;
 			sctp_bind_addr_clean(bp);
 			break;
 		}
-		if (retval)
-			break;
+
+		af->from_addr_param(&addr, rawaddr, port, 0);
+		retval = sctp_add_bind_addr(bp, &addr, gfp);
+		if (retval) {
+			/* Can't finish building the list, clean up. */
+			sctp_bind_addr_clean(bp);
+			break;;
+		}
+
+		len = ntohs(param->length);
+		addrs_len -= len;
+		raw_addr_list += len;
 	}
 
 	return retval;
@@ -307,14 +308,15 @@ int sctp_raw_to_bind_addrs(sctp_bind_add
  ********************************************************************/
 
 /* Does this contain a specified address?  Allow wildcarding. */
-int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
+int sctp_bind_addr_match(struct sctp_bind_addr *bp, 
+			 const union sctp_addr *addr,
 			 struct sctp_opt *opt)
 {
-	struct sockaddr_storage_list *laddr;
+	struct sctp_sockaddr_entry *laddr;
 	struct list_head *pos;
 
 	list_for_each(pos, &bp->address_list) {
-		laddr = list_entry(pos, struct sockaddr_storage_list, list);
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (opt->pf->cmp_addr(&laddr->a, addr, opt))
  			return 1;
 	}
@@ -322,16 +324,52 @@ int sctp_bind_addr_match(sctp_bind_addr_
 	return 0;
 }
 
+/* Find the first address in the bind address list that is not present in
+ * the addrs packed array.
+ */
+union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
+					const union sctp_addr	*addrs,
+					int			addrcnt,
+					struct sctp_opt		*opt)
+{
+	struct sctp_sockaddr_entry	*laddr;
+	union sctp_addr			*addr;
+	void 				*addr_buf;
+	struct sctp_af			*af;
+	struct list_head		*pos;
+	int				i;
+
+	list_for_each(pos, &bp->address_list) {
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
+		
+		addr_buf = (union sctp_addr *)addrs;
+		for (i = 0; i < addrcnt; i++) {
+			addr = (union sctp_addr *)addr_buf;
+			af = sctp_get_af_specific(addr->v4.sin_family);
+			if (!af) 
+				return NULL;
+
+			if (opt->pf->cmp_addr(&laddr->a, addr, opt))
+				break;
+
+			addr_buf += af->sockaddr_len;
+		}
+		if (i == addrcnt)
+			return &laddr->a;
+	}
+
+	return NULL;
+}
+
 /* Copy out addresses from the global local address list. */
-static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr,
+static int sctp_copy_one_addr(struct sctp_bind_addr *dest, 
+			      union sctp_addr *addr,
 			      sctp_scope_t scope, int gfp, int flags)
 {
-	struct sctp_protocol *proto = sctp_get_protocol();
 	int error = 0;
 
 	if (sctp_is_any(addr)) {
-		error = sctp_copy_local_addr_list(proto, dest, scope,
-						  gfp, flags);
+		error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
 	} else if (sctp_in_scope(addr, scope)) {
 		/* Now that the address is in scope, check to see if
 		 * the address type is supported by local sock as
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/chunk.c linux-2.4.26-pre6/net/sctp/chunk.c
--- linux-2.4.25/net/sctp/chunk.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/chunk.c	2004-03-25 00:17:31.000000000 +0000
@@ -0,0 +1,323 @@
+/* SCTP kernel reference Implementation
+ * Copyright (c) 2003 International Business Machines Corp.
+ *
+ * This file is part of the SCTP kernel reference Implementation
+ *
+ * This file contains the code relating the the chunk abstraction.
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * The SCTP reference implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ *                 ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ *    http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ *    Jon Grimm             <jgrimm@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/inet.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/sctp/sctp.h>
+#include <net/sctp/sm.h>
+
+/* This file is mostly in anticipation of future work, but initially
+ * populate with fragment tracking for an outbound message.
+ */
+
+/* Initialize datamsg from memory. */
+void sctp_datamsg_init(struct sctp_datamsg *msg)
+{
+	atomic_set(&msg->refcnt, 1);
+	msg->send_failed = 0;
+	msg->send_error = 0;
+	msg->can_expire = 0;
+	INIT_LIST_HEAD(&msg->chunks);
+}
+
+/* Allocate and initialize datamsg. */
+struct sctp_datamsg *sctp_datamsg_new(int gfp)
+{
+	struct sctp_datamsg *msg;
+	msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
+	if (msg)
+		sctp_datamsg_init(msg);
+	SCTP_DBG_OBJCNT_INC(datamsg);
+	return msg;
+}
+
+/* Final destructruction of datamsg memory. */
+static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
+{
+	struct list_head *pos, *temp;
+	struct sctp_chunk *chunk;
+	struct sctp_opt *sp;
+	struct sctp_ulpevent *ev;
+	struct sctp_association *asoc = NULL;
+	int error = 0, notify;
+
+	/* If we failed, we may need to notify. */
+	notify = msg->send_failed ? -1 : 0;
+
+	/* Release all references. */
+	list_for_each_safe(pos, temp, &msg->chunks) {
+		list_del_init(pos);
+		chunk = list_entry(pos, struct sctp_chunk, frag_list);
+		/* Check whether we _really_ need to notify. */
+		if (notify < 0) {
+			asoc = chunk->asoc;
+			if (msg->send_error)
+				error = msg->send_error;
+			else
+				error = asoc->outqueue.error;
+
+			sp = sctp_sk(asoc->base.sk);
+			notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED,
+							    &sp->subscribe);
+		}
+
+		/* Generate a SEND FAILED event only if enabled. */
+		if (notify > 0) {
+			int sent;
+			if (chunk->has_tsn)
+				sent = SCTP_DATA_SENT;
+			else
+				sent = SCTP_DATA_UNSENT;
+
+			ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent,
+							    error, GFP_ATOMIC);
+			if (ev)
+				sctp_ulpq_tail_event(&asoc->ulpq, ev);
+		}
+
+		sctp_chunk_put(chunk);
+	}
+
+	SCTP_DBG_OBJCNT_DEC(datamsg);
+	kfree(msg);
+}
+
+/* Hold a reference. */
+void sctp_datamsg_hold(struct sctp_datamsg *msg)
+{
+	atomic_inc(&msg->refcnt);
+}
+
+/* Release a reference. */
+void sctp_datamsg_put(struct sctp_datamsg *msg)
+{
+	if (atomic_dec_and_test(&msg->refcnt))
+		sctp_datamsg_destroy(msg);
+}
+
+/* Free a message.  Really just give up a reference, the
+ * really free happens in sctp_datamsg_destroy().
+ */
+void sctp_datamsg_free(struct sctp_datamsg *msg)
+{
+	sctp_datamsg_put(msg);
+}
+
+/* Hold on to all the fragments until all chunks have been sent. */
+void sctp_datamsg_track(struct sctp_chunk *chunk)
+{
+	sctp_chunk_hold(chunk);
+}
+
+/* Assign a chunk to this datamsg. */
+void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
+{
+	sctp_datamsg_hold(msg);
+	chunk->msg = msg;
+}
+
+
+/* A data chunk can have a maximum payload of (2^16 - 20).  Break
+ * down any such message into smaller chunks.  Opportunistically, fragment
+ * the chunks down to the current MTU constraints.  We may get refragmented
+ * later if the PMTU changes, but it is _much better_ to fragment immediately
+ * with a reasonable guess than always doing our fragmentation on the
+ * soft-interrupt.
+ */
+struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
+					    struct sctp_sndrcvinfo *sinfo,
+					    struct msghdr *msgh, int msg_len)
+{
+	int max, whole, i, offset, over, err;
+	int len, first_len;
+	struct sctp_chunk *chunk;
+	struct sctp_datamsg *msg;
+	struct list_head *pos, *temp;
+	__u8 frag;
+
+	msg = sctp_datamsg_new(GFP_KERNEL);
+	if (!msg)
+		return NULL;
+
+	/* Note: Calculate this outside of the loop, so that all fragments
+	 * have the same expiration.
+	 */
+	if (sinfo->sinfo_timetolive) {
+		/* sinfo_timetolive is in milliseconds */
+		msg->expires_at = jiffies +
+				     SCTP_MSECS_TO_JIFFIES(sinfo->sinfo_timetolive);
+		msg->can_expire = 1;
+	}
+
+	/* What is a reasonable fragmentation point right now? */
+	max = asoc->pmtu;
+	if (max < SCTP_MIN_PMTU)
+		max = SCTP_MIN_PMTU;
+	max -= SCTP_IP_OVERHEAD;
+
+	/* Make sure not beyond maximum chunk size. */
+	if (max > SCTP_MAX_CHUNK_LEN)
+		max = SCTP_MAX_CHUNK_LEN;
+
+	/* Subtract out the overhead of a data chunk header. */
+	max -= sizeof(struct sctp_data_chunk);
+	whole = 0;
+
+	/* If user has specified smaller fragmentation, make it so. */
+	if (sctp_sk(asoc->base.sk)->user_frag)
+		max = min_t(int, max, sctp_sk(asoc->base.sk)->user_frag);
+
+	first_len = max;
+
+	/* Encourage Cookie-ECHO bundling. */
+	if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
+		whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);
+
+		/* Account for the DATA to be bundled with the COOKIE-ECHO. */
+		if (whole) {
+			first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
+			msg_len -= first_len;
+			whole = 1;
+		}
+	}
+
+	/* How many full sized?  How many bytes leftover? */
+	whole += msg_len / max;
+	over = msg_len % max;
+	offset = 0;
+
+	if ((whole > 1) || (whole && over))
+		SCTP_INC_STATS_USER(SctpFragUsrMsgs);
+
+	/* Create chunks for all the full sized DATA chunks. */
+	for (i=0, len=first_len; i < whole; i++) {
+		frag = SCTP_DATA_MIDDLE_FRAG;
+
+		if (0 == i)
+			frag |= SCTP_DATA_FIRST_FRAG;
+
+		if ((i == (whole - 1)) && !over)
+			frag |= SCTP_DATA_LAST_FRAG;
+
+		chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
+
+		if (!chunk)
+			goto errout;
+		err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
+		if (err < 0)
+			goto errout;
+
+		offset += len;
+
+		/* Put the chunk->skb back into the form expected by send.  */
+		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
+			   - (__u8 *)chunk->skb->data);
+
+		sctp_datamsg_assign(msg, chunk);
+		list_add_tail(&chunk->frag_list, &msg->chunks);
+
+		/* The first chunk, the first chunk was likely short
+		 * to allow bundling, so reset to full size.
+		 */
+		if (0 == i)
+			len = max;
+	}
+
+	/* .. now the leftover bytes. */
+	if (over) {
+		if (!whole)
+			frag = SCTP_DATA_NOT_FRAG;
+		else
+			frag = SCTP_DATA_LAST_FRAG;
+
+		chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
+
+		if (!chunk)
+			goto errout;
+
+		err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
+
+		/* Put the chunk->skb back into the form expected by send.  */
+		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
+			   - (__u8 *)chunk->skb->data);
+		if (err < 0)
+			goto errout;
+
+		sctp_datamsg_assign(msg, chunk);
+		list_add_tail(&chunk->frag_list, &msg->chunks);
+	}
+
+	return msg;
+
+errout:
+	list_for_each_safe(pos, temp, &msg->chunks) {
+		list_del_init(pos);
+		chunk = list_entry(pos, struct sctp_chunk, frag_list);
+		sctp_chunk_free(chunk);
+	}
+	sctp_datamsg_free(msg);
+	return NULL;
+}
+
+/* Check whether this message has expired. */
+int sctp_datamsg_expires(struct sctp_chunk *chunk)
+{
+	struct sctp_datamsg *msg = chunk->msg;
+
+	/* FIXME: When PR-SCTP is supported we can make this
+	 * check more lenient.
+	 */
+	if (!msg->can_expire)
+		return 0;
+
+	if (time_after(jiffies, msg->expires_at))
+		return 1;
+
+	return 0;
+}
+
+/* This chunk (and consequently entire message) has failed in its sending. */
+void sctp_datamsg_fail(struct sctp_chunk *chunk, int error)
+{
+	chunk->msg->send_failed = 1;
+	chunk->msg->send_error = error;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/debug.c linux-2.4.26-pre6/net/sctp/debug.c
--- linux-2.4.25/net/sctp/debug.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/debug.c	2004-03-25 00:19:21.000000000 +0000
@@ -185,6 +185,7 @@ static const char *sctp_timer_tbl[] = {
 	"TIMEOUT_T1_INIT",
 	"TIMEOUT_T2_SHUTDOWN",
 	"TIMEOUT_T3_RTX",
+	"TIMEOUT_T4_RTO",
 	"TIMEOUT_T5_SHUTDOWN_GUARD",
 	"TIMEOUT_HEARTBEAT",
 	"TIMEOUT_SACK",
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/endpointola.c linux-2.4.26-pre6/net/sctp/endpointola.c
--- linux-2.4.25/net/sctp/endpointola.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/endpointola.c	2004-03-25 00:22:36.000000000 +0000
@@ -54,6 +54,7 @@
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/random.h>	/* get_random_bytes() */
+#include <linux/crypto.h>
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <net/sctp/sctp.h>
@@ -128,15 +129,16 @@ struct sctp_endpoint *sctp_endpoint_init
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
 		SCTP_DEFAULT_TIMEOUT_T1_INIT;
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
-		sp->rtoinfo.srto_initial;
+		SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
+	ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
 
 	/* sctpimpguide-05 Section 2.12.2
 	 * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
 	 * recommended value of 5 times 'RTO.Max'.
 	 */
         ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
-		= 5 * sp->rtoinfo.srto_max;
+		= 5 * SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
 
 	ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
 		SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
@@ -145,17 +147,9 @@ struct sctp_endpoint *sctp_endpoint_init
 	ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
 		sp->autoclose * HZ;
 
-	/* Set up the default send/receive buffer space.  */
-
-	/* FIXME - Should the min and max window size be configurable
-	 * sysctl parameters as opposed to be constants?
-	 */
-	sk->rcvbuf = SCTP_DEFAULT_MAXWINDOW;
-	sk->sndbuf = SCTP_DEFAULT_MAXWINDOW * 2;
-
 	/* Use SCTP specific send buffer space queues.  */
-	sk->write_space = sctp_write_space;
-	sk->use_write_queue = 1;
+	sk->sk_write_space = sctp_write_space;
+	sk->sk_use_write_queue = 1;
 
 	/* Initialize the secret key used with cookie. */
 	get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
@@ -176,9 +170,8 @@ void sctp_endpoint_add_asoc(struct sctp_
 	list_add_tail(&asoc->asocs, &ep->asocs);
 
 	/* Increment the backlog value for a TCP-style listening socket. */
-	if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) &&
-	    (SCTP_SS_LISTENING == sk->state))
-		sk->ack_backlog++;
+	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
+		sk->sk_ack_backlog++;
 }
 
 /* Free the endpoint structure.  Delay cleanup until
@@ -195,7 +188,7 @@ void sctp_endpoint_destroy(struct sctp_e
 {
 	SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
 
-	ep->base.sk->state = SCTP_SS_CLOSED;
+	ep->base.sk->sk_state = SCTP_SS_CLOSED;
 
 	/* Unlink this endpoint, so we can't find it again! */
 	sctp_unhash_endpoint(ep);
@@ -313,13 +306,13 @@ int sctp_endpoint_is_peeled_off(struct s
 				const union sctp_addr *paddr)
 {
 	struct list_head *pos;
-	struct sockaddr_storage_list *addr;
-	sctp_bind_addr_t *bp;
+	struct sctp_sockaddr_entry *addr;
+	struct sctp_bind_addr *bp;
 
 	sctp_read_lock(&ep->base.addr_lock);
 	bp = &ep->base.bind_addr;
 	list_for_each(pos, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (sctp_has_association(&addr->a, paddr)) {
 			sctp_read_unlock(&ep->base.addr_lock);
 			return 1;
@@ -338,7 +331,7 @@ static void sctp_endpoint_bh_rcv(struct 
 	struct sctp_association *asoc;
 	struct sock *sk;
 	struct sctp_transport *transport;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	struct sctp_inq *inqueue;
 	sctp_subtype_t subtype;
 	sctp_state_t state;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/input.c linux-2.4.26-pre6/net/sctp/input.c
--- linux-2.4.25/net/sctp/input.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/input.c	2004-03-25 00:20:46.000000000 +0000
@@ -106,7 +106,7 @@ int sctp_rcv(struct sk_buff *skb)
 	struct sctp_endpoint *ep = NULL;
 	struct sctp_ep_common *rcvr;
 	struct sctp_transport *transport = NULL;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	struct sctphdr *sh;
 	union sctp_addr src;
 	union sctp_addr dest;
@@ -124,16 +124,16 @@ int sctp_rcv(struct sk_buff *skb)
 	/* Pull up the IP and SCTP headers. */
 	__skb_pull(skb, skb->h.raw - skb->data);
 	if (skb->len < sizeof(struct sctphdr))
-		goto bad_packet;
+		goto discard_it;
 	if (sctp_rcv_checksum(skb) < 0)
-		goto bad_packet;
+		goto discard_it;
 
 	skb_pull(skb, sizeof(struct sctphdr));
 
 	family = ipver2af(skb->nh.iph->version);
 	af = sctp_get_af_specific(family);
 	if (unlikely(!af))
-		goto bad_packet;
+		goto discard_it;
 
 	/* Initialize local addresses for lookups. */
 	af->from_skb(&src, skb, 1);
@@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb)
 	 * IP broadcast addresses cannot be used in an SCTP transport
 	 * address."
 	 */
-	if (!af->addr_valid(&src) || !af->addr_valid(&dest))
+	if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL))
 		goto discard_it;
 
 	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
@@ -180,7 +180,7 @@ int sctp_rcv(struct sk_buff *skb)
 
 	ret = sk_filter(sk, skb, 1);
 	if (ret)
-		goto discard_release;
+                goto discard_release;
 
 	/* Create an SCTP packet structure. */
 	chunk = sctp_chunkify(skb, asoc, sk);
@@ -223,9 +223,6 @@ int sctp_rcv(struct sk_buff *skb)
 	sock_put(sk);
 	return ret;
 
-bad_packet:
-	SCTP_INC_STATS(SctpChecksumErrors);
-
 discard_it:
 	kfree_skb(skb);
 	return ret;
@@ -250,13 +247,13 @@ discard_release:
  */
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	struct sctp_inq *inqueue;
 
 	/* One day chunk will live inside the skb, but for
 	 * now this works.
 	 */
-	chunk = (sctp_chunk_t *) skb;
+	chunk = (struct sctp_chunk *) skb;
 	inqueue = &chunk->rcvr->inqueue;
 
 	sctp_inq_push(inqueue, chunk);
@@ -447,10 +444,10 @@ void sctp_v4_err(struct sk_buff *skb, __
 
 	inet = inet_sk(sk);
 	if (!sock_owned_by_user(sk) && inet->recverr) {
-		sk->err = err;
-		sk->error_report(sk);
+		sk->sk_err = err;
+		sk->sk_error_report(sk);
 	} else {  /* Only an error on timeout */
-		sk->err_soft = err;
+		sk->sk_err_soft = err;
 	}
 
 out_unlock:
@@ -503,9 +500,10 @@ int sctp_rcv_ootb(struct sk_buff *skb)
 			goto discard;
 
 		if (SCTP_CID_ERROR == ch->type) {
-			err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t));
-			if (SCTP_ERROR_STALE_COOKIE == err->cause)
-				goto discard;
+			sctp_walk_errors(err, ch) {
+				if (SCTP_ERROR_STALE_COOKIE == err->cause)
+					goto discard;
+			}
 		}
 
 		ch = (sctp_chunkhdr_t *) ch_end;
@@ -522,12 +520,12 @@ void __sctp_hash_endpoint(struct sctp_en
 {
 	struct sctp_ep_common **epp;
 	struct sctp_ep_common *epb;
-	sctp_hashbucket_t *head;
+	struct sctp_hashbucket *head;
 
 	epb = &ep->base;
 
 	epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
-	head = &sctp_proto.ep_hashbucket[epb->hashent];
+	head = &sctp_ep_hashtable[epb->hashent];
 
 	sctp_write_lock(&head->lock);
 	epp = &head->chain;
@@ -550,14 +548,14 @@ void sctp_hash_endpoint(struct sctp_endp
 /* Remove endpoint from the hash table.  */
 void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
 {
-	sctp_hashbucket_t *head;
+	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 
 	epb = &ep->base;
 
 	epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
 
-	head = &sctp_proto.ep_hashbucket[epb->hashent];
+	head = &sctp_ep_hashtable[epb->hashent];
 
 	sctp_write_lock(&head->lock);
 
@@ -582,13 +580,13 @@ void sctp_unhash_endpoint(struct sctp_en
 /* Look up an endpoint. */
 struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
 {
-	sctp_hashbucket_t *head;
+	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 	struct sctp_endpoint *ep;
 	int hash;
 
 	hash = sctp_ep_hashfn(laddr->v4.sin_port);
-	head = &sctp_proto.ep_hashbucket[hash];
+	head = &sctp_ep_hashtable[hash];
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
 		ep = sctp_ep(epb);
@@ -619,14 +617,14 @@ void __sctp_hash_established(struct sctp
 {
 	struct sctp_ep_common **epp;
 	struct sctp_ep_common *epb;
-	sctp_hashbucket_t *head;
+	struct sctp_hashbucket *head;
 
 	epb = &asoc->base;
 
 	/* Calculate which chain this entry will belong to. */
 	epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port);
 
-	head = &sctp_proto.assoc_hashbucket[epb->hashent];
+	head = &sctp_assoc_hashtable[epb->hashent];
 
 	sctp_write_lock(&head->lock);
 	epp = &head->chain;
@@ -649,7 +647,7 @@ void sctp_unhash_established(struct sctp
 /* Remove association from the hash table.  */
 void __sctp_unhash_established(struct sctp_association *asoc)
 {
-	sctp_hashbucket_t *head;
+	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 
 	epb = &asoc->base;
@@ -657,7 +655,7 @@ void __sctp_unhash_established(struct sc
 	epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port,
 					 asoc->peer.port);
 
-	head = &sctp_proto.assoc_hashbucket[epb->hashent];
+	head = &sctp_assoc_hashtable[epb->hashent];
 
 	sctp_write_lock(&head->lock);
 
@@ -677,7 +675,7 @@ struct sctp_association *__sctp_lookup_a
 					const union sctp_addr *peer,
 					struct sctp_transport **pt)
 {
-	sctp_hashbucket_t *head;
+	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 	struct sctp_association *asoc;
 	struct sctp_transport *transport;
@@ -687,7 +685,7 @@ struct sctp_association *__sctp_lookup_a
 	 * have wildcards anyways.
 	 */
 	hash = sctp_assoc_hashfn(local->v4.sin_port, peer->v4.sin_port);
-	head = &sctp_proto.assoc_hashbucket[hash];
+	head = &sctp_assoc_hashtable[hash];
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
 		asoc = sctp_assoc(epb);
@@ -766,6 +764,8 @@ static struct sctp_association *__sctp_r
 	sctp_chunkhdr_t *ch;
 	union sctp_params params;
 	sctp_init_chunk_t *init;
+	struct sctp_transport *transport;
+	struct sctp_af *af;
 
 	ch = (sctp_chunkhdr_t *) skb->data;
 
@@ -800,12 +800,13 @@ static struct sctp_association *__sctp_r
 	sctp_walk_params(params, init, init_hdr.params) {
 
 		/* Note: Ignoring hostname addresses. */
-		if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) &&
-		    (SCTP_PARAM_IPV6_ADDRESS != params.p->type))
+		af = sctp_get_af_specific(param_type2af(params.p->type));
+		if (!af)
 			continue;
 
-		sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0);
-		asoc = __sctp_lookup_association(laddr, paddr, transportp);
+		af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0);
+
+		asoc = __sctp_lookup_association(laddr, paddr, &transport);
 		if (asoc)
 			return asoc;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/inqueue.c linux-2.4.26-pre6/net/sctp/inqueue.c
--- linux-2.4.25/net/sctp/inqueue.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/inqueue.c	2004-03-25 00:19:15.000000000 +0000
@@ -78,17 +78,17 @@ struct sctp_inq *sctp_inq_new(void)
 /* Release the memory associated with an SCTP inqueue.  */
 void sctp_inq_free(struct sctp_inq *queue)
 {
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 
 	/* Empty the queue.  */
-	while ((chunk = (sctp_chunk_t *) skb_dequeue(&queue->in)))
-		sctp_free_chunk(chunk);
+	while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)))
+		sctp_chunk_free(chunk);
 
 	/* If there is a packet which is currently being worked on,
 	 * free it as well.
 	 */
 	if (queue->in_progress)
-		sctp_free_chunk(queue->in_progress);
+		sctp_chunk_free(queue->in_progress);
 
 	if (queue->malloced) {
 		/* Dump the master memory segment.  */
@@ -99,7 +99,7 @@ void sctp_inq_free(struct sctp_inq *queu
 /* Put a new packet in an SCTP inqueue.
  * We assume that packet->sctp_hdr is set and in host byte order.
  */
-void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet)
+void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet)
 {
 	/* Directly call the packet handling routine. */
 
@@ -117,9 +117,9 @@ void sctp_inq_push(struct sctp_inq *q, s
  * WARNING:  If you need to put the chunk on another queue, you need to
  * make a shallow copy (clone) of it.
  */
-sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue)
+struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
 {
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	sctp_chunkhdr_t *ch = NULL;
 
 	/* The assumption is that we are safe to process the chunks
@@ -133,7 +133,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_i
 		if (chunk->singleton ||
 		    chunk->end_of_packet ||
 		    chunk->pdiscard) {
-			sctp_free_chunk(chunk);
+			sctp_chunk_free(chunk);
 			chunk = queue->in_progress = NULL;
 		} else {
 			/* Nothing to do. Next chunk in the packet, please. */
@@ -152,7 +152,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_i
 			return NULL;
 
 		chunk = queue->in_progress =
-			(sctp_chunk_t *) skb_dequeue(&queue->in);
+			(struct sctp_chunk *) skb_dequeue(&queue->in);
 
 		/* This is the first chunk in the packet.  */
 		chunk->singleton = 1;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ipv6.c linux-2.4.26-pre6/net/sctp/ipv6.c
--- linux-2.4.25/net/sctp/ipv6.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/ipv6.c	2004-03-25 00:19:52.000000000 +0000
@@ -2,6 +2,7 @@
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  * Copyright (c) 2002-2003 International Business Machines, Corp.
+ * Copyright (c) 2002-2003 Intel Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -15,7 +16,7 @@
  *
  * The SCTP reference implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- *                 ************************
+ *		   ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public License for more details.
  *
@@ -32,14 +33,15 @@
  *    http://www.sf.net/projects/lksctp
  *
  * Written or modified by:
- *    Le Yanqun             <yanqun.le@nokia.com>
+ *    Le Yanqun		    <yanqun.le@nokia.com>
  *    Hui Huang		    <hui.huang@nokia.com>
  *    La Monte H.P. Yarroll <piggy@acm.org>
  *    Sridhar Samudrala	    <sri@us.ibm.com>
- *    Jon Grimm             <jgrimm@us.ibm.com>
+ *    Jon Grimm		    <jgrimm@us.ibm.com>
+ *    Ardelle Fan	    <ardelle.fan@intel.com>
  *
  * Based on:
- *      linux/net/ipv6/tcp_ipv6.c
+ *	linux/net/ipv6/tcp_ipv6.c
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -61,6 +63,7 @@
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
 #include <linux/random.h>
+#include <linux/seq_file.h>
 
 #include <net/protocol.h>
 #include <net/tcp.h>
@@ -79,14 +82,14 @@ extern struct notifier_block sctp_inetad
 
 /* FIXME: This macro needs to be moved to a common header file. */
 #define NIP6(addr) \
-        ntohs((addr)->s6_addr16[0]), \
-        ntohs((addr)->s6_addr16[1]), \
-        ntohs((addr)->s6_addr16[2]), \
-        ntohs((addr)->s6_addr16[3]), \
-        ntohs((addr)->s6_addr16[4]), \
-        ntohs((addr)->s6_addr16[5]), \
-        ntohs((addr)->s6_addr16[6]), \
-        ntohs((addr)->s6_addr16[7])
+	ntohs((addr)->s6_addr16[0]), \
+	ntohs((addr)->s6_addr16[1]), \
+	ntohs((addr)->s6_addr16[2]), \
+	ntohs((addr)->s6_addr16[3]), \
+	ntohs((addr)->s6_addr16[4]), \
+	ntohs((addr)->s6_addr16[5]), \
+	ntohs((addr)->s6_addr16[6]), \
+	ntohs((addr)->s6_addr16[7])
 
 /* ICMP error handler. */
 void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -134,10 +137,10 @@ void sctp_v6_err(struct sk_buff *skb, st
 	np = inet6_sk(sk);
 	icmpv6_err_convert(type, code, &err);
 	if (!sock_owned_by_user(sk) && np->recverr) {
-		sk->err = err;
-		sk->error_report(sk);
+		sk->sk_err = err;
+		sk->sk_error_report(sk);
 	} else {  /* Only an error on timeout */
-		sk->err_soft = err;
+		sk->sk_err_soft = err;
 	}
 
 out_unlock:
@@ -155,7 +158,9 @@ static int sctp_v6_xmit(struct sk_buff *
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct flowi fl;
 
-	fl.proto = sk->protocol;
+	memset(&fl, 0, sizeof(fl));
+
+	fl.proto = sk->sk_protocol;
 
 	/* Fill in the dest address from the route entry passed with the skb
 	 * and the source address from the transport.
@@ -168,20 +173,20 @@ static int sctp_v6_xmit(struct sk_buff *
 	if (ipv6_addr_type(fl.fl6_src) & IPV6_ADDR_LINKLOCAL)
 		fl.oif = transport->saddr.v6.sin6_scope_id;
 	else
-		fl.oif = sk->bound_dev_if;
-	fl.uli_u.ports.sport = (sk)->sport;
+		fl.oif = sk->sk_bound_dev_if;
+	fl.uli_u.ports.sport = sk->sport;
 	fl.uli_u.ports.dport = transport->ipaddr.v6.sin6_port;
 
 	if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-		fl.nl_u.ip6_u.daddr = rt0->addr;
+		fl.fl6_dst = rt0->addr;
 	}
 
 	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
 			  "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
 			  "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-			  __FUNCTION__, skb, skb->len, NIP6(fl.fl6_src),
-			  NIP6(fl.fl6_dst));
+			  __FUNCTION__, skb, skb->len,
+			  NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
 
 	SCTP_INC_STATS(SctpOutSCTPPacks);
 
@@ -196,8 +201,13 @@ struct dst_entry *sctp_v6_get_dst(struct
 				  union sctp_addr *saddr)
 {
 	struct dst_entry *dst;
-	struct flowi fl = {
-		.nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } };
+	struct flowi fl;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.fl6_dst = &daddr->v6.sin6_addr;
+	if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
+		fl.oif = daddr->v6.sin6_scope_id;
+	
 
 	SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
 			  __FUNCTION__, NIP6(fl.fl6_dst));
@@ -252,9 +262,9 @@ static inline int sctp_v6_addr_match_len
 void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
 		       union sctp_addr *daddr, union sctp_addr *saddr)
 {
-	sctp_bind_addr_t *bp;
+	struct sctp_bind_addr *bp;
 	rwlock_t *addr_lock;
-	struct sockaddr_storage_list *laddr;
+	struct sctp_sockaddr_entry *laddr;
 	struct list_head *pos;
 	sctp_scope_t scope;
 	union sctp_addr *baddr = NULL;
@@ -283,7 +293,7 @@ void sctp_v6_get_saddr(struct sctp_assoc
 	 */
 	sctp_read_lock(addr_lock);
 	list_for_each(pos, &bp->address_list) {
-		laddr = list_entry(pos, struct sockaddr_storage_list, list);
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if ((laddr->a.sa.sa_family == AF_INET6) &&
 		    (scope <= sctp_scope(&laddr->a))) {
 			bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
@@ -315,7 +325,7 @@ static void sctp_v6_copy_addrlist(struct
 {
 	struct inet6_dev *in6_dev;
 	struct inet6_ifaddr *ifp;
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 
 	read_lock(&addrconf_lock);
 	if ((in6_dev = __in6_dev_get(dev)) == NULL) {
@@ -326,7 +336,7 @@ static void sctp_v6_copy_addrlist(struct
 	read_lock(&in6_dev->lock);
 	for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) {
 		/* Add the address to the local list.  */
-		addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC);
+		addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
 		if (addr) {
 			addr->a.v6.sin6_family = AF_INET6;
 			addr->a.v6.sin6_port = 0;
@@ -369,20 +379,62 @@ static void sctp_v6_from_skb(union sctp_
 static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
 {
 	addr->v6.sin6_family = AF_INET6;
-	addr->v6.sin6_port = (sk)->num;
+	addr->v6.sin6_port = sk->num;
 	addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
 }
 
-/* Initialize sk->rcv_saddr from sctp_addr. */
+/* Initialize sk->sk_rcv_saddr from sctp_addr. */
 static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
 {
-	inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
+	if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
+		inet6_sk(sk)->rcv_saddr.s6_addr32[0] = 0;
+		inet6_sk(sk)->rcv_saddr.s6_addr32[1] = 0;
+		inet6_sk(sk)->rcv_saddr.s6_addr32[2] = htonl(0x0000ffff);
+		inet6_sk(sk)->rcv_saddr.s6_addr32[3] =
+			addr->v4.sin_addr.s_addr;
+	} else {
+		inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
+	}
 }
 
-/* Initialize sk->daddr from sctp_addr. */
+/* Initialize sk->sk_daddr from sctp_addr. */
 static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
 {
-	inet6_sk(sk)->daddr = addr->v6.sin6_addr;
+	if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
+		inet6_sk(sk)->daddr.s6_addr32[0] = 0;
+		inet6_sk(sk)->daddr.s6_addr32[1] = 0;
+		inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff);
+		inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
+	} else {
+		inet6_sk(sk)->daddr = addr->v6.sin6_addr;
+	}
+}
+
+/* Initialize a sctp_addr from an address parameter. */
+static void sctp_v6_from_addr_param(union sctp_addr *addr,
+				    union sctp_addr_param *param,
+				    __u16 port, int iif)
+{
+	addr->v6.sin6_family = AF_INET6;
+	addr->v6.sin6_port = port;
+	addr->v6.sin6_flowinfo = 0; /* BUG */
+	ipv6_addr_copy(&addr->v6.sin6_addr, &param->v6.addr);
+	addr->v6.sin6_scope_id = iif;
+}
+
+/* Initialize an address parameter from a sctp_addr and return the length
+ * of the address parameter.
+ */
+static int sctp_v6_to_addr_param(const union sctp_addr *addr,
+				 union sctp_addr_param *param)
+{
+	int length = sizeof(sctp_ipv6addr_param_t);
+
+	param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
+	param->v6.param_hdr.length = ntohs(length);
+	ipv6_addr_copy(&param->v6.addr, &addr->v6.sin6_addr);
+
+	return length;
 }
 
 /* Initialize a sctp_addr from a dst_entry. */
@@ -396,13 +448,30 @@ static void sctp_v6_dst_saddr(union sctp
 }
 
 /* Compare addresses exactly.
- * FIXME: v4-mapped-v6.
+ * v4-mapped-v6 is also in consideration.
  */
 static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
 			    const union sctp_addr *addr2)
 {
-	if (addr1->sa.sa_family != addr2->sa.sa_family)
+	if (addr1->sa.sa_family != addr2->sa.sa_family) {
+		if (addr1->sa.sa_family == AF_INET &&
+		    addr2->sa.sa_family == AF_INET6 &&
+		    IPV6_ADDR_MAPPED == ipv6_addr_type(&addr2->v6.sin6_addr)) {
+			if (addr2->v6.sin6_port == addr1->v4.sin_port &&
+			    addr2->v6.sin6_addr.s6_addr32[3] ==
+			    addr1->v4.sin_addr.s_addr)
+				return 1;
+		}
+		if (addr2->sa.sa_family == AF_INET &&
+		    addr1->sa.sa_family == AF_INET6 &&
+		    IPV6_ADDR_MAPPED == ipv6_addr_type(&addr1->v6.sin6_addr)) {
+			if (addr1->v6.sin6_port == addr2->v4.sin_port &&
+			    addr1->v6.sin6_addr.s6_addr32[3] ==
+			    addr2->v4.sin_addr.s_addr)
+				return 1;
+		}
 		return 0;
+	}
 	if (ipv6_addr_cmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
 		return 0;
 	/* If this is a linklocal address, compare the scope_id. */
@@ -433,7 +502,7 @@ static int sctp_v6_is_any(const union sc
 }
 
 /* Should this be available for binding?   */
-static int sctp_v6_available(const union sctp_addr *addr)
+static int sctp_v6_available(union sctp_addr *addr, struct sctp_opt *sp)
 {
 	int type;
 	struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;
@@ -441,6 +510,14 @@ static int sctp_v6_available(const union
 	type = ipv6_addr_type(in6);
 	if (IPV6_ADDR_ANY == type)
 		return 1;
+	if (type == IPV6_ADDR_MAPPED) {
+		if (sp && !sp->v4mapped)
+			return 0;
+		if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
+			return 0;
+		sctp_v6_map_v4(addr);
+		return sctp_get_af_specific(AF_INET)->available(addr, sp);
+	}
 	if (!(type & IPV6_ADDR_UNICAST))
 		return 0;
 
@@ -454,11 +531,22 @@ static int sctp_v6_available(const union
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v6_addr_valid(union sctp_addr *addr)
+static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_opt *sp)
 {
 	int ret = ipv6_addr_type(&addr->v6.sin6_addr);
 
-	/* FIXME:  v4-mapped-v6 address support. */
+	/* Support v4-mapped-v6 address. */
+	if (ret == IPV6_ADDR_MAPPED) {
+		/* Note: This routine is used in input, so v4-mapped-v6
+		 * are disallowed here when there is no sctp_opt.
+		 */
+		if (!sp || !sp->v4mapped)
+			return 0;
+		if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
+			return 0;
+		sctp_v6_map_v4(addr);
+		return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp);
+	}
 
 	/* Is this a non-unicast address */
 	if (!(ret & IPV6_ADDR_UNICAST))
@@ -511,18 +599,18 @@ struct sock *sctp_v6_create_accept_sk(st
 	sock_init_data(NULL, newsk);
 	sk_set_owner(newsk, THIS_MODULE);
 
-	newsk->type = SOCK_STREAM;
+	newsk->sk_type = SOCK_STREAM;
 
-	newsk->prot = sk->prot;
-	newsk->no_check = sk->no_check;
-	newsk->reuse = sk->reuse;
-
-	newsk->destruct = inet_sock_destruct;
-	newsk->zapped = 0;
-	newsk->family = PF_INET6;
-	newsk->protocol = IPPROTO_SCTP;
-	newsk->backlog_rcv = sk->prot->backlog_rcv;
-	newsk->shutdown = sk->shutdown;
+	newsk->sk_prot = sk->sk_prot;
+	newsk->sk_no_check = sk->sk_no_check;
+	newsk->sk_reuse = sk->sk_reuse;
+
+	newsk->sk_destruct = inet_sock_destruct;
+	newsk->sk_zapped = 0;
+	newsk->sk_family = PF_INET6;
+	newsk->sk_protocol = IPPROTO_SCTP;
+	newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+	newsk->sk_shutdown = sk->sk_shutdown;
 
 	newinet = inet_sk(newsk);
 	newnp = inet6_sk(newsk);
@@ -533,17 +621,31 @@ struct sock *sctp_v6_create_accept_sk(st
 	 * and getpeername().
 	 */
 	newsk->sport = sk->sport;
-	newnp->saddr = np->saddr;
+	newsk->saddr = sk->saddr;
 	newnp->rcv_saddr = np->rcv_saddr;
 	newsk->dport = htons(asoc->peer.port);
-	newnp->daddr =  asoc->peer.primary_addr.v6.sin6_addr;
+	sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
+
+	/* Init the ipv4 part of the socket since we can have sockets
+	 * using v6 API for ipv4.
+	 */
+	newinet->ttl = sysctl_ip_default_ttl;
+	newinet->mc_loop = 1;
+	newinet->mc_ttl = 1;
+	newinet->mc_index = 0;
+	newinet->mc_list = NULL;
+
+	if (ipv4_config.no_pmtu_disc)
+		newinet->pmtudisc = IP_PMTUDISC_DONT;
+	else
+		newinet->pmtudisc = IP_PMTUDISC_WANT;
 
 #ifdef INET_REFCNT_DEBUG
 	atomic_inc(&inet6_sock_nr);
 	atomic_inc(&inet_sock_nr);
 #endif
 
-	if (0 != newsk->prot->init(newsk)) {
+	if (newsk->sk_prot->init(newsk)) {
 		inet_sock_release(newsk);
 		newsk = NULL;
 	}
@@ -552,6 +654,13 @@ out:
 	return newsk;
 }
 
+/* Map v4 address to mapped v6 address */
+static void sctp_v6_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr)
+{
+	if (sp->v4mapped && AF_INET == addr->sa.sa_family)
+		sctp_v4_map_v6(addr);
+}
+
 /* Where did this skb come from?  */
 static int sctp_v6_skb_iif(const struct sk_buff *skb)
 {
@@ -559,6 +668,19 @@ static int sctp_v6_skb_iif(const struct 
 	return opt->iif;
 }
 
+/* Was this packet marked by Explicit Congestion Notification? */
+static int sctp_v6_is_ce(const struct sk_buff *skb)
+{
+	return *((__u32 *)(skb->nh.ipv6h)) & htonl(1<<20);
+}
+
+/* Dump the v6 addr to the seq file. */
+static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
+{
+	seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
+		   NIP6(&addr->v6.sin6_addr));
+}
+
 /* Initialize a PF_INET6 socket msg_name. */
 static void sctp_inet6_msgname(char *msgname, int *addr_len)
 {
@@ -579,25 +701,28 @@ static void sctp_inet6_event_msgname(str
 
 	if (msgname) {
 		union sctp_addr *addr;
+		struct sctp_association *asoc;
 
+		asoc = event->sndrcvinfo.sinfo_assoc_id;
 		sctp_inet6_msgname(msgname, addrlen);
 		sin6 = (struct sockaddr_in6 *)msgname;
-		sin6->sin6_port = htons(event->event_asoc->peer.port);
-		addr = &event->event_asoc->peer.primary_addr;
+		sin6->sin6_port = htons(asoc->peer.port);
+		addr = &asoc->peer.primary_addr;
 
 		/* Note: If we go to a common v6 format, this code
 		 * will change.
 		 */
 
 		/* Map ipv4 address into v4-mapped-on-v6 address.  */
-		if (AF_INET == addr->sa.sa_family) {
-			/* FIXME: Easy, but there was no way to test this
-			 * yet.
-			 */
+		if (sctp_sk(asoc->base.sk)->v4mapped &&
+		    AF_INET == addr->sa.sa_family) {
+			sctp_v4_map_v6((union sctp_addr *)sin6);
+			sin6->sin6_addr.s6_addr32[3] =
+				addr->v4.sin_addr.s_addr;
 			return;
 		}
 
-		sin6from = &event->event_asoc->peer.primary_addr.v6;
+		sin6from = &asoc->peer.primary_addr.v6;
 		ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr);
 		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
 			sin6->sin6_scope_id = sin6from->sin6_scope_id;
@@ -617,16 +742,15 @@ static void sctp_inet6_skb_msgname(struc
 		sh = (struct sctphdr *)skb->h.raw;
 		sin6->sin6_port = sh->source;
 
-		/* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */
-		if (__constant_htons(ETH_P_IP) == skb->protocol) {
-			/* FIXME:  The latest I-D added options for two
-			 * behaviors.
-			 */
+		/* Map ipv4 address into v4-mapped-on-v6 address. */
+		if (sctp_sk(skb->sk)->v4mapped &&
+		    skb->nh.iph->version == 4) {
+			sctp_v4_map_v6((union sctp_addr *)sin6);
+			sin6->sin6_addr.s6_addr32[3] = skb->nh.iph->saddr;
 			return;
 		}
 
 		/* Otherwise, just copy the v6 address. */
-
 		ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
 		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
 			struct sctp_ulpevent *ev = sctp_skb2event(skb);
@@ -636,16 +760,15 @@ static void sctp_inet6_skb_msgname(struc
 }
 
 /* Do we support this AF? */
-static int sctp_inet6_af_supported(sa_family_t family)
+static int sctp_inet6_af_supported(sa_family_t family, struct sctp_opt *sp)
 {
-	/* FIXME:  v4-mapped-v6 addresses.  The I-D is still waffling
-	 * on what to do with sockaddr formats for PF_INET6 sockets.
-	 * For now assume we'll support both.
-	 */
 	switch (family) {
 	case AF_INET6:
-	case AF_INET:
 		return 1;
+	/* v4-mapped-v6 addresses */
+	case AF_INET:
+		if (!__ipv6_only_sock(sctp_opt2sk(sp)) && sp->v4mapped)
+			return 1;
 	default:
 		return 0;
 	}
@@ -689,7 +812,7 @@ static int sctp_inet6_bind_verify(struct
 	else {
 		struct sock *sk;
 		int type = ipv6_addr_type(&addr->v6.sin6_addr);
-		sk = container_of(opt, struct sock, tp_pinfo.af_sctp);
+		sk = sctp_opt2sk(opt);
 		if (type & IPV6_ADDR_LINKLOCAL) {
 			/* Note: Behavior similar to af_inet6.c:
 			 *  1) Overrides previous bound_dev_if
@@ -697,13 +820,13 @@ static int sctp_inet6_bind_verify(struct
 			 */
 
 			if (addr->v6.sin6_scope_id)
-				sk->bound_dev_if = addr->v6.sin6_scope_id;
-			if (!sk->bound_dev_if)
+				sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
+			if (!sk->sk_bound_dev_if)
 				return 0;
 		}
 		af = opt->pf->af;
 	}
-	return af->available(addr);
+	return af->available(addr, opt);
 }
 
 /* Verify that the provided sockaddr looks bindable.   Common verification,
@@ -719,7 +842,7 @@ static int sctp_inet6_send_verify(struct
 	else {
 		struct sock *sk;
 		int type = ipv6_addr_type(&addr->v6.sin6_addr);
-		sk = container_of(opt, struct sock, tp_pinfo.af_sctp);
+		sk = sctp_opt2sk(opt);
 		if (type & IPV6_ADDR_LINKLOCAL) {
 			/* Note: Behavior similar to af_inet6.c:
 			 *  1) Overrides previous bound_dev_if
@@ -727,8 +850,8 @@ static int sctp_inet6_send_verify(struct
 			 */
 
 			if (addr->v6.sin6_scope_id)
-				sk->bound_dev_if = addr->v6.sin6_scope_id;
-			if (!sk->bound_dev_if)
+				sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
+			if (!sk->sk_bound_dev_if)
 				return 0;
 		}
 		af = opt->pf->af;
@@ -810,6 +933,8 @@ static struct sctp_af sctp_ipv6_specific
 	.from_sk         = sctp_v6_from_sk,
 	.to_sk_saddr     = sctp_v6_to_sk_saddr,
 	.to_sk_daddr     = sctp_v6_to_sk_daddr,
+	.from_addr_param = sctp_v6_from_addr_param,
+	.to_addr_param   = sctp_v6_to_addr_param,
 	.dst_saddr       = sctp_v6_dst_saddr,
 	.cmp_addr        = sctp_v6_cmp_addr,
 	.scope           = sctp_v6_scope,
@@ -818,6 +943,8 @@ static struct sctp_af sctp_ipv6_specific
 	.is_any          = sctp_v6_is_any,
 	.available       = sctp_v6_available,
 	.skb_iif         = sctp_v6_skb_iif,
+	.is_ce           = sctp_v6_is_ce,
+	.seq_dump_addr   = sctp_v6_seq_dump_addr,
 	.net_header_len  = sizeof(struct ipv6hdr),
 	.sockaddr_len    = sizeof(struct sockaddr_in6),
 	.sa_family       = AF_INET6,
@@ -832,6 +959,7 @@ static struct sctp_pf sctp_pf_inet6_spec
 	.send_verify   = sctp_inet6_send_verify,
 	.supported_addrs = sctp_inet6_supported_addrs,
 	.create_accept_sk = sctp_v6_create_accept_sk,
+	.addr_v4map    = sctp_v6_addr_v4map,
 	.af            = &sctp_ipv6_specific,
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/objcnt.c linux-2.4.26-pre6/net/sctp/objcnt.c
--- linux-2.4.25/net/sctp/objcnt.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/objcnt.c	2004-03-25 00:18:59.000000000 +0000
@@ -38,6 +38,7 @@
  * be incorporated into the next SCTP release.
  */
 
+#include <linux/kernel.h>
 #include <net/sctp/sctp.h>
 
 /*
@@ -55,6 +56,7 @@ SCTP_DBG_OBJCNT(bind_addr);
 SCTP_DBG_OBJCNT(chunk);
 SCTP_DBG_OBJCNT(addr);
 SCTP_DBG_OBJCNT(ssnmap);
+SCTP_DBG_OBJCNT(datamsg);
 
 /* An array to make it easy to pretty print the debug information
  * to the proc fs.
@@ -68,6 +70,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[
 	SCTP_DBG_OBJCNT_ENTRY(bind_addr),
 	SCTP_DBG_OBJCNT_ENTRY(addr),
 	SCTP_DBG_OBJCNT_ENTRY(ssnmap),
+	SCTP_DBG_OBJCNT_ENTRY(datamsg),
 };
 
 /* Callback from procfs to read out objcount information.
@@ -86,7 +89,7 @@ static int sctp_dbg_objcnt_read(char *bu
 	char temp[128];
 
 	/* How many entries? */
-	entries = sizeof(sctp_dbg_objcnt)/sizeof(sctp_dbg_objcnt[0]);
+	entries = ARRAY_SIZE(sctp_dbg_objcnt);
 
 	/* Walk the entries and print out the debug information
 	 * for proc fs.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/output.c linux-2.4.26-pre6/net/sctp/output.c
--- linux-2.4.25/net/sctp/output.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/output.c	2004-03-25 00:19:36.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 International Business Machines, Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -97,6 +97,7 @@ struct sctp_packet *sctp_packet_init(str
 	packet->source_port = sport;
 	packet->destination_port = dport;
 	skb_queue_head_init(&packet->chunks);
+	packet->size = SCTP_IP_OVERHEAD;
 	packet->vtag = 0;
 	packet->ecn_capable = 0;
 	packet->get_prepend_chunk = NULL;
@@ -114,7 +115,7 @@ void sctp_packet_free(struct sctp_packet
 	struct sctp_chunk *chunk;
 
         while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)))
-		sctp_free_chunk(chunk);
+		sctp_chunk_free(chunk);
 
 	if (packet->malloced)
 		kfree(packet);
@@ -138,7 +139,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(s
 		if (!packet->has_cookie_echo) {
 			error = sctp_packet_transmit(packet);
 			if (error < 0)
-				chunk->skb->sk->err = -error;
+				chunk->skb->sk->sk_err = -error;
 
 			/* If we have an empty packet, then we can NOT ever
 			 * return PMTU_FULL.
@@ -219,22 +220,16 @@ sctp_xmit_t sctp_packet_append_chunk(str
 		/* Both control chunks and data chunks with TSNs are
 		 * non-fragmentable.
 		 */
-		int fragmentable = sctp_chunk_is_data(chunk) &&
-			(!chunk->has_tsn);
-		if (packet_empty) {
-			if (fragmentable) {
-				retval = SCTP_XMIT_MUST_FRAG;
-				goto finish;
-			} else {
-				/* The packet is too big but we can
-				 * not fragment it--we have to just
-				 * transmit and rely on IP
-				 * fragmentation.
-				 */
-				packet->ipfragok = 1;
-				goto append;
-			}
-		} else { /* !packet_empty */
+		if (packet_empty || !sctp_chunk_is_data(chunk)) {
+			/* We no longer do re-fragmentation.
+			 * Just fragment at the IP layer, if we
+			 * actually hit this condition
+			 */
+
+			packet->ipfragok = 1;
+			goto append;
+
+		} else {
 			retval = SCTP_XMIT_PMTU_FULL;
 			goto finish;
 		}
@@ -288,20 +283,18 @@ int sctp_packet_transmit(struct sctp_pac
 	__u8 has_data = 0;
 	struct dst_entry *dst;
 
-	/* Do NOT generate a chunkless packet... */
-	if (skb_queue_empty(&packet->chunks))
+	/* Do NOT generate a chunkless packet. */
+	chunk = (struct sctp_chunk *)skb_peek(&packet->chunks);
+	if (unlikely(!chunk))
 		return err;
 
 	/* Set up convenience variables... */
-	chunk = (struct sctp_chunk *) (packet->chunks.next);
 	sk = chunk->skb->sk;
 
 	/* Allocate the new skb.  */
 	nskb = dev_alloc_skb(packet->size);
-	if (!nskb) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!nskb)
+		goto nomem;
 
 	/* Make sure the outbound skb has enough header room reserved. */
 	skb_reserve(nskb, SCTP_IP_OVERHEAD);
@@ -327,7 +320,6 @@ int sctp_packet_transmit(struct sctp_pac
 	sh->vtag     = htonl(packet->vtag);
 	sh->checksum = 0;
 
-
 	/* 2) Calculate the Adler-32 checksum of the whole packet,
 	 *    including the SCTP common header and all the
 	 *    chunks.
@@ -358,10 +350,11 @@ int sctp_packet_transmit(struct sctp_pac
 	 */
 	SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
 	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
-		chunk->num_times_sent++;
-		chunk->sent_at = jiffies;
 		if (sctp_chunk_is_data(chunk)) {
-			sctp_chunk_assign_tsn(chunk);
+
+			if (!chunk->has_tsn) {
+				sctp_chunk_assign_ssn(chunk);
+				sctp_chunk_assign_tsn(chunk);
 
 			/* 6.3.1 C4) When data is in flight and when allowed
 			 * by rule C5, a new RTT measurement MUST be made each
@@ -369,23 +362,27 @@ int sctp_packet_transmit(struct sctp_pac
 			 * SHOULD be made no more than once per round-trip
 			 * for a given destination transport address.
 			 */
-			if ((1 == chunk->num_times_sent) &&
-			    (!tp->rto_pending)) {
-				chunk->rtt_in_progress = 1;
-				tp->rto_pending = 1;
-			}
+
+				if (!tp->rto_pending) {
+					chunk->rtt_in_progress = 1;
+					tp->rto_pending = 1;
+				}
+			} else
+				chunk->resent = 1;
+
+			chunk->sent_at = jiffies;
 			has_data = 1;
 		}
+
 		padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len;
 		if (padding)
-			memset(skb_put(chunk->skb, padding), 0, padding);      
+			memset(skb_put(chunk->skb, padding), 0, padding);
 
 		crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
-					       chunk->skb->data, 
+					       chunk->skb->data,
 					       chunk->skb->len, crc32);
-		
-		SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, "
-				  "%s %d\n",
+
+		SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
 				  "*** Chunk", chunk,
 				  sctp_cname(SCTP_ST_CHUNK(
 					  chunk->chunk_hdr->type)),
@@ -394,7 +391,6 @@ int sctp_packet_transmit(struct sctp_pac
 				  ntohl(chunk->subh.data_hdr->tsn) : 0,
 				  "length", ntohs(chunk->chunk_hdr->length),
 				  "chunk->skb->len", chunk->skb->len,
-				  "num_times_sent", chunk->num_times_sent,
 				  "rtt_in_progress", chunk->rtt_in_progress);
 
 		/*
@@ -403,7 +399,7 @@ int sctp_packet_transmit(struct sctp_pac
 		 * acknowledged or have failed.
 		 */
 		if (!sctp_chunk_is_data(chunk))
-			sctp_free_chunk(chunk);
+    			sctp_chunk_free(chunk);
 	}
 
 	/* Perform final transformation on checksum. */
@@ -420,21 +416,17 @@ int sctp_packet_transmit(struct sctp_pac
 	 *   data sender to indicate that the end-points of the
 	 *   transport protocol are ECN-capable."
 	 *
-	 * If ECN capable && negotiated && it makes sense for
-	 * this packet to support it (e.g. post ECN negotiation)
-	 * then lets set the ECT bit
+	 * Now setting the ECT bit all the time, as it should not cause
+	 * any problems protocol-wise even if our peer ignores it.
 	 *
-	 * FIXME:  Need to do something else for IPv6
+	 * Note: The works for IPv6 layer checks this bit too later
+	 * in transmission.  See IP6_ECN_flow_xmit().
 	 */
-	if (packet->ecn_capable) {
-		INET_ECN_xmit(nskb->sk);
-	} else {
-		INET_ECN_dontxmit(nskb->sk);
-	}
+	INET_ECN_xmit(nskb->sk);
 
 	/* Set up the IP options.  */
 	/* BUG: not implemented
-	 * For v4 this all lives somewhere in sk->opt...
+	 * For v4 this all lives somewhere in sk->sk_opt...
 	 */
 
 	/* Dump that on IP!  */
@@ -452,8 +444,7 @@ int sctp_packet_transmit(struct sctp_pac
 		tp->last_time_used = jiffies;
 
 		/* Restart the AUTOCLOSE timer when sending data. */
-		if ((SCTP_STATE_ESTABLISHED == asoc->state) &&
-		    (asoc->autoclose)) {
+		if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
 			timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
 			timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
 
@@ -474,9 +465,11 @@ int sctp_packet_transmit(struct sctp_pac
 	if (!nskb->dst)
 		goto no_route;
 
-	SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n",
+	SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
 			  nskb->len);
+
 	(*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
+
 out:
 	packet->size = SCTP_IP_OVERHEAD;
 	return err;
@@ -492,7 +485,20 @@ no_route:
 	 * required.
 	 */
 	 /* err = -EHOSTUNREACH; */
+err:
+	/* Control chunks are unreliable so just drop them.  DATA chunks
+	 * will get resent or dropped later.
+	 */
+
+	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
+		if (!sctp_chunk_is_data(chunk))
+    			sctp_chunk_free(chunk);
+	}
 	goto out;
+nomem:
+	err = -ENOMEM;
+	printk("%s alloc_skb failed.\n", __FUNCTION__);
+	goto err;
 }
 
 /********************************************************************
@@ -604,7 +610,7 @@ static sctp_xmit_t sctp_packet_append_da
 	 * unacknowledged.
 	 */
 	if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size &&
-	    q->outstanding_bytes && SCTP_STATE_ESTABLISHED == asoc->state) {
+	    q->outstanding_bytes && sctp_state(asoc, ESTABLISHED)) {
 		unsigned len = datasize + q->out_qlen;
 
 		/* Check whether this chunk and all the rest of pending
@@ -630,6 +636,8 @@ static sctp_xmit_t sctp_packet_append_da
 		rwnd = 0;
 
 	asoc->peer.rwnd = rwnd;
+	/* Has been accepted for transmission. */
+	chunk->msg->can_expire = 0;
 
 finish:
 	return retval;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/outqueue.c linux-2.4.26-pre6/net/sctp/outqueue.c
--- linux-2.4.25/net/sctp/outqueue.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/outqueue.c	2004-03-25 00:18:29.000000000 +0000
@@ -56,13 +56,19 @@
 #include <net/sctp/sm.h>
 
 /* Declare internal functions here.  */
-static int sctp_acked(sctp_sackhdr_t *sack, __u32 tsn);
+static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
 static void sctp_check_transmitted(struct sctp_outq *q,
 				   struct list_head *transmitted_queue,
 				   struct sctp_transport *transport,
-				   sctp_sackhdr_t *sack,
+				   struct sctp_sackhdr *sack,
 				   __u32 highest_new_tsn);
 
+static void sctp_mark_missing(struct sctp_outq *q,
+			      struct list_head *transmitted_queue,
+			      struct sctp_transport *transport,
+			      __u32 highest_new_tsn,
+			      int count_of_newacks);
+
 /* Add data to the front of the queue. */
 static inline void sctp_outq_head_data(struct sctp_outq *q,
 					struct sctp_chunk *ch)
@@ -100,6 +106,98 @@ static inline void sctp_outq_insert_data
 	q->out_qlen += ch->skb->len;
 }
 
+/*
+ * SFR-CACC algorithm:
+ * D) If count_of_newacks is greater than or equal to 2
+ * and t was not sent to the current primary then the
+ * sender MUST NOT increment missing report count for t.
+ */
+static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary,
+				       struct sctp_transport *transport,
+				       int count_of_newacks)
+{
+	if (count_of_newacks >=2 && transport != primary)
+		return 1;
+	return 0;
+}
+
+/*
+ * SFR-CACC algorithm:
+ * F) If count_of_newacks is less than 2, let d be the
+ * destination to which t was sent. If cacc_saw_newack
+ * is 0 for destination d, then the sender MUST NOT
+ * increment missing report count for t.
+ */
+static inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport,
+				       int count_of_newacks)
+{
+	if (count_of_newacks < 2 && !transport->cacc.cacc_saw_newack)
+		return 1;
+	return 0;
+}
+
+/*
+ * SFR-CACC algorithm:
+ * 3.1) If CYCLING_CHANGEOVER is 0, the sender SHOULD
+ * execute steps C, D, F.
+ *
+ * C has been implemented in sctp_outq_sack
+ */
+static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary,
+				     struct sctp_transport *transport,
+				     int count_of_newacks)
+{
+	if (!primary->cacc.cycling_changeover) {
+		if (sctp_cacc_skip_3_1_d(primary, transport, count_of_newacks))
+			return 1;
+		if (sctp_cacc_skip_3_1_f(transport, count_of_newacks))
+			return 1;
+		return 0;
+	}
+	return 0;
+}
+
+/*
+ * SFR-CACC algorithm:
+ * 3.2) Else if CYCLING_CHANGEOVER is 1, and t is less
+ * than next_tsn_at_change of the current primary, then
+ * the sender MUST NOT increment missing report count
+ * for t.
+ */
+static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn)
+{
+	if (primary->cacc.cycling_changeover &&
+	    TSN_lt(tsn, primary->cacc.next_tsn_at_change))
+		return 1;
+	return 0;
+}
+
+/*
+ * SFR-CACC algorithm:
+ * 3) If the missing report count for TSN t is to be
+ * incremented according to [RFC2960] and
+ * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set,
+ * then the sender MUST futher execute steps 3.1 and
+ * 3.2 to determine if the missing report count for
+ * TSN t SHOULD NOT be incremented.
+ *
+ * 3.3) If 3.1 and 3.2 do not dictate that the missing
+ * report count for t should not be incremented, then
+ * the sender SOULD increment missing report count for
+ * t (according to [RFC2960] and [SCTP_STEWART_2002]).
+ */
+static inline int sctp_cacc_skip(struct sctp_transport *primary,
+				 struct sctp_transport *transport,
+				 int count_of_newacks,
+				 __u32 tsn)
+{
+	if (primary->cacc.changeover_active &&
+	    (sctp_cacc_skip_3_1(primary, transport, count_of_newacks)
+	     || sctp_cacc_skip_3_2(primary, tsn)))
+		return 1;
+	return 0;
+}
+
 /* Generate a new outqueue.  */
 struct sctp_outq *sctp_outq_new(struct sctp_association *asoc)
 {
@@ -133,6 +231,7 @@ void sctp_outq_init(struct sctp_associat
 
 	q->outstanding_bytes = 0;
 	q->empty = 1;
+	q->cork  = 0;
 
 	q->malloced = 0;
 	q->out_qlen = 0;
@@ -144,59 +243,51 @@ void sctp_outq_teardown(struct sctp_outq
 {
 	struct sctp_transport *transport;
 	struct list_head *lchunk, *pos, *temp;
-	sctp_chunk_t *chunk;
-	struct sctp_ulpevent *ev;
+	struct sctp_chunk *chunk;
 
 	/* Throw away unacknowledged chunks. */
 	list_for_each(pos, &q->asoc->peer.transport_addr_list) {
 		transport = list_entry(pos, struct sctp_transport, transports);
 		while ((lchunk = sctp_list_dequeue(&transport->transmitted))) {
-			chunk = list_entry(lchunk, sctp_chunk_t,
+			chunk = list_entry(lchunk, struct sctp_chunk,
 					   transmitted_list);
-
-			/* Generate a SEND FAILED event. */
-			ev = sctp_ulpevent_make_send_failed(q->asoc,
-					chunk, SCTP_DATA_SENT,
-					q->error, GFP_ATOMIC);
-			if (ev)
-				sctp_ulpq_tail_event(&q->asoc->ulpq, ev);
-
-			sctp_free_chunk(chunk);
+			/* Mark as part of a failed message. */
+			sctp_datamsg_fail(chunk, q->error);
+			sctp_chunk_free(chunk);
 		}
 	}
 
 	/* Throw away chunks that have been gap ACKed.  */
 	list_for_each_safe(lchunk, temp, &q->sacked) {
-		list_del(lchunk);
-		chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
-		sctp_free_chunk(chunk);
+		list_del_init(lchunk);
+		chunk = list_entry(lchunk, struct sctp_chunk,
+				   transmitted_list);
+		sctp_datamsg_fail(chunk, q->error);
+		sctp_chunk_free(chunk);
 	}
 
 	/* Throw away any chunks in the retransmit queue. */
 	list_for_each_safe(lchunk, temp, &q->retransmit) {
-		list_del(lchunk);
-		chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
-		sctp_free_chunk(chunk);
+		list_del_init(lchunk);
+		chunk = list_entry(lchunk, struct sctp_chunk,
+				   transmitted_list);
+		sctp_datamsg_fail(chunk, q->error);
+		sctp_chunk_free(chunk);
 	}
 
 	/* Throw away any leftover data chunks. */
 	while ((chunk = sctp_outq_dequeue_data(q))) {
 
-		/* Generate a SEND FAILED event. */
-		ev = sctp_ulpevent_make_send_failed(q->asoc,
-				chunk, SCTP_DATA_UNSENT,
-				q->error, GFP_ATOMIC);
-		if (ev)
-			sctp_ulpq_tail_event(&q->asoc->ulpq, ev);
-
-		sctp_free_chunk(chunk);
+		/* Mark as send failure. */
+		sctp_datamsg_fail(chunk, q->error);
+		sctp_chunk_free(chunk);
 	}
 
 	q->error = 0;
 
 	/* Throw away any leftover control chunks. */
-	while ((chunk = (sctp_chunk_t *) skb_dequeue(&q->control)))
-		sctp_free_chunk(chunk);
+	while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control)))
+		sctp_chunk_free(chunk);
 }
 
 /* Free the outqueue structure and any related pending chunks.  */
@@ -211,7 +302,7 @@ void sctp_outq_free(struct sctp_outq *q)
 }
 
 /* Put a new chunk in an sctp_outq.  */
-int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk)
+int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
 {
 	int error = 0;
 
@@ -266,7 +357,8 @@ int sctp_outq_tail(struct sctp_outq *q, 
 	if (error < 0)
 		return error;
 
-	error = sctp_outq_flush(q, 0);
+	if (!q->cork)
+		error = sctp_outq_flush(q, 0);
 
 	return error;
 }
@@ -277,15 +369,16 @@ int sctp_outq_tail(struct sctp_outq *q, 
 void sctp_retransmit_insert(struct list_head *tlchunk, struct sctp_outq *q)
 {
 	struct list_head *rlchunk;
-	sctp_chunk_t *tchunk, *rchunk;
+	struct sctp_chunk *tchunk, *rchunk;
 	__u32 ttsn, rtsn;
 	int done = 0;
 
-	tchunk = list_entry(tlchunk, sctp_chunk_t, transmitted_list);
+	tchunk = list_entry(tlchunk, struct sctp_chunk, transmitted_list);
 	ttsn = ntohl(tchunk->subh.data_hdr->tsn);
 
 	list_for_each(rlchunk, &q->retransmit) {
-		rchunk = list_entry(rlchunk, sctp_chunk_t, transmitted_list);
+		rchunk = list_entry(rlchunk, struct sctp_chunk,
+				    transmitted_list);
 		rtsn = ntohl(rchunk->subh.data_hdr->tsn);
 		if (TSN_lt(ttsn, rtsn)) {
 			list_add(tlchunk, rlchunk->prev);
@@ -304,11 +397,12 @@ void sctp_retransmit_mark(struct sctp_ou
 			  __u8 fast_retransmit)
 {
 	struct list_head *lchunk, *ltemp;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 
 	/* Walk through the specified transmitted queue.  */
 	list_for_each_safe(lchunk, ltemp, &transport->transmitted) {
-		chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
+		chunk = list_entry(lchunk, struct sctp_chunk,
+				   transmitted_list);
 
 		/* If we are doing retransmission due to a fast retransmit,
 		 * only the chunk's that are marked for fast retransmit
@@ -352,7 +446,7 @@ void sctp_retransmit_mark(struct sctp_ou
 			/* Move the chunk to the retransmit queue. The chunks
 			 * on the retransmit queue is always kept in order.
 			 */
-			list_del(lchunk);
+			list_del_init(lchunk);
 			sctp_retransmit_insert(lchunk, q);
 		}
 	}
@@ -399,7 +493,7 @@ void sctp_retransmit(struct sctp_outq *q
 	error = sctp_outq_flush(q, /* rtx_timeout */ 1);
 
 	if (error)
-		q->asoc->base.sk->err = -error;
+		q->asoc->base.sk->sk_err = -error;
 }
 
 /*
@@ -417,7 +511,7 @@ static int sctp_outq_flush_rtx(struct sc
 	struct list_head *lchunk;
 	struct sctp_transport *transport = pkt->transport;
 	sctp_xmit_t status;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	struct sctp_association *asoc;
 	int error = 0;
 
@@ -443,7 +537,8 @@ static int sctp_outq_flush_rtx(struct sc
 	lchunk = sctp_list_dequeue(lqueue);
 
 	while (lchunk) {
-		chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
+		chunk = list_entry(lchunk, struct sctp_chunk,
+				   transmitted_list);
 
 		/* Make sure that Gap Acked TSNs are not retransmitted.  A
 		 * simple approach is just to move such TSNs out of the
@@ -505,215 +600,19 @@ static int sctp_outq_flush_rtx(struct sc
 	return error;
 }
 
-/* This routine either transmits the fragment or puts it on the output
- * queue.  'pos' points to the next chunk in the output queue after the
- * chunk that is currently in the process of fragmentation.
- */
-void sctp_xmit_frag(struct sctp_outq *q, struct sctp_chunk *pos,
-		struct sctp_packet *packet, struct sctp_chunk *frag, __u32 tsn)
-{
-	struct sctp_transport *transport = packet->transport;
-	struct sk_buff_head *queue = &q->out;
-	sctp_xmit_t status;
-	int error;
-
-	frag->subh.data_hdr->tsn = htonl(tsn);
-	frag->has_tsn = 1;
-
-	/* An inner fragment may be smaller than the earlier one and may get
-	 * in if we call q->build_output.  This ensures that all the fragments
-	 * are sent in order.
-	 */
-	if (!skb_queue_empty(queue)) {
-		SCTP_DEBUG_PRINTK("sctp_xmit_frag: q not empty. "
-				  "adding 0x%x to outqueue\n",
-				  ntohl(frag->subh.data_hdr->tsn));
-		if (pos)
-			sctp_outq_insert_data(q, frag, pos);
-		else
-			sctp_outq_tail_data(q, frag);
-		return;
-	}
-
-	/* Add the chunk fragment to the packet.  */
-	status = (*q->build_output)(packet, frag);
-	switch (status) {
-	case SCTP_XMIT_RWND_FULL:
-		/* RWND is full, so put the chunk in the output queue. */
-		SCTP_DEBUG_PRINTK("sctp_xmit_frag: rwnd full. "
-				  "adding 0x%x to outqueue\n",
-				  ntohl(frag->subh.data_hdr->tsn));
-		if (pos)
-			sctp_outq_insert_data(q, frag, pos);
-		else
-			sctp_outq_tail_data(q, frag);
-		break;
-
-	case SCTP_XMIT_OK:
-		error = (*q->force_output)(packet);
-		if (error < 0) {
-			/* Packet could not be transmitted, put the chunk in
-			 * the output queue
-			 */
-			SCTP_DEBUG_PRINTK("sctp_xmit_frag: force output "
-					  "failed. adding 0x%x to outqueue\n",
-					  ntohl(frag->subh.data_hdr->tsn));
-			if (pos)
-				sctp_outq_insert_data(q, frag, pos);
-			else
-				sctp_outq_tail_data(q, frag);
-		} else {
-			SCTP_DEBUG_PRINTK("sctp_xmit_frag: force output "
-					  "success. 0x%x sent\n",
-					  ntohl(frag->subh.data_hdr->tsn));
-			list_add_tail(&frag->transmitted_list,
-				      &transport->transmitted);
-
-			sctp_transport_reset_timers(transport);
-		}
-		break;
-
-	default:
-		BUG();
-	};
-}
-
-/* This routine calls sctp_xmit_frag() for all the fragments of a message.
- * The argument 'frag' point to the first fragment and it holds the list
- * of all the other fragments in the 'frag_list' field.
- */
-void sctp_xmit_fragmented_chunks(struct sctp_outq *q, struct sctp_packet *pkt,
-				 sctp_chunk_t *frag)
-{
-	struct sctp_association *asoc = frag->asoc;
-	struct list_head *lfrag, *frag_list;
-	__u32 tsn;
-	int nfrags = 1;
-	struct sctp_chunk *pos;
-
-	/* Count the number of fragments. */
-	frag_list = &frag->frag_list;
-	list_for_each(lfrag, frag_list) {
-		nfrags++;
-	}
-
-	/* Get a TSN block of nfrags TSNs. */
-	tsn = sctp_association_get_tsn_block(asoc, nfrags);
-
-	pos = (struct sctp_chunk *)skb_peek(&q->out);
-	/* Transmit the first fragment. */
-	sctp_xmit_frag(q, pos, pkt, frag, tsn++);
-
-	/* Transmit the rest of fragments. */
-	frag_list = &frag->frag_list;
-	list_for_each(lfrag, frag_list) {
-		frag = list_entry(lfrag, sctp_chunk_t, frag_list);
-		sctp_xmit_frag(q, pos, pkt, frag, tsn++);
-	}
-}
-
-/* This routine breaks the given chunk into 'max_frag_data_len' size
- * fragments.  It returns the first fragment with the frag_list field holding
- * the remaining fragments.
- */
-sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk,
-				  size_t max_frag_data_len)
+/* Cork the outqueue so queued chunks are really queued. */
+int sctp_outq_uncork(struct sctp_outq *q)
 {
-	struct sctp_association *asoc = chunk->asoc;
-	void *data_ptr = chunk->subh.data_hdr;
-	struct sctp_sndrcvinfo *sinfo = &chunk->sinfo;
-	__u16 chunk_data_len = sctp_data_size(chunk);
-	__u16 ssn = ntohs(chunk->subh.data_hdr->ssn);
-	sctp_chunk_t *first_frag, *frag;
-	struct list_head *frag_list;
-	int nfrags;
-	__u8 old_flags, flags;
-
-	/* nfrags = no. of max size fragments + any smaller last fragment. */
-	nfrags = ((chunk_data_len / max_frag_data_len) +
-		  ((chunk_data_len % max_frag_data_len) ? 1 : 0));
-
-	/* Start of the data in the chunk. */
-	data_ptr += sizeof(sctp_datahdr_t);
-
-	/* Are we fragmenting an already fragmented large message? */
- 	old_flags = chunk->chunk_hdr->flags;
-	if (old_flags & SCTP_DATA_FIRST_FRAG)
-		flags = SCTP_DATA_FIRST_FRAG;
-	else
-		flags = SCTP_DATA_MIDDLE_FRAG;
-
-	/* Make the first fragment. */
-	first_frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len,
-					data_ptr, flags, ssn);
-
-	if (!first_frag)
-		goto err;
-	first_frag->has_ssn = 1;
-	/* All the fragments are added to the frag_list of the first chunk. */
-	frag_list = &first_frag->frag_list;
-
-	chunk_data_len -= max_frag_data_len;
-	data_ptr += max_frag_data_len;
-
-	/* Make the middle fragments. */
-	while (chunk_data_len > max_frag_data_len) {
-		frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len,
-					  data_ptr, SCTP_DATA_MIDDLE_FRAG,
-					  ssn);
-		if (!frag)
-			goto err;
-		frag->has_ssn = 1;
-		/* Add the middle fragment to the first fragment's
-		 * frag_list.
-		 */
-		list_add_tail(&frag->frag_list, frag_list);
-
-		chunk_data_len -= max_frag_data_len;
-		data_ptr += max_frag_data_len;
-	}
-
-	if (old_flags & SCTP_DATA_LAST_FRAG)
-		flags = SCTP_DATA_LAST_FRAG;
-	else
-		flags = SCTP_DATA_MIDDLE_FRAG;
-
-	/* Make the last fragment. */
-	frag = sctp_make_datafrag(asoc, sinfo, chunk_data_len, data_ptr,
-				  flags, ssn);
-	if (!frag)
-		goto err;
-	frag->has_ssn = 1;
-
-	/* Add the last fragment to the first fragment's frag_list. */
-	list_add_tail(&frag->frag_list, frag_list);
-
-	/* Free the original chunk. */
-	sctp_free_chunk(chunk);
-
-	return first_frag;
-
-err:
-	/* Free any fragments that are created before the failure.  */
-	if (first_frag) {
-		struct list_head *flist, *lfrag;
-
-		/* Free all the fragments off the first one. */
-		flist = &first_frag->frag_list;
-		while (NULL != (lfrag = sctp_list_dequeue(flist))) {
-			frag = list_entry(lfrag, sctp_chunk_t, frag_list);
-			sctp_free_chunk(frag);
-		}
-
-		/* Free the first fragment. */
-		sctp_free_chunk(first_frag);
+	int error = 0;
+	if (q->cork) {
+		q->cork = 0;
+		error = sctp_outq_flush(q, 0);
 	}
-
-	return NULL;
+	return error;
 }
 
 /*
- * sctp_outq_flush - Try to flush an outqueue.
+ * Try to flush an outqueue.
  *
  * Description: Send everything in q which we legally can, subject to
  * congestion limitations.
@@ -736,7 +635,7 @@ int sctp_outq_flush(struct sctp_outq *q,
 	struct sk_buff_head *queue;
 	struct sctp_transport *transport = NULL;
 	struct sctp_transport *new_transport;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	sctp_xmit_t status;
 	int error = 0;
 	int start_timer = 0;
@@ -763,7 +662,7 @@ int sctp_outq_flush(struct sctp_outq *q,
 	}
 
 	queue = &q->control;
-	while ((chunk = (sctp_chunk_t *)skb_dequeue(queue))) {
+	while ((chunk = (struct sctp_chunk *)skb_dequeue(queue))) {
 		/* Pick the right transport to use. */
 		new_transport = chunk->transport;
 
@@ -903,32 +802,25 @@ int sctp_outq_flush(struct sctp_outq *q,
 			 */
 			if (chunk->sinfo.sinfo_stream >=
 			    asoc->c.sinit_num_ostreams) {
-				struct sctp_ulpevent *ev;
 
-				/* Generate a SEND FAILED event. */
-				ev = sctp_ulpevent_make_send_failed(asoc,
-					    chunk, SCTP_DATA_UNSENT,
-					    SCTP_ERROR_INV_STRM, GFP_ATOMIC);
-				if (ev)
-					sctp_ulpq_tail_event(&asoc->ulpq, ev);
-
-				/* Free the chunk. */
-				sctp_free_chunk(chunk);
+				/* Mark as s failed send. */
+				sctp_datamsg_fail(chunk, SCTP_ERROR_INV_STRM);
+				sctp_chunk_free(chunk);
 				continue;
 			}
 
-			/* Now do delayed assignment of SSN.  This will
-			 * probably change again when we start supporting
-			 * large (> approximately 2^16) size messages.
-			 */
-			sctp_chunk_assign_ssn(chunk);
+			/* Has this chunk expired? */
+			if (sctp_datamsg_expires(chunk)) {
+				sctp_datamsg_fail(chunk, 0);
+				sctp_chunk_free(chunk);
+				continue;
+			}
 
 			/* If there is a specified transport, use it.
 			 * Otherwise, we want to use the active path.
 			 */
 			new_transport = chunk->transport;
-			if (new_transport == NULL ||
-			    !new_transport->active)
+			if (!new_transport || !new_transport->active)
 				new_transport = asoc->peer.active_path;
 
 			/* Change packets if necessary.  */
@@ -980,26 +872,6 @@ int sctp_outq_flush(struct sctp_outq *q,
 				goto sctp_flush_out;
 				break;
 
-			case SCTP_XMIT_MUST_FRAG: {
-				sctp_chunk_t *frag;
-
-				frag = sctp_fragment_chunk(chunk,
-					packet->transport->asoc->frag_point);
-				if (!frag) {
-					/* We could not fragment due to out of
-					 * memory condition. Free the original
-					 * chunk and return ENOMEM.
-					 */
-					sctp_free_chunk(chunk);
-					error = -ENOMEM;
-					return error;
-				}
-
-				sctp_xmit_fragmented_chunks(q, packet, frag);
-				goto sctp_flush_out;
-				break;
-			}
-
 			case SCTP_XMIT_OK:
 				break;
 
@@ -1079,7 +951,7 @@ int sctp_outq_set_output_handlers(struct
 
 /* Update unack_data based on the incoming SACK chunk */
 static void sctp_sack_update_unack_data(struct sctp_association *assoc,
-					sctp_sackhdr_t *sack)
+					struct sctp_sackhdr *sack)
 {
 	sctp_sack_variable_t *frags;
 	__u16 unack_data;
@@ -1097,12 +969,12 @@ static void sctp_sack_update_unack_data(
 }
 
 /* Return the highest new tsn that is acknowledged by the given SACK chunk. */
-static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack,
+static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack,
 				  struct sctp_association *asoc)
 {
 	struct list_head *ltransport, *lchunk;
 	struct sctp_transport *transport;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	__u32 highest_new_tsn, tsn;
 	struct list_head *transport_list = &asoc->peer.transport_addr_list;
 
@@ -1112,7 +984,7 @@ static __u32 sctp_highest_new_tsn(sctp_s
 		transport = list_entry(ltransport, struct sctp_transport,
 				       transports);
 		list_for_each(lchunk, &transport->transmitted) {
-			chunk = list_entry(lchunk, sctp_chunk_t,
+			chunk = list_entry(lchunk, struct sctp_chunk,
 					   transmitted_list);
 			tsn = ntohl(chunk->subh.data_hdr->tsn);
 
@@ -1131,26 +1003,64 @@ static __u32 sctp_highest_new_tsn(sctp_s
  * Process the SACK against the outqueue.  Mostly, this just frees
  * things off the transmitted queue.
  */
-int sctp_outq_sack(struct sctp_outq *q, sctp_sackhdr_t *sack)
+int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
 {
 	struct sctp_association *asoc = q->asoc;
 	struct sctp_transport *transport;
-	sctp_chunk_t *tchunk;
-	struct list_head *lchunk, *transport_list, *pos;
+	struct sctp_chunk *tchunk;
+	struct list_head *lchunk, *transport_list, *pos, *temp;
 	sctp_sack_variable_t *frags = sack->variable;
 	__u32 sack_ctsn, ctsn, tsn;
 	__u32 highest_tsn, highest_new_tsn;
 	__u32 sack_a_rwnd;
-	int outstanding;
+	unsigned outstanding;
+	struct sctp_transport *primary = asoc->peer.primary_path;
+	int count_of_newacks = 0;
 
 	/* Grab the association's destination address list. */
 	transport_list = &asoc->peer.transport_addr_list;
 
 	sack_ctsn = ntohl(sack->cum_tsn_ack);
 
+	/*
+	 * SFR-CACC algorithm:
+	 * On receipt of a SACK the sender SHOULD execute the
+	 * following statements.
+	 *
+	 * 1) If the cumulative ack in the SACK passes next tsn_at_change
+	 * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be
+	 * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for
+	 * all destinations.
+	 */
+	if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) {
+		primary->cacc.changeover_active = 0;
+		list_for_each(pos, transport_list) {
+			transport = list_entry(pos, struct sctp_transport,
+					transports);
+			transport->cacc.cycling_changeover = 0;
+		}
+	}
+
+	/*
+	 * SFR-CACC algorithm:
+	 * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE
+	 * is set the receiver of the SACK MUST take the following actions:
+	 *
+	 * A) Initialize the cacc_saw_newack to 0 for all destination
+	 * addresses.
+	 */
+	if (sack->num_gap_ack_blocks > 0 &&
+	    primary->cacc.changeover_active) {
+		list_for_each(pos, transport_list) {
+			transport = list_entry(pos, struct sctp_transport,
+					transports);
+			transport->cacc.cacc_saw_newack = 0;
+		}
+	}
+
 	/* Get the highest TSN in the sack. */
 	highest_tsn = sack_ctsn +
-		      ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end);
+		ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end);
 
 	if (TSN_lt(asoc->highest_sacked, highest_tsn)) {
 		highest_new_tsn = highest_tsn;
@@ -1163,6 +1073,7 @@ int sctp_outq_sack(struct sctp_outq *q, 
 	 * and free those chunks that we can.
 	 */
 	sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn);
+	sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0);
 
 	/* Run through the transmitted queue.
 	 * Credit bytes received and free those chunks which we can.
@@ -1174,6 +1085,20 @@ int sctp_outq_sack(struct sctp_outq *q, 
 					transports);
 		sctp_check_transmitted(q, &transport->transmitted,
 				       transport, sack, highest_new_tsn);
+		/*
+		 * SFR-CACC algorithm:
+		 * C) Let count_of_newacks be the number of
+		 * destinations for which cacc_saw_newack is set.
+		 */
+		if (transport->cacc.cacc_saw_newack)
+			count_of_newacks ++;
+	}
+
+	list_for_each(pos, transport_list) {
+		transport  = list_entry(pos, struct sctp_transport,
+					transports);
+		sctp_mark_missing(q, &transport->transmitted, transport,
+				  highest_new_tsn, count_of_newacks);
 	}
 
 	/* Move the Cumulative TSN Ack Point if appropriate.  */
@@ -1191,13 +1116,12 @@ int sctp_outq_sack(struct sctp_outq *q, 
 			  "%p is 0x%x.\n", __FUNCTION__, asoc, ctsn);
 
 	/* Throw away stuff rotting on the sack queue.  */
-	list_for_each(lchunk, &q->sacked) {
-		tchunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
+	list_for_each_safe(lchunk, temp, &q->sacked) {
+		tchunk = list_entry(lchunk, struct sctp_chunk,
+				    transmitted_list);
 		tsn = ntohl(tchunk->subh.data_hdr->tsn);
-		if (TSN_lte(tsn, ctsn)) {
-			lchunk = lchunk->prev;
-			sctp_free_chunk(tchunk);
-		}
+		if (TSN_lte(tsn, ctsn))
+			sctp_chunk_free(tchunk);
 	}
 
 	/* ii) Set rwnd equal to the newly received a_rwnd minus the
@@ -1245,12 +1169,9 @@ int sctp_outq_is_empty(const struct sctp
  * 2nd Level Abstractions
  ********************************************************************/
 
-/* Go through a transport's transmitted list or the assocication's retransmit
+/* Go through a transport's transmitted list or the association's retransmit
  * list and move chunks that are acked by the Cumulative TSN Ack to q->sacked.
- * The retransmit list will not have an associated transport. In case of a
- * transmitted list with a transport, the transport's congestion, rto and fast
- * retransmit parameters are also updated and if needed a fast retransmit
- * process is started.
+ * The retransmit list will not have an associated transport.
  *
  * I added coherent debug information output.	--xguo
  *
@@ -1261,17 +1182,16 @@ int sctp_outq_is_empty(const struct sctp
 static void sctp_check_transmitted(struct sctp_outq *q,
 				   struct list_head *transmitted_queue,
 				   struct sctp_transport *transport,
-				   sctp_sackhdr_t *sack,
+				   struct sctp_sackhdr *sack,
 				   __u32 highest_new_tsn_in_sack)
 {
 	struct list_head *lchunk;
-	sctp_chunk_t *tchunk;
+	struct sctp_chunk *tchunk;
 	struct list_head tlist;
 	__u32 tsn;
 	__u32 sack_ctsn;
 	__u32 rtt;
 	__u8 restart_timer = 0;
-	__u8 do_fast_retransmit = 0;
 	int bytes_acked = 0;
 
 	/* These state variables are for coherent debug output. --xguo */
@@ -1295,7 +1215,8 @@ static void sctp_check_transmitted(struc
 
 	/* The while loop will skip empty transmitted queues. */
 	while (NULL != (lchunk = sctp_list_dequeue(transmitted_queue))) {
-		tchunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
+		tchunk = list_entry(lchunk, struct sctp_chunk,
+				    transmitted_list);
 
 		tsn = ntohl(tchunk->subh.data_hdr->tsn);
 		if (sctp_acked(sack, tsn)) {
@@ -1316,9 +1237,9 @@ static void sctp_check_transmitted(struc
 				 * first instance of the packet or a later
 				 * instance).
 				 */
-			   	if ((!tchunk->tsn_gap_acked) &&
-				    (1 == tchunk->num_times_sent) &&
-				    (tchunk->rtt_in_progress)) {
+			   	if (!tchunk->tsn_gap_acked &&
+				    !tchunk->resent &&
+				    tchunk->rtt_in_progress) {
 					rtt = jiffies - tchunk->sent_at;
 					sctp_transport_update_rto(transport,
 								  rtt);
@@ -1339,6 +1260,25 @@ static void sctp_check_transmitted(struc
 				if (!tchunk->tsn_gap_acked) {
 					tchunk->tsn_gap_acked = 1;
 					bytes_acked += sctp_data_size(tchunk);
+					/*
+					 * SFR-CACC algorithm:
+					 * 2) If the SACK contains gap acks
+					 * and the flag CHANGEOVER_ACTIVE is
+					 * set the receiver of the SACK MUST
+					 * take the following action:
+					 *
+					 * B) For each TSN t being acked that
+					 * has not been acked in any SACK so
+					 * far, set cacc_saw_newack to 1 for
+					 * the destination that the TSN was
+					 * sent to.
+					 */
+					if (transport &&
+					    sack->num_gap_ack_blocks &&
+					    q->asoc->peer.primary_path->cacc.
+					    changeover_active)
+						transport->cacc.cacc_saw_newack
+							= 1;
 				}
 
 				list_add_tail(&tchunk->transmitted_list,
@@ -1525,8 +1465,8 @@ static void sctp_check_transmitted(struc
 			 * receiver's advertised window is zero, and there is
 			 * only one data chunk in flight to the receiver.
 			 */
-			if ((0 == q->asoc->peer.rwnd) &&
-			    (!list_empty(&tlist)) &&
+			if (!q->asoc->peer.rwnd &&
+			    !list_empty(&tlist) &&
 			    (sack_ctsn+2 == q->asoc->next_tsn)) {
 				SCTP_DEBUG_PRINTK("%s: SACK received for zero "
 						  "window probe: %u\n",
@@ -1554,12 +1494,26 @@ static void sctp_check_transmitted(struc
 		}
 	}
 
-	/* Reconstruct the transmitted list with chunks that are not yet
-	 * acked by the Cumulative TSN Ack.
-	 */
-        while (NULL != (lchunk = sctp_list_dequeue(&tlist))) {
-		tchunk = list_entry(lchunk, sctp_chunk_t, transmitted_list);
-		tsn = ntohl(tchunk->subh.data_hdr->tsn);
+	list_splice(&tlist, transmitted_queue);
+}
+
+/* Mark chunks as missing and consequently may get retransmitted. */
+static void sctp_mark_missing(struct sctp_outq *q,
+			      struct list_head *transmitted_queue,
+			      struct sctp_transport *transport,
+			      __u32 highest_new_tsn_in_sack,
+			      int count_of_newacks)
+{
+	struct sctp_chunk *chunk;
+	struct list_head *pos;
+	__u32 tsn;
+	char do_fast_retransmit = 0;
+	struct sctp_transport *primary = q->asoc->peer.primary_path;
+
+	list_for_each(pos, transmitted_queue) {
+
+		chunk = list_entry(pos, struct sctp_chunk, transmitted_list);
+		tsn = ntohl(chunk->subh.data_hdr->tsn);
 
 		/* RFC 2960 7.2.4, sctpimpguide-05 2.8.2 M3) Examine all
 		 * 'Unacknowledged TSN's', if the TSN number of an
@@ -1567,26 +1521,35 @@ static void sctp_check_transmitted(struc
 		 * value, increment the 'TSN.Missing.Report' count on that
 		 * chunk if it has NOT been fast retransmitted or marked for
 		 * fast retransmit already.
-		 *
+		 */
+		if (!chunk->fast_retransmit &&
+		    !chunk->tsn_gap_acked &&
+		    TSN_lt(tsn, highest_new_tsn_in_sack)) {
+
+			/* SFR-CACC may require us to skip marking
+			 * this chunk as missing.
+			 */
+			if (!transport || !sctp_cacc_skip(primary, transport,
+					    count_of_newacks, tsn)) {
+				chunk->tsn_missing_report++;
+
+				SCTP_DEBUG_PRINTK(
+					"%s: TSN 0x%x missing counter: %d\n",
+					__FUNCTION__, tsn,
+					chunk->tsn_missing_report);
+			}
+		}
+		/*
 		 * M4) If any DATA chunk is found to have a
 		 * 'TSN.Missing.Report'
 		 * value larger than or equal to 4, mark that chunk for
 		 * retransmission and start the fast retransmit procedure.
 		 */
-		if ((!tchunk->fast_retransmit) &&
-		    (!tchunk->tsn_gap_acked) &&
-		    (TSN_lt(tsn, highest_new_tsn_in_sack))) {
-			tchunk->tsn_missing_report++;
-			SCTP_DEBUG_PRINTK("%s: TSN 0x%x missing counter: %d\n",
-					  __FUNCTION__, tsn,
-					  tchunk->tsn_missing_report);
-		}
-		if (tchunk->tsn_missing_report >= 4) {
-			tchunk->fast_retransmit = 1;
+
+		if (chunk->tsn_missing_report >= 4) {
+			chunk->fast_retransmit = 1;
 			do_fast_retransmit = 1;
 		}
-
-		list_add_tail(lchunk, transmitted_queue);
 	}
 
 	if (transport) {
@@ -1602,7 +1565,7 @@ static void sctp_check_transmitted(struc
 }
 
 /* Is the given TSN acked by this packet?  */
-static int sctp_acked(sctp_sackhdr_t *sack, __u32 tsn)
+static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn)
 {
 	int i;
 	sctp_sack_variable_t *frags;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/primitive.c linux-2.4.26-pre6/net/sctp/primitive.c
--- linux-2.4.25/net/sctp/primitive.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/primitive.c	2004-03-25 00:17:30.000000000 +0000
@@ -39,6 +39,7 @@
  *    Narasimha Budihal     <narasimha@refcode.org>
  *    Karl Knutson          <karl@athena.chicago.il.us>
  *    Ardelle Fan	    <ardelle.fan@intel.com>
+ *    Kevin Gao             <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -203,3 +204,16 @@ DECLARE_PRIMITIVE(SEND);
  */
 
 DECLARE_PRIMITIVE(REQUESTHEARTBEAT);
+
+/* ADDIP
+* 3.1.1 Address Configuration Change Chunk (ASCONF)
+* 
+* This chunk is used to communicate to the remote endpoint one of the
+* configuration change requests that MUST be acknowledged.  The
+* information carried in the ASCONF Chunk uses the form of a
+* Type-Length-Value (TLV), as described in "3.2.1 Optional/
+* Variable-length Parameter Format" in RFC2960 [5], forall variable
+* parameters.
+*/
+
+DECLARE_PRIMITIVE(ASCONF);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/proc.c linux-2.4.26-pre6/net/sctp/proc.c
--- linux-2.4.25/net/sctp/proc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/proc.c	2004-03-25 00:17:59.000000000 +0000
@@ -35,8 +35,6 @@
  */
 
 #include <linux/types.h>
-#include <asm/semaphore.h>
-#include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <net/sctp/sctp.h>
@@ -92,6 +90,7 @@ static int sctp_snmp_seq_show(struct seq
 	for (i = 0; i < sizeof(sctp_snmp_list) / sizeof(char *); i++)
 		seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i],
 			   fold_field((void **)sctp_statistics, i));
+
 	return 0;
 }
 
@@ -102,6 +101,7 @@ static int sctp_snmp_seq_open(struct ino
 }
 
 static struct file_operations sctp_snmp_seq_fops = {
+	.owner	 = THIS_MODULE,
 	.open	 = sctp_snmp_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
@@ -127,3 +127,162 @@ void sctp_snmp_proc_exit(void)
 {
 	remove_proc_entry("snmp", proc_net_sctp);
 }
+
+/* Dump local addresses of an association/endpoint. */
+static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
+{
+	struct list_head *pos;
+	struct sctp_sockaddr_entry *laddr;
+	union sctp_addr *addr;
+	struct sctp_af *af;
+
+	list_for_each(pos, &epb->bind_addr.address_list) {
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
+		addr = (union sctp_addr *)&laddr->a;
+		af = sctp_get_af_specific(addr->sa.sa_family);
+		af->seq_dump_addr(seq, addr);
+	}
+}
+
+/* Dump remote addresses of an association. */
+static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
+{
+	struct list_head *pos;
+	struct sctp_transport *transport;
+	union sctp_addr *addr;
+	struct sctp_af *af;
+
+	list_for_each(pos, &assoc->peer.transport_addr_list) {
+		transport = list_entry(pos, struct sctp_transport, transports);
+		addr = (union sctp_addr *)&transport->ipaddr;
+		af = sctp_get_af_specific(addr->sa.sa_family);
+		af->seq_dump_addr(seq, addr);
+	}
+}
+
+/* Display sctp endpoints (/proc/net/sctp/eps). */
+static int sctp_eps_seq_show(struct seq_file *seq, void *v)
+{
+	struct sctp_hashbucket *head;
+	struct sctp_ep_common *epb;
+	struct sctp_endpoint *ep;
+	struct sock *sk;
+	int hash;
+
+	seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT LADDRS\n");
+	for (hash = 0; hash < sctp_ep_hashsize; hash++) {
+		head = &sctp_ep_hashtable[hash];
+		read_lock(&head->lock);
+		for (epb = head->chain; epb; epb = epb->next) {
+			ep = sctp_ep(epb);
+			sk = epb->sk;
+			seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d ", ep, sk,
+				   sctp_sk(sk)->type, sk->sk_state, hash,
+				   epb->bind_addr.port);
+			sctp_seq_dump_local_addrs(seq, epb);
+			seq_printf(seq, "\n");
+		}
+		read_unlock(&head->lock);
+	}
+
+	return 0;
+}
+
+/* Initialize the seq file operations for 'eps' object. */
+static int sctp_eps_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sctp_eps_seq_show, NULL);
+}
+
+static struct file_operations sctp_eps_seq_fops = {
+	.open	 = sctp_eps_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+/* Set up the proc fs entry for 'eps' object. */
+int __init sctp_eps_proc_init(void)
+{
+	struct proc_dir_entry *p;
+
+	p = create_proc_entry("eps", S_IRUGO, proc_net_sctp);
+	if (!p)
+		return -ENOMEM;
+
+	p->proc_fops = &sctp_eps_seq_fops;
+
+	return 0;
+}
+
+/* Cleanup the proc fs entry for 'eps' object. */
+void sctp_eps_proc_exit(void)
+{
+	remove_proc_entry("eps", proc_net_sctp);
+}
+
+/* Display sctp associations (/proc/net/sctp/assocs). */
+static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
+{
+	struct sctp_hashbucket *head;
+	struct sctp_ep_common *epb;
+	struct sctp_association *assoc;
+	struct sock *sk;
+	int hash;
+
+	seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT LPORT RPORT "
+			"LADDRS <-> RADDRS\n");
+	for (hash = 0; hash < sctp_assoc_hashsize; hash++) {
+		head = &sctp_assoc_hashtable[hash];
+		read_lock(&head->lock);
+		for (epb = head->chain; epb; epb = epb->next) {
+			assoc = sctp_assoc(epb);
+			sk = epb->sk;
+			seq_printf(seq,
+				   "%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ",
+				   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+				   assoc->state, hash, epb->bind_addr.port,
+				   assoc->peer.port);
+			sctp_seq_dump_local_addrs(seq, epb);
+			seq_printf(seq, "<-> ");
+			sctp_seq_dump_remote_addrs(seq, assoc);
+			seq_printf(seq, "\n");
+		}
+		read_unlock(&head->lock);
+	}
+
+	return 0;
+}
+
+/* Initialize the seq file operations for 'assocs' object. */
+static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sctp_assocs_seq_show, NULL);
+}
+
+static struct file_operations sctp_assocs_seq_fops = {
+	.open	 = sctp_assocs_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+/* Set up the proc fs entry for 'assocs' object. */
+int __init sctp_assocs_proc_init(void)
+{
+	struct proc_dir_entry *p;
+
+	p = create_proc_entry("assocs", S_IRUGO, proc_net_sctp);
+	if (!p)
+		return -ENOMEM;
+
+	p->proc_fops = &sctp_assocs_seq_fops;
+
+	return 0;
+}
+
+/* Cleanup the proc fs entry for 'assocs' object. */
+void sctp_assocs_proc_exit(void)
+{
+	remove_proc_entry("assocs", proc_net_sctp);
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/protocol.c linux-2.4.26-pre6/net/sctp/protocol.c
--- linux-2.4.25/net/sctp/protocol.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/protocol.c	2004-03-25 00:20:04.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2002 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -50,15 +50,17 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
+#include <linux/seq_file.h>
 #include <net/protocol.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/sctp/sctp.h>
 #include <net/addrconf.h>
 #include <net/inet_common.h>
+#include <net/inet_ecn.h>
 
 /* Global data structures. */
-struct sctp_protocol sctp_proto;
+struct sctp_globals sctp_globals;
 struct proc_dir_entry	*proc_net_sctp;
 DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
 
@@ -73,10 +75,16 @@ static struct sctp_pf *sctp_pf_inet_spec
 static struct sctp_af *sctp_af_v4_specific;
 static struct sctp_af *sctp_af_v6_specific;
 
+kmem_cache_t *sctp_chunk_cachep;
+
 extern struct net_proto_family inet_family_ops;
 
 extern int sctp_snmp_proc_init(void);
 extern int sctp_snmp_proc_exit(void);
+extern int sctp_eps_proc_init(void);
+extern int sctp_eps_proc_exit(void);
+extern int sctp_assocs_proc_init(void);
+extern int sctp_assocs_proc_exit(void);
 
 /* Return the address of the control sock. */
 struct sock *sctp_get_ctl_sock(void)
@@ -87,8 +95,6 @@ struct sock *sctp_get_ctl_sock(void)
 /* Set up the proc fs entry for the SCTP protocol. */
 __init int sctp_proc_init(void)
 {
-	int rc = 0;
-
 	if (!proc_net_sctp) {
 		struct proc_dir_entry *ent;
 		ent = proc_mkdir("net/sctp", 0);
@@ -96,20 +102,31 @@ __init int sctp_proc_init(void)
 			ent->owner = THIS_MODULE;
 			proc_net_sctp = ent;
 		} else
-			rc = -ENOMEM;
+			goto out_nomem;
 	}
 
 	if (sctp_snmp_proc_init())
-		rc = -ENOMEM;
+		goto out_nomem;	
+	if (sctp_eps_proc_init())
+		goto out_nomem;	
+	if (sctp_assocs_proc_init())
+		goto out_nomem;	
+
+	return 0;
 
-	return rc;
+out_nomem:
+	return -ENOMEM;
 }
 
-/* Clean up the proc fs entry for the SCTP protocol. */
+/* Clean up the proc fs entry for the SCTP protocol. 
+ * Note: Do not make this __exit as it is used in the init error
+ * path.
+ */
 void sctp_proc_exit(void)
 {
-
 	sctp_snmp_proc_exit();
+	sctp_eps_proc_exit();
+	sctp_assocs_proc_exit();
 
 	if (proc_net_sctp) {
 		proc_net_sctp = NULL;
@@ -125,7 +142,7 @@ static void sctp_v4_copy_addrlist(struct
 {
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 
 	read_lock(&inetdev_lock);
 	if ((in_dev = __in_dev_get(dev)) == NULL) {
@@ -136,7 +153,7 @@ static void sctp_v4_copy_addrlist(struct
 	read_lock(&in_dev->lock);
 	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
 		/* Add the address to the local list.  */
-		addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC);
+		addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
 		if (addr) {
 			addr->a.v4.sin_family = AF_INET;
 			addr->a.v4.sin_port = 0;
@@ -152,7 +169,7 @@ static void sctp_v4_copy_addrlist(struct
 /* Extract our IP addresses from the system and stash them in the
  * protocol structure.
  */
-static void __sctp_get_local_addr_list(struct sctp_protocol *proto)
+static void __sctp_get_local_addr_list(void)
 {
 	struct net_device *dev;
 	struct list_head *pos;
@@ -160,59 +177,58 @@ static void __sctp_get_local_addr_list(s
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev; dev = dev->next) {
-		list_for_each(pos, &proto->address_families) {
+		list_for_each(pos, &sctp_address_families) {
 			af = list_entry(pos, struct sctp_af, list);
-			af->copy_addrlist(&proto->local_addr_list, dev);
+			af->copy_addrlist(&sctp_local_addr_list, dev);
 		}
 	}
 	read_unlock(&dev_base_lock);
 }
 
-static void sctp_get_local_addr_list(struct sctp_protocol *proto)
+static void sctp_get_local_addr_list(void)
 {
 	unsigned long flags;
 
-	sctp_spin_lock_irqsave(&sctp_proto.local_addr_lock, flags);
-	__sctp_get_local_addr_list(&sctp_proto);
-	sctp_spin_unlock_irqrestore(&sctp_proto.local_addr_lock, flags);
+	sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+	__sctp_get_local_addr_list();
+	sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
 }
 
 /* Free the existing local addresses.  */
-static void __sctp_free_local_addr_list(struct sctp_protocol *proto)
+static void __sctp_free_local_addr_list(void)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos, *temp;
 
-	list_for_each_safe(pos, temp, &proto->local_addr_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+	list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		list_del(pos);
 		kfree(addr);
 	}
 }
 
 /* Free the existing local addresses.  */
-static void sctp_free_local_addr_list(struct sctp_protocol *proto)
+static void sctp_free_local_addr_list(void)
 {
 	unsigned long flags;
 
-	sctp_spin_lock_irqsave(&proto->local_addr_lock, flags);
-	__sctp_free_local_addr_list(proto);
-	sctp_spin_unlock_irqrestore(&proto->local_addr_lock, flags);
+	sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+	__sctp_free_local_addr_list();
+	sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
 }
 
 /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
-int sctp_copy_local_addr_list(struct sctp_protocol *proto,
-			      struct sctp_bind_addr *bp, sctp_scope_t scope,
+int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
 			      int gfp, int copy_flags)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	int error = 0;
 	struct list_head *pos;
 	unsigned long flags;
 
-	sctp_spin_lock_irqsave(&proto->local_addr_lock, flags);
-	list_for_each(pos, &proto->local_addr_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+	sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+	list_for_each(pos, &sctp_local_addr_list) {
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (sctp_in_scope(&addr->a, scope)) {
 			/* Now that the address is in scope, check to see if
 			 * the address type is really supported by the local
@@ -232,7 +248,7 @@ int sctp_copy_local_addr_list(struct sct
 	}
 
 end_copy:
-	sctp_spin_unlock_irqrestore(&proto->local_addr_lock, flags);
+	sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
 	return error;
 }
 
@@ -262,20 +278,45 @@ static void sctp_v4_from_skb(union sctp_
 static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
 {
 	addr->v4.sin_family = AF_INET;
-	addr->v4.sin_port = (sk)->num;
-	addr->v4.sin_addr.s_addr = (sk)->rcv_saddr;
+	addr->v4.sin_port = sk->num;
+	addr->v4.sin_addr.s_addr = sk->rcv_saddr;
 }
 
-/* Initialize sk->rcv_saddr from sctp_addr. */
+/* Initialize sk->sk_rcv_saddr from sctp_addr. */
 static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
 {
-	(sk)->rcv_saddr = addr->v4.sin_addr.s_addr;
+	sk->rcv_saddr = addr->v4.sin_addr.s_addr;
 }
 
-/* Initialize sk->daddr from sctp_addr. */
+/* Initialize sk->sk_daddr from sctp_addr. */
 static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
 {
-	(sk)->daddr = addr->v4.sin_addr.s_addr;
+	sk->daddr = addr->v4.sin_addr.s_addr;
+}
+
+/* Initialize a sctp_addr from an address parameter. */
+static void sctp_v4_from_addr_param(union sctp_addr *addr,
+				    union sctp_addr_param *param,
+				    __u16 port, int iif)
+{
+	addr->v4.sin_family = AF_INET;
+	addr->v4.sin_port = port;
+	addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
+}
+
+/* Initialize an address parameter from a sctp_addr and return the length
+ * of the address parameter.
+ */
+static int sctp_v4_to_addr_param(const union sctp_addr *addr,
+				 union sctp_addr_param *param)
+{
+	int length = sizeof(sctp_ipv4addr_param_t);
+
+	param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
+	param->v4.param_hdr.length = ntohs(length);
+	param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;	
+
+	return length;
 }
 
 /* Initialize a sctp_addr from a dst_entry. */
@@ -323,7 +364,7 @@ static int sctp_v4_is_any(const union sc
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v4_addr_valid(union sctp_addr *addr)
+static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_opt *sp)
 {
 	/* Is this a non-unicast address or a unusable SCTP address? */
 	if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
@@ -333,7 +374,7 @@ static int sctp_v4_addr_valid(union sctp
 }
 
 /* Should this be available for binding?   */
-static int sctp_v4_available(const union sctp_addr *addr)
+static int sctp_v4_available(union sctp_addr *addr, struct sctp_opt *sp)
 {
 	int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
 
@@ -393,16 +434,20 @@ struct dst_entry *sctp_v4_get_dst(struct
 {
 	struct rtable *rt;
 	struct rt_key key;
-	sctp_bind_addr_t *bp;
+	struct sctp_bind_addr *bp;
 	rwlock_t *addr_lock;
-	struct sockaddr_storage_list *laddr;
+	struct sctp_sockaddr_entry *laddr;
 	struct list_head *pos;
 	struct dst_entry *dst = NULL;
 	union sctp_addr dst_saddr;
-	
+
 	memset(&key, 0x0, sizeof(struct rt_key));
 	key.dst = daddr->v4.sin_addr.s_addr;
-	
+
+	if (asoc) {
+		key.tos = RT_CONN_FLAGS(asoc->base.sk);
+		key.oif = asoc->base.sk->bound_dev_if;
+	}
 	if (saddr)
 		key.src = saddr->v4.sin_addr.s_addr;
 
@@ -429,7 +474,7 @@ struct dst_entry *sctp_v4_get_dst(struct
 		 */
 		sctp_read_lock(addr_lock);
 		list_for_each(pos, &bp->address_list) {
-			laddr = list_entry(pos, struct sockaddr_storage_list,
+			laddr = list_entry(pos, struct sctp_sockaddr_entry,
 					   list);
 			sctp_v4_dst_saddr(&dst_saddr, dst, bp->port);
 			if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
@@ -449,7 +494,7 @@ struct dst_entry *sctp_v4_get_dst(struct
 	 */
 	sctp_read_lock(addr_lock);
 	list_for_each(pos, &bp->address_list) {
-		laddr = list_entry(pos, struct sockaddr_storage_list, list);
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
 
 		if (AF_INET == laddr->a.sa.sa_family) {
 			key.src = laddr->a.v4.sin_addr.s_addr;
@@ -490,11 +535,17 @@ void sctp_v4_get_saddr(struct sctp_assoc
 }
 
 /* What interface did this skb arrive on? */
-int sctp_v4_skb_iif(const struct sk_buff *skb)
+static int sctp_v4_skb_iif(const struct sk_buff *skb)
 {
      	return ((struct rtable *)skb->dst)->rt_iif;
 }
 
+/* Was this packet marked by Explicit Congestion Notification? */
+static int sctp_v4_is_ce(const struct sk_buff *skb)
+{
+	return INET_ECN_is_ce(skb->nh.iph->tos);
+}
+
 /* Create and initialize a new sk for the socket returned by accept(). */
 struct sock *sctp_v4_create_accept_sk(struct sock *sk,
 				      struct sctp_association *asoc)
@@ -510,18 +561,18 @@ struct sock *sctp_v4_create_accept_sk(st
 	sock_init_data(NULL, newsk);
 	sk_set_owner(newsk, THIS_MODULE);
 
-	newsk->type = SOCK_STREAM;
+	newsk->sk_type = SOCK_STREAM;
 
-	newsk->prot = sk->prot;
-	newsk->no_check = sk->no_check;
-	newsk->reuse = sk->reuse;
-	newsk->shutdown = sk->shutdown;
-
-	newsk->destruct = inet_sock_destruct;
-	newsk->zapped = 0;
-	newsk->family = PF_INET;
-	newsk->protocol = IPPROTO_SCTP;
-	newsk->backlog_rcv = sk->prot->backlog_rcv;
+	newsk->sk_prot = sk->sk_prot;
+	newsk->sk_no_check = sk->sk_no_check;
+	newsk->sk_reuse = sk->sk_reuse;
+	newsk->sk_shutdown = sk->sk_shutdown;
+
+	newsk->sk_destruct = inet_sock_destruct;
+	newsk->sk_zapped = 0;
+	newsk->sk_family = PF_INET;
+	newsk->sk_protocol = IPPROTO_SCTP;
+	newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
 
 	newinet = inet_sk(newsk);
 
@@ -546,7 +597,7 @@ struct sock *sctp_v4_create_accept_sk(st
 	atomic_inc(&inet_sock_nr);
 #endif
 
-	if (0 != newsk->prot->init(newsk)) {
+	if (newsk->sk_prot->init(newsk)) {
 		inet_sock_release(newsk);
 		newsk = NULL;
 	}
@@ -555,6 +606,18 @@ out:
 	return newsk;
 }
 
+/* Map address, empty for v4 family */
+static void sctp_v4_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr)
+{
+	/* Empty */
+}
+
+/* Dump the v4 addr to the seq file. */
+static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
+{
+	seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr));
+}
+
 /* Event handler for inet address addition/deletion events.
  * Basically, whenever there is an event, we re-build our local address list.
  */
@@ -563,10 +626,10 @@ static int sctp_inetaddr_event(struct no
 {
 	unsigned long flags;
 
-	sctp_spin_lock_irqsave(&sctp_proto.local_addr_lock, flags);
-	__sctp_free_local_addr_list(&sctp_proto);
-	__sctp_get_local_addr_list(&sctp_proto);
-	sctp_spin_unlock_irqrestore(&sctp_proto.local_addr_lock, flags);
+	sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+	__sctp_free_local_addr_list();
+	__sctp_get_local_addr_list();
+	sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
 
 	return NOTIFY_DONE;
 }
@@ -592,7 +655,7 @@ int sctp_ctl_sock_init(void)
 		       "SCTP: Failed to create the SCTP control socket.\n");
 		return err;
 	}
-	sctp_ctl_socket->sk->allocation = GFP_ATOMIC;
+	sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
 	inet_sk(sctp_ctl_socket->sk)->ttl = MAXTTL;
 
 	return 0;
@@ -617,7 +680,7 @@ int sctp_register_af(struct sctp_af *af)
 	}
 
 	INIT_LIST_HEAD(&af->list);
-	list_add_tail(&af->list, &sctp_proto.address_families);
+	list_add_tail(&af->list, &sctp_address_families);
 	return 1;
 }
 
@@ -654,10 +717,13 @@ static void sctp_inet_event_msgname(stru
 	struct sockaddr_in *sin, *sinfrom;
 
 	if (msgname) {
+		struct sctp_association *asoc;
+
+		asoc = event->sndrcvinfo.sinfo_assoc_id;
 		sctp_inet_msgname(msgname, addr_len);
 		sin = (struct sockaddr_in *)msgname;
-		sinfrom = &event->event_asoc->peer.primary_addr.v4;
-		sin->sin_port = htons(event->event_asoc->peer.port);
+		sinfrom = &asoc->peer.primary_addr.v4;
+		sin->sin_port = htons(asoc->peer.port);
 		sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr;
 	}
 }
@@ -678,7 +744,7 @@ static void sctp_inet_skb_msgname(struct
 }
 
 /* Do we support this AF? */
-static int sctp_inet_af_supported(sa_family_t family)
+static int sctp_inet_af_supported(sa_family_t family, struct sctp_opt *sp)
 {
 	/* PF_INET only supports AF_INET addresses. */
 	return (AF_INET == family);
@@ -706,7 +772,7 @@ static int sctp_inet_cmp_addr(const unio
  */
 static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
 {
-	return sctp_v4_available(addr);
+	return sctp_v4_available(addr, opt);
 }
 
 /* Verify that sockaddr looks sendable.  Common verification has already
@@ -752,6 +818,7 @@ static struct sctp_pf sctp_pf_inet = {
 	.send_verify   = sctp_inet_send_verify,
 	.supported_addrs = sctp_inet_supported_addrs,
 	.create_accept_sk = sctp_v4_create_accept_sk,
+	.addr_v4map	= sctp_v4_addr_v4map,
 	.af            = &sctp_ipv4_specific,
 };
 
@@ -821,6 +888,8 @@ struct sctp_af sctp_ipv4_specific = {
 	.from_sk        = sctp_v4_from_sk,
 	.to_sk_saddr    = sctp_v4_to_sk_saddr,
 	.to_sk_daddr    = sctp_v4_to_sk_daddr,
+	.from_addr_param= sctp_v4_from_addr_param,
+	.to_addr_param  = sctp_v4_to_addr_param,	
 	.dst_saddr      = sctp_v4_dst_saddr,
 	.cmp_addr       = sctp_v4_cmp_addr,
 	.addr_valid     = sctp_v4_addr_valid,
@@ -829,6 +898,8 @@ struct sctp_af sctp_ipv4_specific = {
 	.available      = sctp_v4_available,
 	.scope          = sctp_v4_scope,
 	.skb_iif        = sctp_v4_skb_iif,
+	.is_ce          = sctp_v4_is_ce,
+	.seq_dump_addr  = sctp_v4_seq_dump_addr,
 	.net_header_len = sizeof(struct iphdr),
 	.sockaddr_len   = sizeof(struct sockaddr_in),
 	.sa_family      = AF_INET,
@@ -873,6 +944,7 @@ static int __init init_sctp_mibs(void)
 
 static void cleanup_sctp_mibs(void)
 {
+	return;
 }
 
 /* Initialize the universe into something sensible.  */
@@ -880,6 +952,8 @@ __init int sctp_init(void)
 {
 	int i;
 	int status = 0;
+	unsigned long goal;
+	int order;
 
 	/* SCTP_DEBUG sanity check. */
 	if (!sctp_sanity_check())
@@ -892,6 +966,14 @@ __init int sctp_init(void)
 	inet_register_protosw(&sctp_seqpacket_protosw);
 	inet_register_protosw(&sctp_stream_protosw);
 
+	/* Allocate cache pools. */
+	sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
+					       sizeof(struct sctp_chunk),
+					       0, SLAB_HWCACHE_ALIGN,
+					       NULL, NULL);
+	if (!sctp_chunk_cachep)
+		goto err_chunk_cachep;
+
 	/* Allocate and initialise sctp mibs.  */
 	status = init_sctp_mibs();
 	if (status)
@@ -910,91 +992,116 @@ __init int sctp_init(void)
 	 */
 	/* The following protocol parameters are RECOMMENDED:  */
 	/* RTO.Initial              - 3  seconds */
-	sctp_proto.rto_initial		= SCTP_RTO_INITIAL;
+	sctp_rto_initial		= SCTP_RTO_INITIAL;
 	/* RTO.Min                  - 1  second */
-	sctp_proto.rto_min	 	= SCTP_RTO_MIN;
+	sctp_rto_min	 		= SCTP_RTO_MIN;
 	/* RTO.Max                 -  60 seconds */
-	sctp_proto.rto_max 		= SCTP_RTO_MAX;
+	sctp_rto_max 			= SCTP_RTO_MAX;
 	/* RTO.Alpha                - 1/8 */
-	sctp_proto.rto_alpha	        = SCTP_RTO_ALPHA;
+	sctp_rto_alpha	        	= SCTP_RTO_ALPHA;
 	/* RTO.Beta                 - 1/4 */
-	sctp_proto.rto_beta		= SCTP_RTO_BETA;
-
+	sctp_rto_beta			= SCTP_RTO_BETA;
 	/* Valid.Cookie.Life        - 60  seconds */
-	sctp_proto.valid_cookie_life	= 60 * HZ;
+	sctp_valid_cookie_life		= 60 * HZ;
 
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
-	sctp_proto.cookie_preserve_enable = 1;
+	sctp_cookie_preserve_enable 	= 1;
 
 	/* Max.Burst		    - 4 */
-	sctp_proto.max_burst = SCTP_MAX_BURST;
+	sctp_max_burst 			= SCTP_MAX_BURST;
 
 	/* Association.Max.Retrans  - 10 attempts
 	 * Path.Max.Retrans         - 5  attempts (per destination address)
 	 * Max.Init.Retransmits     - 8  attempts
 	 */
-	sctp_proto.max_retrans_association = 10;
-	sctp_proto.max_retrans_path	= 5;
-	sctp_proto.max_retrans_init	= 8;
+	sctp_max_retrans_association 	= 10;
+	sctp_max_retrans_path		= 5;
+	sctp_max_retrans_init		= 8;
 
 	/* HB.interval              - 30 seconds */
-	sctp_proto.hb_interval		= 30 * HZ;
+	sctp_hb_interval		= 30 * HZ;
 
 	/* Implementation specific variables. */
 
 	/* Initialize default stream count setup information. */
-	sctp_proto.max_instreams    = SCTP_DEFAULT_INSTREAMS;
-	sctp_proto.max_outstreams   = SCTP_DEFAULT_OUTSTREAMS;
+	sctp_max_instreams    		= SCTP_DEFAULT_INSTREAMS;
+	sctp_max_outstreams   		= SCTP_DEFAULT_OUTSTREAMS;
 
-	/* Allocate and initialize the association hash table.  */
-	sctp_proto.assoc_hashsize = 4096;
-	sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *)
-		kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
-	if (!sctp_proto.assoc_hashbucket) {
+	/* Size and allocate the association hash table.
+	 * The methodology is similar to that of the tcp hash tables.
+	 */
+	if (num_physpages >= (128 * 1024))
+		goal = num_physpages >> (22 - PAGE_SHIFT);
+	else
+		goal = num_physpages >> (24 - PAGE_SHIFT);
+
+	for (order = 0; (1UL << order) < goal; order++)
+		;
+
+	do {
+		sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE /
+					sizeof(struct sctp_hashbucket);
+		if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0)
+			continue;
+		sctp_assoc_hashtable = (struct sctp_hashbucket *)
+					__get_free_pages(GFP_ATOMIC, order);
+	} while (!sctp_assoc_hashtable && --order > 0);
+	if (!sctp_assoc_hashtable) {
 		printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
 		status = -ENOMEM;
 		goto err_ahash_alloc;
 	}
-	for (i = 0; i < sctp_proto.assoc_hashsize; i++) {
-		sctp_proto.assoc_hashbucket[i].lock = RW_LOCK_UNLOCKED;
-		sctp_proto.assoc_hashbucket[i].chain = NULL;
+	for (i = 0; i < sctp_assoc_hashsize; i++) {
+		sctp_assoc_hashtable[i].lock = RW_LOCK_UNLOCKED;
+		sctp_assoc_hashtable[i].chain = NULL;
 	}
 
 	/* Allocate and initialize the endpoint hash table.  */
-	sctp_proto.ep_hashsize = 64;
-	sctp_proto.ep_hashbucket = (sctp_hashbucket_t *)
-		kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
-	if (!sctp_proto.ep_hashbucket) {
+	sctp_ep_hashsize = 64;
+	sctp_ep_hashtable = (struct sctp_hashbucket *)
+		kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
+	if (!sctp_ep_hashtable) {
 		printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
 		status = -ENOMEM;
 		goto err_ehash_alloc;
 	}
-
-	for (i = 0; i < sctp_proto.ep_hashsize; i++) {
-		sctp_proto.ep_hashbucket[i].lock = RW_LOCK_UNLOCKED;
-		sctp_proto.ep_hashbucket[i].chain = NULL;
+	for (i = 0; i < sctp_ep_hashsize; i++) {
+		sctp_ep_hashtable[i].lock = RW_LOCK_UNLOCKED;
+		sctp_ep_hashtable[i].chain = NULL;
 	}
 
 	/* Allocate and initialize the SCTP port hash table.  */
-	sctp_proto.port_hashsize = 4096;
-	sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *)
-		kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL);
-	if (!sctp_proto.port_hashtable) {
+	do {
+		sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
+					sizeof(struct sctp_bind_hashbucket);
+		if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
+			continue;
+		sctp_port_hashtable = (struct sctp_bind_hashbucket *)
+					__get_free_pages(GFP_ATOMIC, order);
+	} while (!sctp_port_hashtable && --order > 0);
+	if (!sctp_port_hashtable) {
 		printk(KERN_ERR "SCTP: Failed bind hash alloc.");
 		status = -ENOMEM;
 		goto err_bhash_alloc;
 	}
-
-	sctp_proto.port_alloc_lock = SPIN_LOCK_UNLOCKED;
-	sctp_proto.port_rover = sysctl_local_port_range[0] - 1;
-	for (i = 0; i < sctp_proto.port_hashsize; i++) {
-		sctp_proto.port_hashtable[i].lock = SPIN_LOCK_UNLOCKED;
-		sctp_proto.port_hashtable[i].chain = NULL;
+	for (i = 0; i < sctp_port_hashsize; i++) {
+		sctp_port_hashtable[i].lock = SPIN_LOCK_UNLOCKED;
+		sctp_port_hashtable[i].chain = NULL;
 	}
 
+	sctp_port_alloc_lock = SPIN_LOCK_UNLOCKED;
+	sctp_port_rover = sysctl_local_port_range[0] - 1;
+
+	printk(KERN_INFO "SCTP: Hash tables configured "
+			 "(established %d bind %d)\n",
+		sctp_assoc_hashsize, sctp_port_hashsize);
+
+	/* Disable ADDIP by default. */
+	sctp_addip_enable = 0;
+
 	sctp_sysctl_register();
 
-	INIT_LIST_HEAD(&sctp_proto.address_families);
+	INIT_LIST_HEAD(&sctp_address_families);
 	sctp_register_af(&sctp_ipv4_specific);
 
 	status = sctp_v6_init();
@@ -1009,13 +1116,13 @@ __init int sctp_init(void)
 	}
 
 	/* Initialize the local address list. */
-	INIT_LIST_HEAD(&sctp_proto.local_addr_list);
-	sctp_proto.local_addr_lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&sctp_local_addr_list);
+	sctp_local_addr_lock = SPIN_LOCK_UNLOCKED;
 
 	/* Register notifier for inet address additions/deletions. */
 	register_inetaddr_notifier(&sctp_inetaddr_notifier);
 
-	sctp_get_local_addr_list(&sctp_proto);
+	sctp_get_local_addr_list();
 
 	__unsafe(THIS_MODULE);
 	return 0;
@@ -1025,16 +1132,22 @@ err_ctl_sock_init:
 err_v6_init:
 	sctp_sysctl_unregister();
 	list_del(&sctp_ipv4_specific.list);
-	kfree(sctp_proto.port_hashtable);
+	free_pages((unsigned long)sctp_port_hashtable,
+		   get_order(sctp_port_hashsize *
+			     sizeof(struct sctp_bind_hashbucket)));
 err_bhash_alloc:
-	kfree(sctp_proto.ep_hashbucket);
+	kfree(sctp_ep_hashtable);
 err_ehash_alloc:
-	kfree(sctp_proto.assoc_hashbucket);
+	free_pages((unsigned long)sctp_assoc_hashtable,
+		   get_order(sctp_assoc_hashsize *
+			     sizeof(struct sctp_hashbucket)));
 err_ahash_alloc:
 	sctp_dbg_objcnt_exit();
 	sctp_proc_exit();
 	cleanup_sctp_mibs();
 err_init_mibs:
+	kmem_cache_destroy(sctp_chunk_cachep);
+err_chunk_cachep:
 	inet_del_protocol(&sctp_protocol);
 	inet_unregister_protosw(&sctp_seqpacket_protosw);
 	inet_unregister_protosw(&sctp_stream_protosw);
@@ -1052,7 +1165,7 @@ __exit void sctp_exit(void)
 	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
 
 	/* Free the local address list.  */
-	sctp_free_local_addr_list(&sctp_proto);
+	sctp_free_local_addr_list();
 
 	/* Free the control endpoint.  */
 	sock_release(sctp_ctl_socket);
@@ -1061,9 +1174,15 @@ __exit void sctp_exit(void)
 	sctp_sysctl_unregister();
 	list_del(&sctp_ipv4_specific.list);
 
-	kfree(sctp_proto.assoc_hashbucket);
-	kfree(sctp_proto.ep_hashbucket);
-	kfree(sctp_proto.port_hashtable);
+	free_pages((unsigned long)sctp_assoc_hashtable,
+		   get_order(sctp_assoc_hashsize *
+			     sizeof(struct sctp_hashbucket)));
+	kfree(sctp_ep_hashtable);
+	free_pages((unsigned long)sctp_port_hashtable,
+		   get_order(sctp_port_hashsize *
+			     sizeof(struct sctp_bind_hashbucket)));
+
+	kmem_cache_destroy(sctp_chunk_cachep);
 
 	sctp_dbg_objcnt_exit();
 	sctp_proc_exit();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_make_chunk.c linux-2.4.26-pre6/net/sctp/sm_make_chunk.c
--- linux-2.4.25/net/sctp/sm_make_chunk.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/sm_make_chunk.c	2004-03-25 00:17:08.000000000 +0000
@@ -1,8 +1,8 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2002 Intel Corp.
- * Copyright (c) 2001-2002 International Business Machines Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -48,6 +48,7 @@
  *    Sridhar Samudrala	    <sri@us.ibm.com>
  *    Daisy Chang	    <daisyc@us.ibm.com>
  *    Ardelle Fan	    <ardelle.fan@intel.com>
+ *    Kevin Gao             <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -60,6 +61,7 @@
 #include <linux/net.h>
 #include <linux/inet.h>
 #include <asm/scatterlist.h>
+#include <linux/crypto.h>
 #include <net/sock.h>
 
 #include <linux/skbuff.h>
@@ -67,6 +69,8 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
+extern kmem_cache_t *sctp_chunk_cachep;
+
 /* What was the inbound interface for this chunk? */
 int sctp_chunk_iif(const struct sctp_chunk *chunk)
 {
@@ -96,7 +100,7 @@ static const sctp_ecn_capable_param_t ec
  * provided chunk, as most cause codes will be embedded inside an
  * abort chunk.
  */
-void  sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
+void  sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code,
 		      const void *payload, size_t paylen)
 {
 	sctp_errhdr_t err;
@@ -157,14 +161,14 @@ void  sctp_init_cause(sctp_chunk_t *chun
  * Host Name Address (Note 3)          Optional    11
  * Supported Address Types (Note 4)    Optional    12
  */
-sctp_chunk_t *sctp_make_init(const struct sctp_association *asoc,
-			     const sctp_bind_addr_t *bp,
+struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
+			     const struct sctp_bind_addr *bp,
 			     int gfp, int vparam_len)
 {
 	sctp_inithdr_t init;
 	union sctp_params addrs;
 	size_t chunksize;
-	sctp_chunk_t *retval = NULL;
+	struct sctp_chunk *retval = NULL;
 	int num_types, addrs_len = 0;
 	struct sctp_opt *sp;
 	sctp_supported_addrs_param_t sat;
@@ -234,12 +238,12 @@ nodata:
 	return retval;
 }
 
-sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc,
-				 const sctp_chunk_t *chunk,
+struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
+				 const struct sctp_chunk *chunk,
 				 int gfp, int unkparam_len)
 {
 	sctp_inithdr_t initack;
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	union sctp_params addrs;
 	int addrs_len;
 	sctp_cookie_param_t *cookie;
@@ -347,10 +351,10 @@ nomem_cookie:
  *   An implementation SHOULD make the cookie as small as possible
  *   to insure interoperability.
  */
-sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *asoc,
-				    const sctp_chunk_t *chunk)
+struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *asoc,
+				    const struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	void *cookie;
 	int cookie_len;
 
@@ -398,10 +402,10 @@ nodata:
  *
  *   Set to zero on transmit and ignored on receipt.
  */
-sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *asoc,
-				   const sctp_chunk_t *chunk)
+struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,
+				   const struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 
 	retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ACK, 0, 0);
 
@@ -443,11 +447,11 @@ sctp_chunk_t *sctp_make_cookie_ack(const
  *
  *     Note: The CWR is considered a Control chunk.
  */
-sctp_chunk_t *sctp_make_cwr(const struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,
 			    const __u32 lowest_tsn,
-			    const sctp_chunk_t *chunk)
+			    const struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	sctp_cwrhdr_t cwr;
 
 	cwr.lowest_tsn = htonl(lowest_tsn);
@@ -478,10 +482,10 @@ nodata:
 }
 
 /* Make an ECNE chunk.  This is a congestion experienced report.  */
-sctp_chunk_t *sctp_make_ecne(const struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc,
 			     const __u32 lowest_tsn)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	sctp_ecnehdr_t ecne;
 
 	ecne.lowest_tsn = htonl(lowest_tsn);
@@ -499,25 +503,27 @@ nodata:
 /* Make a DATA chunk for the given association from the provided
  * parameters.  However, do not populate the data payload.
  */
-sctp_chunk_t *sctp_make_datafrag_empty(struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
 				       const struct sctp_sndrcvinfo *sinfo,
 				       int data_len, __u8 flags, __u16 ssn)
 {
-	sctp_chunk_t *retval;
-	sctp_datahdr_t dp;
+	struct sctp_chunk *retval;
+	struct sctp_datahdr dp;
 	int chunk_len;
 
 	/* We assign the TSN as LATE as possible, not here when
 	 * creating the chunk.
 	 */
-	dp.tsn= 1000000;       /* This marker is a debugging aid. */
+	dp.tsn = 0;
 	dp.stream = htons(sinfo->sinfo_stream);
 	dp.ppid   = htonl(sinfo->sinfo_ppid);
-	dp.ssn    = htons(ssn);
 
 	/* Set the flags for an unordered send.  */
-	if (sinfo->sinfo_flags & MSG_UNORDERED)
+	if (sinfo->sinfo_flags & MSG_UNORDERED) {
 		flags |= SCTP_DATA_UNORDERED;
+		dp.ssn = 0;
+	} else
+		dp.ssn = htons(ssn);
 
 	chunk_len = sizeof(dp) + data_len;
 	retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len);
@@ -534,12 +540,12 @@ nodata:
 /* Make a DATA chunk for the given association.  Populate the data
  * payload.
  */
-sctp_chunk_t *sctp_make_datafrag(struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_datafrag(struct sctp_association *asoc,
 				 const struct sctp_sndrcvinfo *sinfo,
 				 int data_len, const __u8 *data,
 				 __u8 flags, __u16 ssn)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 
 	retval = sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, ssn);
 	if (retval)
@@ -551,11 +557,11 @@ sctp_chunk_t *sctp_make_datafrag(struct 
 /* Make a DATA chunk for the given association to ride on stream id
  * 'stream', with a payload id of 'payload', and a body of 'data'.
  */
-sctp_chunk_t *sctp_make_data(struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_data(struct sctp_association *asoc,
 			     const struct sctp_sndrcvinfo *sinfo,
 			     int data_len, const __u8 *data)
 {
-	sctp_chunk_t *retval = NULL;
+	struct sctp_chunk *retval = NULL;
 
 	retval = sctp_make_data_empty(asoc, sinfo, data_len);
 	if (retval)
@@ -568,7 +574,7 @@ sctp_chunk_t *sctp_make_data(struct sctp
  * hold 'data_len' octets of data.  We use this version when we need
  * to build the message AFTER allocating memory.
  */
-sctp_chunk_t *sctp_make_data_empty(struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_data_empty(struct sctp_association *asoc,
 				   const struct sctp_sndrcvinfo *sinfo,
 				   int data_len)
 {
@@ -581,30 +587,20 @@ sctp_chunk_t *sctp_make_data_empty(struc
  * association.  This reports on which TSN's we've seen to date,
  * including duplicates and gaps.
  */
-sctp_chunk_t *sctp_make_sack(const struct sctp_association *asoc)
+struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
 {
-	sctp_chunk_t *retval;
-	sctp_sackhdr_t sack;
-	sctp_gap_ack_block_t gab;
-	int length;
+	struct sctp_chunk *retval;
+	struct sctp_sackhdr sack;
+	int len;
 	__u32 ctsn;
-	struct sctp_tsnmap_iter iter;
 	__u16 num_gabs, num_dup_tsns;
 	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
 
 	ctsn = sctp_tsnmap_get_ctsn(map);
-	SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn);
-
-	/* Count the number of Gap Ack Blocks.  */
-	num_gabs = 0;
-
-	if (sctp_tsnmap_has_gap(map)) {
-		sctp_tsnmap_iter_init(map, &iter);
-		while (sctp_tsnmap_next_gap_ack(map, &iter,
-						&gab.start, &gab.end))
-			num_gabs++;
-	}
+	SCTP_DEBUG_PRINTK("sackCTSNAck sent:  0x%x.\n", ctsn);
 
+	/* How much room is needed in the chunk? */
+	num_gabs = sctp_tsnmap_num_gabs(map);
 	num_dup_tsns = sctp_tsnmap_num_dups(map);
 
 	/* Initialize the SACK header.  */
@@ -613,12 +609,12 @@ sctp_chunk_t *sctp_make_sack(const struc
 	sack.num_gap_ack_blocks     = htons(num_gabs);
 	sack.num_dup_tsns           = htons(num_dup_tsns);
 
-	length = sizeof(sack)
-		+ sizeof(sctp_gap_ack_block_t) * num_gabs
+	len = sizeof(sack)
+		+ sizeof(struct sctp_gap_ack_block) * num_gabs
 		+ sizeof(__u32) * num_dup_tsns;
 
 	/* Create the chunk.  */
-	retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, length);
+	retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len);
 	if (!retval)
 		goto nodata;
 
@@ -657,30 +653,25 @@ sctp_chunk_t *sctp_make_sack(const struc
 	retval->subh.sack_hdr =
 		sctp_addto_chunk(retval, sizeof(sack), &sack);
 
-	/* Put the Gap Ack Blocks into the chunk.  */
-	if (num_gabs) {
-		sctp_tsnmap_iter_init(map, &iter);
-		while(sctp_tsnmap_next_gap_ack(map, &iter,
-					       &gab.start, &gab.end)) {
-			gab.start = htons(gab.start);
-			gab.end = htons(gab.end);
-			sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t),
-					 &gab);
-		}
-	}
-
-	/* Register the duplicates.  */
-	sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
-			 sctp_tsnmap_get_dups(map));
+	/* Add the gap ack block information.   */
+	if (num_gabs)
+		sctp_addto_chunk(retval, sizeof(__u32) * num_gabs,
+				 sctp_tsnmap_get_gabs(map));
+
+	/* Add the duplicate TSN information.  */
+	if (num_dup_tsns)
+		sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
+				 sctp_tsnmap_get_dups(map));
 
 nodata:
 	return retval;
 }
 
 /* Make a SHUTDOWN chunk. */
-sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc)
+struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
+				      const struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	sctp_shutdownhdr_t shut;
 	__u32 ctsn;
 
@@ -694,14 +685,17 @@ sctp_chunk_t *sctp_make_shutdown(const s
 
 	retval->subh.shutdown_hdr =
 		sctp_addto_chunk(retval, sizeof(shut), &shut);
+
+	if (chunk)
+		retval->transport = chunk->transport;
 nodata:
 	return retval;
 }
 
-sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc,
-				     const sctp_chunk_t *chunk)
+struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
+				     const struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 
 	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0);
 
@@ -720,10 +714,11 @@ sctp_chunk_t *sctp_make_shutdown_ack(con
 	return retval;
 }
 
-sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *asoc,
-					  const sctp_chunk_t *chunk)
+struct sctp_chunk *sctp_make_shutdown_complete(
+	const struct sctp_association *asoc,
+	const struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	__u8 flags = 0;
 
 	/* Maybe set the T-bit if we have no association. */
@@ -750,11 +745,11 @@ sctp_chunk_t *sctp_make_shutdown_complet
 /* Create an ABORT.  Note that we set the T bit if we have no
  * association.
  */
-sctp_chunk_t *sctp_make_abort(const struct sctp_association *asoc,
-			      const sctp_chunk_t *chunk,
+struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc,
+			      const struct sctp_chunk *chunk,
 			      const size_t hint)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	__u8 flags = 0;
 
 	/* Maybe set the T-bit if we have no association.  */
@@ -778,10 +773,11 @@ sctp_chunk_t *sctp_make_abort(const stru
 }
 
 /* Helper to create ABORT with a NO_USER_DATA error.  */
-sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *asoc,
-				      const sctp_chunk_t *chunk, __u32 tsn)
+struct sctp_chunk *sctp_make_abort_no_data(
+	const struct sctp_association *asoc,
+	const struct sctp_chunk *chunk, __u32 tsn)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	__u32 payload;
 
 	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t)
@@ -812,17 +808,22 @@ no_mem:
 }
 
 /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error.  */
-sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *asoc,
-				   const sctp_chunk_t *chunk,
+struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
+				   const struct sctp_chunk *chunk,
 				   const struct msghdr *msg)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	void *payload = NULL, *payoff;
-	size_t paylen;
-	struct iovec *iov = msg->msg_iov;
-	int iovlen = msg->msg_iovlen;
+	size_t paylen = 0;
+	struct iovec *iov = NULL;
+	int iovlen = 0;
+
+	if (msg) {
+		iov = msg->msg_iov;
+		iovlen = msg->msg_iovlen;
+		paylen = get_user_iov_size(iov, iovlen);
+	}
 
-	paylen = get_user_iov_size(iov, iovlen);
 	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);
 	if (!retval)
 		goto err_chunk;
@@ -852,19 +853,19 @@ sctp_chunk_t *sctp_make_abort_user(const
 err_copy:
 	kfree(payload);
 err_payload:
-	sctp_free_chunk(retval);
+	sctp_chunk_free(retval);
 	retval = NULL;
 err_chunk:
 	return retval;
 }
 
 /* Make a HEARTBEAT chunk.  */
-sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
 				  const struct sctp_transport *transport,
 				  const void *payload, const size_t paylen)
 {
-	sctp_chunk_t *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT,
-					       0, paylen);
+	struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT,
+						    0, paylen);
 
 	if (!retval)
 		goto nodata;
@@ -879,15 +880,16 @@ nodata:
 	return retval;
 }
 
-sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *asoc,
-				      const sctp_chunk_t *chunk,
+struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *asoc,
+				      const struct sctp_chunk *chunk,
 				      const void *payload, const size_t paylen)
 {
-	sctp_chunk_t *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK,
-					       0, paylen);
+	struct sctp_chunk *retval;
 
+	retval  = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK, 0, paylen);
 	if (!retval)
 		goto nodata;
+
 	retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload);
 
 	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
@@ -909,11 +911,12 @@ nodata:
 /* Create an Operation Error chunk with the specified space reserved.
  * This routine can be used for containing multiple causes in the chunk.
  */
-sctp_chunk_t *sctp_make_op_error_space(const struct sctp_association *asoc,
-				       const sctp_chunk_t *chunk,
-				       size_t size)
+struct sctp_chunk *sctp_make_op_error_space(
+	const struct sctp_association *asoc,
+	const struct sctp_chunk *chunk,
+	size_t size)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 
 	retval = sctp_make_chunk(asoc, SCTP_CID_ERROR, 0,
 				 sizeof(sctp_errhdr_t) + size);
@@ -936,13 +939,14 @@ nodata:
 }
 
 /* Create an Operation Error chunk.  */
-sctp_chunk_t *sctp_make_op_error(const struct sctp_association *asoc,
-				 const sctp_chunk_t *chunk,
+struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
+				 const struct sctp_chunk *chunk,
 				 __u16 cause_code, const void *payload,
 				 size_t paylen)
 {
-	sctp_chunk_t *retval = sctp_make_op_error_space(asoc, chunk, paylen);
+	struct sctp_chunk *retval;
 
+	retval = sctp_make_op_error_space(asoc, chunk, paylen);
 	if (!retval)
 		goto nodata;
 
@@ -959,15 +963,17 @@ nodata:
 /* Turn an skb into a chunk.
  * FIXME: Eventually move the structure directly inside the skb->cb[].
  */
-sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, 
+struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
 			    const struct sctp_association *asoc,
 			    struct sock *sk)
 {
-	sctp_chunk_t *retval = t_new(sctp_chunk_t, GFP_ATOMIC);
+	struct sctp_chunk *retval;
+
+	retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC);
 
 	if (!retval)
 		goto nodata;
-	memset(retval, 0, sizeof(sctp_chunk_t));
+	memset(retval, 0, sizeof(struct sctp_chunk));
 
 	if (!sk) {
 		SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb);
@@ -975,11 +981,11 @@ sctp_chunk_t *sctp_chunkify(struct sk_bu
 
 	retval->skb		= skb;
 	retval->asoc		= (struct sctp_association *)asoc;
-	retval->num_times_sent	= 0;
+	retval->resent  	= 0;
 	retval->has_tsn		= 0;
 	retval->has_ssn         = 0;
 	retval->rtt_in_progress	= 0;
-	retval->sent_at	= jiffies;
+	retval->sent_at		= 0;
 	retval->singleton	= 1;
 	retval->end_of_packet	= 0;
 	retval->ecn_ce_done	= 0;
@@ -995,17 +1001,24 @@ sctp_chunk_t *sctp_chunkify(struct sk_bu
 	retval->tsn_gap_acked = 0;
 	retval->fast_retransmit = 0;
 
+	/* If this is a fragmented message, track all fragments
+	 * of the message (for SEND_FAILED).
+	 */
+	retval->msg = NULL;
+
 	/* Polish the bead hole.  */
 	INIT_LIST_HEAD(&retval->transmitted_list);
 	INIT_LIST_HEAD(&retval->frag_list);
 	SCTP_DBG_OBJCNT_INC(chunk);
+	atomic_set(&retval->refcnt, 1);
+
 
 nodata:
 	return retval;
 }
 
 /* Set chunk->source and dest based on the IP header in chunk->skb.  */
-void sctp_init_addrs(sctp_chunk_t *chunk, union sctp_addr *src,
+void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src,
 		     union sctp_addr *dest)
 {
 	memcpy(&chunk->source, src, sizeof(union sctp_addr));
@@ -1013,7 +1026,7 @@ void sctp_init_addrs(sctp_chunk_t *chunk
 }
 
 /* Extract the source address from a chunk.  */
-const union sctp_addr *sctp_source(const sctp_chunk_t *chunk)
+const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
 {
 	/* If we have a known transport, use that.  */
 	if (chunk->transport) {
@@ -1027,10 +1040,10 @@ const union sctp_addr *sctp_source(const
 /* Create a new chunk, setting the type and flags headers from the
  * arguments, reserving enough space for a 'paylen' byte payload.
  */
-sctp_chunk_t *sctp_make_chunk(const struct sctp_association *asoc,
-			      __u8 type, __u8 flags, int paylen)
+struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
+				   __u8 type, __u8 flags, int paylen)
 {
-	sctp_chunk_t *retval;
+	struct sctp_chunk *retval;
 	sctp_chunkhdr_t *chunk_hdr;
 	struct sk_buff *skb;
 	struct sock *sk;
@@ -1055,36 +1068,58 @@ sctp_chunk_t *sctp_make_chunk(const stru
 	}
 
 	retval->chunk_hdr = chunk_hdr;
-	retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(sctp_chunkhdr_t);
+	retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);
 
 	/* Set the skb to the belonging sock for accounting.  */
 	skb->sk = sk;
 
 	return retval;
-
 nodata:
 	return NULL;
 }
 
+
 /* Release the memory occupied by a chunk.  */
-void sctp_free_chunk(sctp_chunk_t *chunk)
+static void sctp_chunk_destroy(struct sctp_chunk *chunk)
 {
-	/* Make sure that we are not on any list.  */
-	skb_unlink((struct sk_buff *) chunk);
-	list_del(&chunk->transmitted_list);
-
 	/* Free the chunk skb data and the SCTP_chunk stub itself. */
 	dev_kfree_skb(chunk->skb);
 
-	kfree(chunk);
 	SCTP_DBG_OBJCNT_DEC(chunk);
+	kmem_cache_free(sctp_chunk_cachep, chunk);
+}
+
+/* Possibly, free the chunk.  */
+void sctp_chunk_free(struct sctp_chunk *chunk)
+{
+	/* Make sure that we are not on any list.  */
+	skb_unlink((struct sk_buff *) chunk);
+	list_del_init(&chunk->transmitted_list);
+
+	/* Release our reference on the message tracker. */
+	if (chunk->msg)
+		sctp_datamsg_put(chunk->msg);
+
+	sctp_chunk_put(chunk);
+}
+
+/* Grab a reference to the chunk. */
+void sctp_chunk_hold(struct sctp_chunk *ch)
+{
+	atomic_inc(&ch->refcnt);
 }
 
+/* Release a reference to the chunk. */
+void sctp_chunk_put(struct sctp_chunk *ch)
+{
+	if (atomic_dec_and_test(&ch->refcnt))
+		sctp_chunk_destroy(ch);
+}
 
 /* Append bytes to the end of a chunk.  Will panic if chunk is not big
  * enough.
  */
-void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data)
+void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
 {
 	void *target;
 	void *padding;
@@ -1108,8 +1143,8 @@ void *sctp_addto_chunk(sctp_chunk_t *chu
  * chunk is not big enough.
  * Returns a kernel err value.
  */
-static int sctp_user_addto_chunk(sctp_chunk_t *chunk, int off, int len,
-				 struct iovec *data)
+int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
+			  struct iovec *data)
 {
 	__u8 *target;
 	int err = 0;
@@ -1130,132 +1165,10 @@ out:
 	return err;
 }
 
-/* A data chunk can have a maximum payload of (2^16 - 20).  Break
- * down any such message into smaller chunks.  Opportunistically, fragment
- * the chunks down to the current MTU constraints.  We may get refragmented
- * later if the PMTU changes, but it is _much better_ to fragment immediately
- * with a reasonable guess than always doing our fragmentation on the
- * soft-interrupt.
- */
-
-
-int sctp_datachunks_from_user(struct sctp_association *asoc,
-			      const struct sctp_sndrcvinfo *sinfo,
-			      struct msghdr *msg, int msg_len,
-			      struct sk_buff_head *chunks)
-{
-	int max, whole, i, offset, over, err;
-	int len, first_len;
-	sctp_chunk_t *chunk;
-	__u8 frag;
-
-	/* What is a reasonable fragmentation point right now? */
-	max = asoc->pmtu;
-	if (max < SCTP_MIN_PMTU)
-		max = SCTP_MIN_PMTU;
-	max -= SCTP_IP_OVERHEAD;
-
-	/* Make sure not beyond maximum chunk size. */
-	if (max > SCTP_MAX_CHUNK_LEN)
-		max = SCTP_MAX_CHUNK_LEN;
-
-	/* Subtract out the overhead of a data chunk header. */
-	max -= sizeof(struct sctp_data_chunk);
-
-	whole = 0;
-	first_len = max;
-
-	/* Encourage Cookie-ECHO bundling. */
-	if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
-		whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);
-
-		/* Account for the DATA to be bundled with the COOKIE-ECHO. */
-		if (whole) {
-			first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
-			msg_len -= first_len;
-			whole = 1;
-		}
-	}
-
-	/* How many full sized?  How many bytes leftover? */
-	whole += msg_len / max;
-	over = msg_len % max;
-	offset = 0;
-
-	if (whole && over)
-		SCTP_INC_STATS_USER(SctpFragUsrMsgs);
-
-	/* Create chunks for all the full sized DATA chunks. */
-	for (i=0, len=first_len; i < whole; i++) {
-		frag = SCTP_DATA_MIDDLE_FRAG;
-
-		if (0 == i)
-			frag |= SCTP_DATA_FIRST_FRAG;
-
-		if ((i == (whole - 1)) && !over)
-			frag |= SCTP_DATA_LAST_FRAG;
-
-		chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
-
-		if (!chunk)
-			goto nomem;
-		err = sctp_user_addto_chunk(chunk, offset, len, msg->msg_iov);
-		if (err < 0)
-			goto errout;
-
-		offset += len;
-
-		/* Put the chunk->skb back into the form expected by send.  */
-		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
-			   - (__u8 *)chunk->skb->data);
-
-		__skb_queue_tail(chunks, (struct sk_buff *)chunk);
-
-		/* The first chunk, the first chunk was likely short
-		 * to allow bundling, so reset to full size.
-		 */
-		if (0 == i)
-			len = max;
-	}
-
-	/* .. now the leftover bytes. */
-	if (over) {
-		if (!whole)
-			frag = SCTP_DATA_NOT_FRAG;
-		else
-			frag = SCTP_DATA_LAST_FRAG;
-
-		chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
-
-		if (!chunk)
-			goto nomem;
-
-		err = sctp_user_addto_chunk(chunk, offset, over, msg->msg_iov);
-
-		/* Put the chunk->skb back into the form expected by send.  */
-		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
-			   - (__u8 *)chunk->skb->data);
-		if (err < 0)
-			goto errout;
-
-		__skb_queue_tail(chunks, (struct sk_buff *)chunk);
-	}
-	err = 0;
-	goto out;
-
-nomem:
-	err = -ENOMEM;
-errout:
-	while ((chunk = (sctp_chunk_t *)__skb_dequeue(chunks)))
-		sctp_free_chunk(chunk);
-out:
-	return err;
-}
-
 /* Helper function to assign a TSN if needed.  This assumes that both
  * the data_hdr and association have already been assigned.
  */
-void sctp_chunk_assign_ssn(sctp_chunk_t *chunk)
+void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
 {
 	__u16 ssn;
 	__u16 sid;
@@ -1282,7 +1195,7 @@ void sctp_chunk_assign_ssn(sctp_chunk_t 
 /* Helper function to assign a TSN if needed.  This assumes that both
  * the data_hdr and association have already been assigned.
  */
-void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
+void sctp_chunk_assign_tsn(struct sctp_chunk *chunk)
 {
 	if (!chunk->has_tsn) {
 		/* This is the last possible instant to
@@ -1301,6 +1214,7 @@ struct sctp_association *sctp_make_temp_
 	struct sctp_association *asoc;
 	struct sk_buff *skb;
 	sctp_scope_t scope;
+	struct sctp_af *af;
 
 	/* Create the bare association.  */
 	scope = sctp_scope(sctp_source(chunk));
@@ -1310,29 +1224,10 @@ struct sctp_association *sctp_make_temp_
 	asoc->temp = 1;
 	skb = chunk->skb;
 	/* Create an entry for the source address of the packet.  */
-	/* FIXME: Use the af specific helpers. */
-	switch (skb->nh.iph->version) {
-	case 4:
-		asoc->c.peer_addr.v4.sin_family     = AF_INET;
-		asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source);
-		asoc->c.peer_addr.v4.sin_addr.s_addr = skb->nh.iph->saddr;
-                break;
-
-	case 6:
-		asoc->c.peer_addr.v6.sin6_family     = AF_INET6;
-		asoc->c.peer_addr.v6.sin6_port
-			= ntohs(chunk->sctp_hdr->source);
-		asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */
-		asoc->c.peer_addr.v6.sin6_addr = skb->nh.ipv6h->saddr;
-		asoc->c.peer_addr.v6.sin6_scope_id =
-			((struct inet6_skb_parm *)skb->cb)->iif;
-		break;
-
-        default:
-		/* Yikes!  I never heard of this kind of address.  */
+	af = sctp_get_af_specific(ipver2af(skb->nh.iph->version));
+	if (unlikely(!af))
 		goto fail;
-	};
-
+	af->from_skb(&asoc->c.peer_addr, skb, 1);
 nodata:
 	return asoc;
 
@@ -1346,19 +1241,19 @@ fail:
  */
 sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
 				      const struct sctp_association *asoc,
-				      const sctp_chunk_t *init_chunk,
+				      const struct sctp_chunk *init_chunk,
 				      int *cookie_len,
 				      const __u8 *raw_addrs, int addrs_len)
 {
 	sctp_cookie_param_t *retval;
-	sctp_signed_cookie_t *cookie;
+	struct sctp_signed_cookie *cookie;
 	struct scatterlist sg;
 	int headersize, bodysize;
 	unsigned int keylen;
 	char *key;
 
 	headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
-	bodysize = sizeof(sctp_cookie_t)
+	bodysize = sizeof(struct sctp_cookie)
 		+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
 
 	/* Pad out the cookie to a multiple to make the signature
@@ -1380,7 +1275,7 @@ sctp_cookie_param_t *sctp_pack_cookie(co
 	 * out on the network.
 	 */
 	memset(retval, 0x00, *cookie_len);
-	cookie = (sctp_signed_cookie_t *) retval->body;
+	cookie = (struct sctp_signed_cookie *) retval->body;
 
 	/* Set up the parameter header.  */
 	retval->p.type = SCTP_PARAM_STATE_COOKIE;
@@ -1388,22 +1283,21 @@ sctp_cookie_param_t *sctp_pack_cookie(co
 
 	/* Copy the cookie part of the association itself.  */
 	cookie->c = asoc->c;
-
 	/* Save the raw address list length in the cookie. */
 	cookie->c.raw_addr_list_len = addrs_len;
 
 	/* Set an expiration time for the cookie.  */
 	do_gettimeofday(&cookie->c.expiration);
-	tv_add(&asoc->cookie_life, &cookie->c.expiration);
+	TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration);
 
 	/* Copy the peer's init packet.  */
 	memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr,
 	       ntohs(init_chunk->chunk_hdr->length));
 
 	/* Copy the raw local address list of the association. */
-	memcpy((__u8 *)&cookie->c.peer_init[0] + 
+	memcpy((__u8 *)&cookie->c.peer_init[0] +
 	       ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
-	
+
   	if (sctp_sk(ep->base.sk)->hmac) {
 		/* Sign the message.  */
 		sg.page = virt_to_page(&cookie->c);
@@ -1411,13 +1305,10 @@ sctp_cookie_param_t *sctp_pack_cookie(co
 		sg.length = bodysize;
 		keylen = SCTP_SECRET_SIZE;
 		key = (char *)ep->secret_key[ep->current_key];
-		
-		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, 
+
+		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,
 				 &sg, 1, cookie->signature);
-	} else
-		sctp_hash_digest(ep->secret_key[ep->current_key], 
-				 SCTP_SECRET_SIZE, (__u8 *) &cookie->c,
-				 bodysize, cookie->signature);
+	}
 
 nodata:
 	return retval;
@@ -1427,31 +1318,30 @@ nodata:
 struct sctp_association *sctp_unpack_cookie(
 	const struct sctp_endpoint *ep,
 	const struct sctp_association *asoc,
-	sctp_chunk_t *chunk, int gfp,
-	int *error, sctp_chunk_t **errp)
+	struct sctp_chunk *chunk, int gfp,
+	int *error, struct sctp_chunk **errp)
 {
 	struct sctp_association *retval = NULL;
-	sctp_signed_cookie_t *cookie;
-	sctp_cookie_t *bear_cookie;
+	struct sctp_signed_cookie *cookie;
+	struct sctp_cookie *bear_cookie;
 	int headersize, bodysize, fixed_size;
 	__u8 digest[SCTP_SIGNATURE_SIZE];
-	int secret;
 	struct scatterlist sg;
-	unsigned int keylen;
+	unsigned int keylen, len;
 	char *key;
 	sctp_scope_t scope;
 	struct sk_buff *skb = chunk->skb;
 
 	headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
 	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
-	fixed_size = headersize + sizeof(sctp_cookie_t);
+	fixed_size = headersize + sizeof(struct sctp_cookie);
 
 	/* Verify that the chunk looks like it even has a cookie.
 	 * There must be enough room for our cookie and our peer's
 	 * INIT chunk.
 	 */
-	if (ntohs(chunk->chunk_hdr->length) <
-	    (fixed_size + sizeof(sctp_chunkhdr_t)))
+	len = ntohs(chunk->chunk_hdr->length);
+	if (len < fixed_size + sizeof(struct sctp_chunkhdr))
 		goto malformed;
 
 	/* Verify that the cookie has been padded out. */
@@ -1462,28 +1352,8 @@ struct sctp_association *sctp_unpack_coo
 	cookie = chunk->subh.cookie_hdr;
 	bear_cookie = &cookie->c;
 
-	if (!sctp_sk(ep->base.sk)->hmac) {
-		secret = ep->current_key;
-		sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE,
-				 (__u8 *) bear_cookie, bodysize, digest);
-
-		if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
-			/* Try the previous key. */
-			secret = ep->last_key;
-			sctp_hash_digest(ep->secret_key[secret], 
-					 SCTP_SECRET_SIZE, (__u8 *) bear_cookie,
-					 bodysize, digest);
-
-			if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
-				/* Yikes!  Still bad signature! */
-				*error = -SCTP_IERROR_BAD_SIG;
-				goto fail;
-			}
-			
-		}
-
+	if (!sctp_sk(ep->base.sk)->hmac)
 		goto no_hmac;
-	}
 
 	/* Check the signature.  */
 	keylen = SCTP_SECRET_SIZE;
@@ -1493,16 +1363,16 @@ struct sctp_association *sctp_unpack_coo
 	key = (char *)ep->secret_key[ep->current_key];
 
 	memset(digest, 0x00, sizeof(digest));
-	sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 
+	sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg,
 			 1, digest);
 
 	if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
-		/* Try the previous key. */	
+		/* Try the previous key. */
 		key = (char *)ep->secret_key[ep->last_key];
 		memset(digest, 0x00, sizeof(digest));
-		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, 
+		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,
 				 &sg, 1, digest);
-		
+
 		if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
 			/* Yikes!  Still bad signature! */
 			*error = -SCTP_IERROR_BAD_SIG;
@@ -1555,7 +1425,7 @@ no_hmac:
 	retval->peer.port = ntohs(chunk->sctp_hdr->source);
 
 	/* Populate the association from the cookie.  */
-	retval->c = *bear_cookie;
+	memcpy(&retval->c, bear_cookie, sizeof(*bear_cookie));
 
 	if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie,
 						 GFP_ATOMIC) < 0) {
@@ -1565,12 +1435,13 @@ no_hmac:
 
 	/* Also, add the destination address. */
 	if (list_empty(&retval->base.bind_addr.address_list)) {
-		sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 
+		sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
 				   GFP_ATOMIC);
 	}
 
 	retval->next_tsn = retval->c.initial_tsn;
 	retval->ctsn_ack_point = retval->next_tsn - 1;
+	retval->addip_serial = retval->c.initial_tsn;
 
 	/* The INIT stuff will be done by the side effects.  */
 	return retval;
@@ -1603,8 +1474,8 @@ struct __sctp_missing {
  */
 static int sctp_process_missing_param(const struct sctp_association *asoc,
 				      sctp_param_t paramtype,
-				      sctp_chunk_t *chunk,
-				      sctp_chunk_t **errp)
+				      struct sctp_chunk *chunk,
+				      struct sctp_chunk **errp)
 {
 	struct __sctp_missing report;
 	__u16 len;
@@ -1630,8 +1501,8 @@ static int sctp_process_missing_param(co
 
 /* Report an Invalid Mandatory Parameter.  */
 static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
-				      sctp_chunk_t *chunk,
-				      sctp_chunk_t **errp)
+				      struct sctp_chunk *chunk,
+				      struct sctp_chunk **errp)
 {
 	/* Invalid Mandatory Parameter Error has no payload. */
 
@@ -1650,8 +1521,8 @@ static int sctp_process_inv_mandatory(co
  */
 static int sctp_process_hn_param(const struct sctp_association *asoc,
 				 union sctp_params param,
-				 sctp_chunk_t *chunk,
-				 sctp_chunk_t **errp)
+				 struct sctp_chunk *chunk,
+				 struct sctp_chunk **errp)
 {
 	__u16 len = ntohs(param.p->length);
 
@@ -1695,8 +1566,8 @@ static int sctp_process_hn_param(const s
  */
 static int sctp_process_unk_param(const struct sctp_association *asoc,
 				  union sctp_params param,
-				  sctp_chunk_t *chunk,
-				  sctp_chunk_t **errp)
+				  struct sctp_chunk *chunk,
+				  struct sctp_chunk **errp)
 {
 	int retval = 1;
 
@@ -1758,8 +1629,8 @@ static int sctp_process_unk_param(const 
 static int sctp_verify_param(const struct sctp_association *asoc,
 			     union sctp_params param,
 			     sctp_cid_t cid,
-			     sctp_chunk_t *chunk,
-			     sctp_chunk_t **err_chunk)
+			     struct sctp_chunk *chunk,
+			     struct sctp_chunk **err_chunk)
 {
 	int retval = 1;
 
@@ -1796,8 +1667,8 @@ static int sctp_verify_param(const struc
 int sctp_verify_init(const struct sctp_association *asoc,
 		     sctp_cid_t cid,
 		     sctp_init_chunk_t *peer_init,
-		     sctp_chunk_t *chunk,
-		     sctp_chunk_t **errp)
+		     struct sctp_chunk *chunk,
+		     struct sctp_chunk **errp)
 {
 	union sctp_params param;
 	int has_cookie = 0;
@@ -1831,8 +1702,12 @@ int sctp_verify_init(const struct sctp_a
 
 	sctp_walk_params(param, peer_init, init_hdr.params) {
 
-		if (!sctp_verify_param(asoc, param, cid, chunk, errp))
-			return 0;
+		if (!sctp_verify_param(asoc, param, cid, chunk, errp)) {
+			if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type)
+				return 0;
+			else
+				return 1;
+		}
 
 	} /* for (loop through all parameters) */
 
@@ -1939,11 +1814,14 @@ int sctp_process_init(struct sctp_associ
 	 * stream sequence number shall be set to 0.
 	 */
 
-	/* Allocate storage for the negotiated streams. */
-	asoc->ssnmap = sctp_ssnmap_new(asoc->peer.i.num_outbound_streams,
-				       asoc->c.sinit_num_ostreams, gfp);
-	if (!asoc->ssnmap)
-		goto nomem_ssnmap;
+	/* Allocate storage for the negotiated streams if it is not a temporary 	 * association.
+	 */
+	if (!asoc->temp) {
+		asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams,
+					       asoc->c.sinit_num_ostreams, gfp);
+		if (!asoc->ssnmap)
+			goto nomem_ssnmap;
+	}
 
 	/* ADDIP Section 4.1 ASCONF Chunk Procedures
 	 *
@@ -1963,7 +1841,7 @@ clean_up:
 	/* Release the transport structures. */
 	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
 		transport = list_entry(pos, struct sctp_transport, transports);
-		list_del(pos);
+		list_del_init(pos);
 		sctp_transport_free(transport);
 	}
 nomem:
@@ -1991,6 +1869,7 @@ int sctp_process_param(struct sctp_assoc
 	int retval = 1;
 	sctp_scope_t scope;
 	time_t stale;
+	struct sctp_af *af;
 
 	/* We maintain all INIT parameters in network byte order all the
 	 * time.  This allows us to not worry about whether the parameters
@@ -1998,11 +1877,12 @@ int sctp_process_param(struct sctp_assoc
 	 */
 	switch (param.p->type) {
 	case SCTP_PARAM_IPV6_ADDRESS:
-		if( PF_INET6 != asoc->base.sk->family)
+		if (PF_INET6 != asoc->base.sk->sk_family)
 			break;
 		/* Fall through. */
 	case SCTP_PARAM_IPV4_ADDRESS:
-		sctp_param2sockaddr(&addr, param.addr, asoc->peer.port, 0);
+		af = sctp_get_af_specific(param_type2af(param.p->type));
+		af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
 		scope = sctp_scope(peer_addr);
 		if (sctp_in_scope(&addr, scope))
 			if (!sctp_assoc_add_peer(asoc, &addr, gfp))
@@ -2010,7 +1890,7 @@ int sctp_process_param(struct sctp_assoc
 		break;
 
 	case SCTP_PARAM_COOKIE_PRESERVATIVE:
-		if (!sctp_proto.cookie_preserve_enable)
+		if (!sctp_cookie_preserve_enable)
 			break;
 
 		stale = ntohl(param.life->lifespan_increment);
@@ -2114,86 +1994,619 @@ __u32 sctp_generate_tsn(const struct sct
 	return retval;
 }
 
-/********************************************************************
- * 4th Level Abstractions
- ********************************************************************/
-
-/* Convert from an SCTP IP parameter to a union sctp_addr.  */
-void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *param,
-			 __u16 port, int iif)
+/*
+ * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF)
+ *      0                   1                   2                   3
+ *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     | Type = 0xC1   |  Chunk Flags  |      Chunk Length             |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                       Serial Number                           |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                    Address Parameter                          |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                     ASCONF Parameter #1                       |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     \                                                               \
+ *     /                             ....                              /
+ *     \                                                               \
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                     ASCONF Parameter #N                       |
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Address Parameter and other parameter will not be wrapped in this function 
+ */
+struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
+				    union sctp_addr *addr, int vparam_len)
 {
-	switch(param->v4.param_hdr.type) {
-	case SCTP_PARAM_IPV4_ADDRESS:
-		addr->v4.sin_family = AF_INET;
-		addr->v4.sin_port = port;
-		addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
-		break;
+	sctp_addiphdr_t asconf;
+	struct sctp_chunk *retval;
+	int length = sizeof(asconf) + vparam_len;
+	union sctp_addr_param addrparam;
+	int addrlen;
+	struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family);
+
+	addrlen = af->to_addr_param(addr, &addrparam);
+	if (!addrlen)
+		return NULL;
+	length += addrlen;
 
-	case SCTP_PARAM_IPV6_ADDRESS:
-		addr->v6.sin6_family = AF_INET6;
-		addr->v6.sin6_port = port;
-		addr->v6.sin6_flowinfo = 0; /* BUG */
-		addr->v6.sin6_addr = param->v6.addr;
-		addr->v6.sin6_scope_id = iif;
-		break;
+	/* Create the chunk.  */
+	retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF, 0, length);
+	if (!retval)
+		return NULL;
 
-	default:
-		SCTP_DEBUG_PRINTK("Illegal address type %d\n",
-				  ntohs(param->v4.param_hdr.type));
-		break;
-	};
+	asconf.serial = htonl(asoc->addip_serial++);
+
+	retval->subh.addip_hdr =
+		sctp_addto_chunk(retval, sizeof(asconf), &asconf);
+	retval->param_hdr.v =
+		sctp_addto_chunk(retval, addrlen, &addrparam);
+
+	return retval;
+}
+
+/* ADDIP
+ * 3.2.1 Add IP Address
+ * 	0                   1                   2                   3
+ * 	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |        Type = 0xC001          |    Length = Variable          |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |               ASCONF-Request Correlation ID                   |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                       Address Parameter                       |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 3.2.2 Delete IP Address
+ * 	0                   1                   2                   3
+ * 	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |        Type = 0xC002          |    Length = Variable          |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |               ASCONF-Request Correlation ID                   |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                       Address Parameter                       |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
+					      union sctp_addr	      *laddr,
+					      struct sockaddr	      *addrs,
+					      int		      addrcnt,
+					      __u16		      flags)
+{
+	sctp_addip_param_t	param;
+	struct sctp_chunk	*retval;
+	union sctp_addr_param	addr_param;
+	union sctp_addr		*addr;
+	void			*addr_buf;
+	struct sctp_af		*af;
+	int			paramlen = sizeof(param);
+	int			addr_param_len = 0;
+	int 			totallen = 0;
+	int 			i;
+
+	/* Get total length of all the address parameters. */
+	addr_buf = addrs;
+	for (i = 0; i < addrcnt; i++) {
+		addr = (union sctp_addr *)addr_buf;
+		af = sctp_get_af_specific(addr->v4.sin_family);
+		addr_param_len = af->to_addr_param(addr, &addr_param);
+
+		totallen += paramlen;
+		totallen += addr_param_len;
+
+		addr_buf += af->sockaddr_len;
+	}
+
+	/* Create an asconf chunk with the required length. */
+	retval = sctp_make_asconf(asoc, laddr, totallen);
+	if (!retval)
+		return NULL;
+
+	/* Add the address parameters to the asconf chunk. */
+	addr_buf = addrs;
+	for (i = 0; i < addrcnt; i++) {
+		addr = (union sctp_addr *)addr_buf;
+		af = sctp_get_af_specific(addr->v4.sin_family);
+		addr_param_len = af->to_addr_param(addr, &addr_param);
+		param.param_hdr.type = flags;
+		param.param_hdr.length = htons(paramlen + addr_param_len);
+		param.crr_id = i;
+
+		sctp_addto_chunk(retval, paramlen, &param);
+		sctp_addto_chunk(retval, addr_param_len, &addr_param);
+
+		addr_buf += af->sockaddr_len;
+	}
+	return retval;
 }
 
-/* Convert an IP address in an SCTP param into a sockaddr_in.  */
-/* Returns true if a valid conversion was possible.  */
-int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa)
+/* ADDIP
+ * 3.2.4 Set Primary IP Address
+ *	0                   1                   2                   3
+ *	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |        Type =0xC004           |    Length = Variable          |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |               ASCONF-Request Correlation ID                   |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                       Address Parameter                       |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Create an ASCONF chunk with Set Primary IP address parameter. 
+ */
+struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
+					     union sctp_addr *addr)
 {
-	switch (p.p->type) {
-	case SCTP_PARAM_IPV4_ADDRESS:
-		sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr);
-		sa->v4.sin_family = AF_INET;
-		break;
+	sctp_addip_param_t	param;
+	struct sctp_chunk 	*retval;
+	int 			len = sizeof(param);
+	union sctp_addr_param	addrparam;
+	int			addrlen;
+	struct sctp_af		*af = sctp_get_af_specific(addr->v4.sin_family);
+
+	addrlen = af->to_addr_param(addr, &addrparam);
+	if (!addrlen)
+		return NULL;
+	len += addrlen;
 
-	case SCTP_PARAM_IPV6_ADDRESS:
-		*((struct in6_addr *)&sa->v4.sin_addr)
-			= p.v6->addr;
-		sa->v4.sin_family = AF_INET6;
-		break;
+	/* Create the chunk and make asconf header. */
+	retval = sctp_make_asconf(asoc, addr, len);
+	if (!retval)
+		return NULL;
 
-        default:
-                return 0;
-        };
+	param.param_hdr.type = SCTP_PARAM_SET_PRIMARY;
+	param.param_hdr.length = htons(len);
+	param.crr_id = 0;
 
-	return 1;
+	sctp_addto_chunk(retval, sizeof(param), &param);
+	sctp_addto_chunk(retval, addrlen, &addrparam);
+
+	return retval;
 }
 
-/* Convert a sockaddr_in to an IP address in an SCTP param.
- * Returns len if a valid conversion was possible.
+/* ADDIP 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK)
+ *      0                   1                   2                   3
+ *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     | Type = 0x80   |  Chunk Flags  |      Chunk Length             |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                       Serial Number                           |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                 ASCONF Parameter Response#1                   |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     \                                                               \
+ *     /                             ....                              /
+ *     \                                                               \
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                 ASCONF Parameter Response#N                   |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Create an ASCONF_ACK chunk with enough space for the parameter responses. 
  */
-int sockaddr2sctp_addr(const union sctp_addr *sa, sctp_addr_param_t *p)
+struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
+					__u32 serial, int vparam_len)
 {
-	int len = 0;
+	sctp_addiphdr_t		asconf;
+	struct sctp_chunk	*retval;
+	int			length = sizeof(asconf) + vparam_len;
 
-	switch (sa->v4.sin_family) {
-	case AF_INET:
-		p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
-		p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t));
-		len = sizeof(sctp_ipv4addr_param_t);
-		p->v4.addr.s_addr = sa->v4.sin_addr.s_addr;
-		break;
-
-	case AF_INET6:
-		p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
-		p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t));
-		len = sizeof(sctp_ipv6addr_param_t);
-		p->v6.addr = *(&sa->v6.sin6_addr);
+	/* Create the chunk.  */
+	retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF_ACK, 0, length);
+	if (!retval)
+		return NULL;
+
+	asconf.serial = htonl(serial);
+
+	retval->subh.addip_hdr =
+		sctp_addto_chunk(retval, sizeof(asconf), &asconf);
+
+	return retval;
+}
+
+/* Add response parameters to an ASCONF_ACK chunk. */
+static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id,
+			      __u16 err_code, sctp_addip_param_t *asconf_param)
+{
+	sctp_addip_param_t 	ack_param;
+	sctp_errhdr_t		err_param;
+	int			asconf_param_len = 0;
+	int			err_param_len = 0;
+	__u16			response_type;
+
+	if (SCTP_ERROR_NO_ERROR == err_code) {
+		response_type = SCTP_PARAM_SUCCESS_REPORT;
+	} else {
+		response_type = SCTP_PARAM_ERR_CAUSE;
+		err_param_len = sizeof(err_param);
+		if (asconf_param)
+			asconf_param_len =
+				 ntohs(asconf_param->param_hdr.length);
+	}
+
+	/* Add Success Indication or Error Cause Indication parameter. */ 
+	ack_param.param_hdr.type = response_type;
+	ack_param.param_hdr.length = htons(sizeof(ack_param) +
+					   err_param_len +
+					   asconf_param_len);
+	ack_param.crr_id = crr_id;
+	sctp_addto_chunk(chunk, sizeof(ack_param), &ack_param);
+
+	if (SCTP_ERROR_NO_ERROR == err_code)
+		return;
+
+	/* Add Error Cause parameter. */
+	err_param.cause = err_code;
+	err_param.length = htons(err_param_len + asconf_param_len);
+	sctp_addto_chunk(chunk, err_param_len, &err_param);
+
+	/* Add the failed TLV copied from ASCONF chunk. */
+	if (asconf_param)
+		sctp_addto_chunk(chunk, asconf_param_len, asconf_param);
+}
+
+/* Process a asconf parameter. */
+static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
+				       struct sctp_chunk *asconf,
+				       sctp_addip_param_t *asconf_param)
+{
+	struct sctp_transport *peer;
+	struct sctp_af *af;
+	union sctp_addr	addr;
+	struct list_head *pos;
+	union sctp_addr_param *addr_param;
+				 
+	addr_param = (union sctp_addr_param *)
+			((void *)asconf_param + sizeof(sctp_addip_param_t));
+
+	af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
+	if (unlikely(!af))
+		return SCTP_ERROR_INV_PARAM;
+
+	af->from_addr_param(&addr, addr_param, asoc->peer.port, 0);
+	switch (asconf_param->param_hdr.type) {
+	case SCTP_PARAM_ADD_IP:
+		/* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
+	 	 * request and does not have the local resources to add this
+	 	 * new address to the association, it MUST return an Error
+	 	 * Cause TLV set to the new error code 'Operation Refused
+	 	 * Due to Resource Shortage'.
+	 	 */
+
+		peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC);
+		if (!peer)
+			return SCTP_ERROR_RSRC_LOW;
+
+		/* Start the heartbeat timer. */
+		if (!mod_timer(&peer->hb_timer, sctp_transport_timeout(peer)))
+			sctp_transport_hold(peer);
+		break;
+	case SCTP_PARAM_DEL_IP:
+		/* ADDIP 4.3 D7) If a request is received to delete the
+	 	 * last remaining IP address of a peer endpoint, the receiver
+	 	 * MUST send an Error Cause TLV with the error cause set to the
+	 	 * new error code 'Request to Delete Last Remaining IP Address'.
+	 	 */
+		pos = asoc->peer.transport_addr_list.next;
+		if (pos->next == &asoc->peer.transport_addr_list)
+			return SCTP_ERROR_DEL_LAST_IP;
+
+		/* ADDIP 4.3 D8) If a request is received to delete an IP
+		 * address which is also the source address of the IP packet
+		 * which contained the ASCONF chunk, the receiver MUST reject
+		 * this request. To reject the request the receiver MUST send
+		 * an Error Cause TLV set to the new error code 'Request to
+		 * Delete Source IP Address'
+		 */
+		if (sctp_cmp_addr_exact(sctp_source(asconf), &addr))
+			return SCTP_ERROR_DEL_SRC_IP;
+
+		sctp_assoc_del_peer(asoc, &addr);
 		break;
+	case SCTP_PARAM_SET_PRIMARY:
+		peer = sctp_assoc_lookup_paddr(asoc, &addr);
+		if (!peer)
+			return SCTP_ERROR_INV_PARAM;
 
+		sctp_assoc_set_primary(asoc, peer);
+		break;
 	default:
-		printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n",
-		       sa->v4.sin_family);
-		return 0;
-	};
+		return SCTP_ERROR_INV_PARAM;
+		break;
+	}
+
+	return SCTP_ERROR_NO_ERROR;
+}
+
+/* Process an incoming ASCONF chunk with the next expected serial no. and 
+ * return an ASCONF_ACK chunk to be sent in response.
+ */
+struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+				       struct sctp_chunk *asconf)
+{
+	sctp_addiphdr_t		*hdr;
+	union sctp_addr_param	*addr_param;
+	sctp_addip_param_t	*asconf_param;
+	struct sctp_chunk	*asconf_ack;
+
+	__u16	err_code;
+	int	length = 0;
+	int	chunk_len = asconf->skb->len;
+	__u32	serial;
+	int	all_param_pass = 1;
+
+	hdr = (sctp_addiphdr_t *)asconf->skb->data;
+	serial = ntohl(hdr->serial);
+
+	/* Skip the addiphdr and store a pointer to address parameter.  */ 
+	length = sizeof(sctp_addiphdr_t);
+	addr_param = (union sctp_addr_param *)(asconf->skb->data + length);
+	chunk_len -= length;
+
+	/* Skip the address parameter and store a pointer to the first
+	 * asconf paramter.
+	 */ 
+	length = ntohs(addr_param->v4.param_hdr.length);
+	asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
+	chunk_len -= length;
+
+	/* create an ASCONF_ACK chunk. 
+	 * Based on the definitions of parameters, we know that the size of
+	 * ASCONF_ACK parameters are less than or equal to the twice of ASCONF
+	 * paramters.
+	 */
+	asconf_ack = sctp_make_asconf_ack(asoc, serial, chunk_len * 2);
+	if (!asconf_ack)
+		goto done;
+
+	/* Process the TLVs contained within the ASCONF chunk. */
+	while (chunk_len > 0) {
+		err_code = sctp_process_asconf_param(asoc, asconf,
+						     asconf_param);
+		/* ADDIP 4.1 A7)
+		 * If an error response is received for a TLV parameter,
+		 * all TLVs with no response before the failed TLV are
+		 * considered successful if not reported.  All TLVs after
+		 * the failed response are considered unsuccessful unless
+		 * a specific success indication is present for the parameter.
+		 */
+		if (SCTP_ERROR_NO_ERROR != err_code)
+			all_param_pass = 0;
+
+		if (!all_param_pass)
+			sctp_add_asconf_response(asconf_ack,
+						 asconf_param->crr_id, err_code,
+						 asconf_param);
+
+		/* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add
+		 * an IP address sends an 'Out of Resource' in its response, it
+		 * MUST also fail any subsequent add or delete requests bundled
+		 * in the ASCONF. 
+		 */
+		if (SCTP_ERROR_RSRC_LOW == err_code)
+			goto done;
 
-	return len;
+		/* Move to the next ASCONF param. */
+		length = ntohs(asconf_param->param_hdr.length);
+		asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
+						      length);
+		chunk_len -= length;
+	}
+	
+done:
+	asoc->peer.addip_serial++;
+
+	/* If we are sending a new ASCONF_ACK hold a reference to it in assoc
+	 * after freeing the reference to old asconf ack if any. 
+	 */
+	if (asconf_ack) {
+		if (asoc->addip_last_asconf_ack)
+			sctp_chunk_free(asoc->addip_last_asconf_ack);
+
+		sctp_chunk_hold(asconf_ack);
+		asoc->addip_last_asconf_ack = asconf_ack;
+	}
+
+	return asconf_ack;
+}
+
+/* Process a asconf parameter that is successfully acked. */
+static int sctp_asconf_param_success(struct sctp_association *asoc,
+				     sctp_addip_param_t *asconf_param)
+{
+	struct sctp_af *af;
+	union sctp_addr	addr;
+	struct sctp_bind_addr *bp = &asoc->base.bind_addr;
+	union sctp_addr_param *addr_param;
+	int retval = 0;
+
+	addr_param = (union sctp_addr_param *)
+			((void *)asconf_param + sizeof(sctp_addip_param_t));
+
+	/* We have checked the packet before, so we do not check again.	*/
+	af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
+	af->from_addr_param(&addr, addr_param, bp->port, 0);
+
+	switch (asconf_param->param_hdr.type) {
+	case SCTP_PARAM_ADD_IP:
+		sctp_local_bh_disable();
+		sctp_write_lock(&asoc->base.addr_lock);
+		retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC);
+		sctp_write_unlock(&asoc->base.addr_lock);
+		sctp_local_bh_enable();
+		break;
+	case SCTP_PARAM_DEL_IP:
+		sctp_local_bh_disable();
+		sctp_write_lock(&asoc->base.addr_lock);
+		retval = sctp_del_bind_addr(bp, &addr);
+		sctp_write_unlock(&asoc->base.addr_lock);
+		sctp_local_bh_enable();
+		break;
+	default:
+		break;
+	}
+
+	return retval;
+}
+
+/* Get the corresponding ASCONF response error code from the ASCONF_ACK chunk
+ * for the given asconf parameter.  If there is no response for this parameter,
+ * return the error code based on the third argument 'no_err'. 
+ * ADDIP 4.1
+ * A7) If an error response is received for a TLV parameter, all TLVs with no
+ * response before the failed TLV are considered successful if not reported.
+ * All TLVs after the failed response are considered unsuccessful unless a
+ * specific success indication is present for the parameter.
+ */
+static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
+				      sctp_addip_param_t *asconf_param,
+				      int no_err)
+{
+	sctp_addip_param_t	*asconf_ack_param;
+	sctp_errhdr_t		*err_param;
+	int			length;
+	int			asconf_ack_len = asconf_ack->skb->len;
+	__u16			err_code;
+
+	if (no_err)
+		err_code = SCTP_ERROR_NO_ERROR;
+	else
+		err_code = SCTP_ERROR_REQ_REFUSED;
+
+	/* Skip the addiphdr from the asconf_ack chunk and store a pointer to
+	 * the first asconf_ack parameter.
+	 */ 
+	length = sizeof(sctp_addiphdr_t);
+	asconf_ack_param = (sctp_addip_param_t *)(asconf_ack->skb->data +
+						  length);
+	asconf_ack_len -= length;
+
+	while (asconf_ack_len > 0) {
+		if (asconf_ack_param->crr_id == asconf_param->crr_id) {
+			switch(asconf_ack_param->param_hdr.type) {
+			case SCTP_PARAM_SUCCESS_REPORT:
+				return SCTP_ERROR_NO_ERROR;
+			case SCTP_PARAM_ERR_CAUSE:
+				length = sizeof(sctp_addip_param_t);
+				err_param = (sctp_errhdr_t *)
+					   ((void *)asconf_ack_param + length);
+				asconf_ack_len -= length;
+				if (asconf_ack_len > 0)
+					return err_param->cause;
+				else
+					return SCTP_ERROR_INV_PARAM;
+				break;
+			default:
+				return SCTP_ERROR_INV_PARAM;
+			}
+		}
+
+		length = ntohs(asconf_ack_param->param_hdr.length);
+		asconf_ack_param = (sctp_addip_param_t *)
+					((void *)asconf_ack_param + length);
+		asconf_ack_len -= length;
+	}
+
+	return err_code;
+}
+
+/* Process an incoming ASCONF_ACK chunk against the cached last ASCONF chunk. */
+int sctp_process_asconf_ack(struct sctp_association *asoc,
+			    struct sctp_chunk *asconf_ack)
+{
+	struct sctp_chunk	*asconf = asoc->addip_last_asconf;
+	union sctp_addr_param	*addr_param;
+	sctp_addip_param_t	*asconf_param;
+	int	length = 0;
+	int	asconf_len = asconf->skb->len;
+	int	all_param_pass = 0;
+	int	no_err = 1;
+	int	retval = 0;
+	__u16	err_code = SCTP_ERROR_NO_ERROR;
+
+	/* Skip the chunkhdr and addiphdr from the last asconf sent and store
+	 * a pointer to address parameter.
+	 */ 
+	length = sizeof(sctp_addip_chunk_t);
+	addr_param = (union sctp_addr_param *)(asconf->skb->data + length);
+	asconf_len -= length;
+
+	/* Skip the address parameter in the last asconf sent and store a
+	 * pointer to the first asconf paramter.
+	 */ 
+	length = ntohs(addr_param->v4.param_hdr.length);
+	asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
+	asconf_len -= length;
+
+	/* ADDIP 4.1
+	 * A8) If there is no response(s) to specific TLV parameter(s), and no
+	 * failures are indicated, then all request(s) are considered
+	 * successful.
+	 */
+	if (asconf_ack->skb->len == sizeof(sctp_addiphdr_t))
+		all_param_pass = 1;
+
+	/* Process the TLVs contained in the last sent ASCONF chunk. */
+	while (asconf_len > 0) {
+		if (all_param_pass)
+			err_code = SCTP_ERROR_NO_ERROR;
+		else {
+			err_code = sctp_get_asconf_response(asconf_ack,
+							    asconf_param,
+							    no_err);
+			if (no_err && (SCTP_ERROR_NO_ERROR != err_code))
+				no_err = 0;
+		}
+
+		switch (err_code) {
+		case SCTP_ERROR_NO_ERROR:
+			retval = sctp_asconf_param_success(asoc, asconf_param);
+			break;
+
+		case SCTP_ERROR_RSRC_LOW:
+			retval = 1;
+			break;
+
+		case SCTP_ERROR_INV_PARAM:
+			/* Disable sending this type of asconf parameter in
+			 * future.
+			 */	
+			asoc->peer.addip_disabled_mask |=
+				asconf_param->param_hdr.type;
+			break;
+
+		case SCTP_ERROR_REQ_REFUSED:
+		case SCTP_ERROR_DEL_LAST_IP:
+		case SCTP_ERROR_DEL_SRC_IP:
+		default:
+			 break;
+		}
+
+		/* Skip the processed asconf parameter and move to the next
+		 * one.
+	 	 */ 
+		length = ntohs(asconf_param->param_hdr.length);
+		asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
+						      length);
+		asconf_len -= length;
+	}
+
+	/* Free the cached last sent asconf chunk. */
+	sctp_chunk_free(asconf);
+	asoc->addip_last_asconf = NULL;
+
+	/* Send the next asconf chunk from the addip chunk queue. */
+	asconf = (struct sctp_chunk *)__skb_dequeue(&asoc->addip_chunks);
+	if (asconf) {
+		/* Hold the chunk until an ASCONF_ACK is received. */
+		sctp_chunk_hold(asconf);
+		if (sctp_primitive_ASCONF(asoc, asconf))
+			sctp_chunk_free(asconf);
+		else
+			asoc->addip_last_asconf = asconf;
+	}
+
+	return retval;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_sideeffect.c linux-2.4.26-pre6/net/sctp/sm_sideeffect.c
--- linux-2.4.25/net/sctp/sm_sideeffect.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/sm_sideeffect.c	2004-03-25 00:20:33.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2002 International Business Machines Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -81,11 +81,11 @@ static void sctp_do_ecn_ce_work(struct s
  * This element represents the lowest TSN number in the datagram
  * that was originally marked with the CE bit.
  */
-static sctp_chunk_t *sctp_do_ecn_ecne_work(struct sctp_association *asoc,
+static struct sctp_chunk *sctp_do_ecn_ecne_work(struct sctp_association *asoc,
 					   __u32 lowest_tsn,
-					   sctp_chunk_t *chunk)
+					   struct sctp_chunk *chunk)
 {
-	sctp_chunk_t *repl;
+	struct sctp_chunk *repl;
 
 	/* Our previously transmitted packet ran into some congestion
 	 * so we should take action by reducing cwnd and ssthresh
@@ -229,7 +229,7 @@ void sctp_generate_t3_rtx_event(unsigned
 			   transport, GFP_ATOMIC);
 
 	if (error)
-		asoc->base.sk->err = -error;
+		asoc->base.sk->sk_err = -error;
 
 out_unlock:
 	sctp_bh_unlock_sock(asoc->base.sk);
@@ -269,7 +269,7 @@ static void sctp_generate_timeout_event(
 			   (void *)timeout_type, GFP_ATOMIC);
 
 	if (error)
-		asoc->base.sk->err = -error;
+		asoc->base.sk->sk_err = -error;
 
 out_unlock:
 	sctp_bh_unlock_sock(asoc->base.sk);
@@ -294,6 +294,12 @@ void sctp_generate_t2_shutdown_event(uns
 	sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN);
 }
 
+void sctp_generate_t4_rto_event(unsigned long data)
+{
+	struct sctp_association *asoc = (struct sctp_association *) data;
+	sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T4_RTO);
+}
+
 void sctp_generate_t5_shutdown_guard_event(unsigned long data)
 {
         struct sctp_association *asoc = (struct sctp_association *)data;
@@ -339,7 +345,7 @@ void sctp_generate_heartbeat_event(unsig
 			   transport, GFP_ATOMIC);
 
          if (error)
-		 asoc->base.sk->err = -error;
+		 asoc->base.sk->sk_err = -error;
 
 out_unlock:
 	sctp_bh_unlock_sock(asoc->base.sk);
@@ -359,6 +365,7 @@ sctp_timer_event_t *sctp_timer_events[SC
 	sctp_generate_t1_init_event,
 	sctp_generate_t2_shutdown_event,
 	NULL,
+	sctp_generate_t4_rto_event,
 	sctp_generate_t5_shutdown_guard_event,
 	sctp_generate_heartbeat_event,
 	sctp_generate_sack_event,
@@ -415,7 +422,8 @@ static void sctp_cmd_init_failed(sctp_cm
 	struct sctp_ulpevent *event;
 
 	event = sctp_ulpevent_make_assoc_change(asoc,0, SCTP_CANT_STR_ASSOC,
-						0, 0, 0, GFP_ATOMIC);
+						(__u16)error, 0, 0,
+						GFP_ATOMIC);
 
 	if (event)
 		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
@@ -528,7 +536,7 @@ static void sctp_cmd_hb_timer_update(sct
 static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
 				  struct sctp_association *asoc,
 				  struct sctp_transport *t,
-				  sctp_chunk_t *chunk)
+				  struct sctp_chunk *chunk)
 {
 	sctp_sender_hb_info_t *hbinfo;
 
@@ -596,7 +604,7 @@ static int sctp_cmd_process_sack(sctp_cm
  */
 static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, 
 			      struct sctp_association *asoc,
-			      sctp_chunk_t *chunk)
+			      struct sctp_chunk *chunk)
 {
 	struct sctp_transport *t;
 
@@ -607,33 +615,30 @@ static void sctp_cmd_setup_t2(sctp_cmd_s
 }
 
 /* Helper function to change the state of an association. */
-static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *asoc,
+static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, 
+			       struct sctp_association *asoc,
 			       sctp_state_t state)
 {
-
 	struct sock *sk = asoc->base.sk;
-	struct sctp_opt *sp = sctp_sk(sk);
 
 	asoc->state = state;
-	asoc->state_timestamp = jiffies;
 
-	if (SCTP_SOCKET_TCP == sp->type) {
-		/* Change the sk->state of a TCP-style socket that has 
+	if (sctp_style(sk, TCP)) {
+		/* Change the sk->sk_state of a TCP-style socket that has 
 		 * sucessfully completed a connect() call.
 		 */
-		if ((SCTP_STATE_ESTABLISHED == asoc->state) &&
-		    (SCTP_SS_CLOSED == sk->state))
-			sk->state = SCTP_SS_ESTABLISHED;
+		if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
+			sk->sk_state = SCTP_SS_ESTABLISHED;
 
 		/* Set the RCV_SHUTDOWN flag when a SHUTDOWN is received. */
-		if (SCTP_STATE_SHUTDOWN_RECEIVED == asoc->state)
-			sk->shutdown |= RCV_SHUTDOWN;
-
+		if (sctp_state(asoc, SHUTDOWN_RECEIVED) &&
+		    sctp_sstate(sk, ESTABLISHED))
+			sk->sk_shutdown |= RCV_SHUTDOWN;
 	}
 
-	if ((SCTP_STATE_ESTABLISHED == asoc->state) ||
-	    (SCTP_STATE_CLOSED == asoc->state) ||
-	    (SCTP_STATE_SHUTDOWN_RECEIVED == asoc->state)) {
+	if (sctp_state(asoc, ESTABLISHED) ||
+	    sctp_state(asoc, CLOSED) ||
+	    sctp_state(asoc, SHUTDOWN_RECEIVED)) {
 		/* Wake up any processes waiting in the asoc's wait queue in
 		 * sctp_wait_for_connect() or sctp_wait_for_sndbuf().
 	 	 */
@@ -646,30 +651,84 @@ static void sctp_cmd_new_state(sctp_cmd_
 		 * For a UDP-style socket, the waiters are woken up by the
 		 * notifications.
 		 */
-		if (SCTP_SOCKET_UDP != sp->type)
-			sk->state_change(sk);
+		if (!sctp_style(sk, UDP))
+			sk->sk_state_change(sk);
 	}
-
 }
 
 /* Helper function to delete an association. */
 static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds,
-			      struct sctp_association *asoc)
+				struct sctp_association *asoc)
 {
 	struct sock *sk = asoc->base.sk;
 
 	/* If it is a non-temporary association belonging to a TCP-style
-	 * listening socket, do not free it so that accept() can pick it
-	 * up later.
-	 */
-	if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) &&
-	    (SCTP_SS_LISTENING == sk->state) && (!asoc->temp))
+	 * listening socket that is not closed, do not free it so that accept() 
+	 * can pick it up later.
+	 */ 
+	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING) &&
+	    (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK))
 		return;
 
 	sctp_unhash_established(asoc);
 	sctp_association_free(asoc);
 }
 
+/*
+ * ADDIP Section 4.1 ASCONF Chunk Procedures
+ * A4) Start a T-4 RTO timer, using the RTO value of the selected
+ * destination address (we use active path instead of primary path just
+ * because primary path may be inactive. 
+ */
+static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
+				struct sctp_association *asoc,
+				struct sctp_chunk *chunk)
+{
+	struct sctp_transport *t;
+
+	t = asoc->peer.active_path;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto;
+	chunk->transport = t;
+}
+
+/* Process an incoming Operation Error Chunk. */ 
+static void sctp_cmd_process_operr(sctp_cmd_seq_t *cmds,
+				   struct sctp_association *asoc,
+				   struct sctp_chunk *chunk)
+{
+	struct sctp_operr_chunk *operr_chunk;
+	struct sctp_errhdr *err_hdr;
+
+	operr_chunk = (struct sctp_operr_chunk *)chunk->chunk_hdr;
+	err_hdr = &operr_chunk->err_hdr;
+
+	switch (err_hdr->cause) {
+	case SCTP_ERROR_UNKNOWN_CHUNK:
+	{
+		struct sctp_chunkhdr *unk_chunk_hdr;
+
+		unk_chunk_hdr = (struct sctp_chunkhdr *)err_hdr->variable;
+		switch (unk_chunk_hdr->type) {
+		/* ADDIP 4.1 A9) If the peer responds to an ASCONF with an
+		 * ERROR chunk reporting that it did not recognized the ASCONF
+		 * chunk type, the sender of the ASCONF MUST NOT send any
+		 * further ASCONF chunks and MUST stop its T-4 timer.
+		 */
+		case SCTP_CID_ASCONF:
+			asoc->peer.asconf_capable = 0;
+			sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP,
+					SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	default:
+		break;
+	}
+}
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -706,7 +765,7 @@ int sctp_do_sm(sctp_event_t event_type, 
 	       int gfp)
 {
 	sctp_cmd_seq_t commands;
-	sctp_sm_table_entry_t *state_fn;
+	const sctp_sm_table_entry_t *state_fn;
 	sctp_disposition_t status;
 	int error = 0;
 	typedef const char *(printfn_t)(sctp_subtype_t);
@@ -837,17 +896,18 @@ int sctp_cmd_interpreter(sctp_event_t ev
 	int error = 0;
 	int force;
 	sctp_cmd_t *cmd;
-	sctp_chunk_t *new_obj;
-	sctp_chunk_t *chunk = NULL;
+	struct sctp_chunk *new_obj;
+	struct sctp_chunk *chunk = NULL;
 	struct sctp_packet *packet;
 	struct list_head *pos;
 	struct timer_list *timer;
 	unsigned long timeout;
 	struct sctp_transport *t;
 	sctp_sackhdr_t sackh;
+	int local_cork = 0;
 
-	if(SCTP_EVENT_T_TIMEOUT != event_type)
-		chunk = (sctp_chunk_t *) event_arg;
+	if (SCTP_EVENT_T_TIMEOUT != event_type)
+		chunk = (struct sctp_chunk *) event_arg;
 
 	/* Note:  This whole file is a huge candidate for rework.
 	 * For example, each command could either have its own handler, so
@@ -864,6 +924,10 @@ int sctp_cmd_interpreter(sctp_event_t ev
 
 		case SCTP_CMD_NEW_ASOC:
 			/* Register a new association.  */
+			if (local_cork) {
+				sctp_outq_uncork(&asoc->outqueue); 
+				local_cork = 0;
+			}
 			asoc = cmd->obj.ptr;
 			/* Register with the endpoint.  */
 			sctp_endpoint_add_asoc(ep, asoc);
@@ -878,7 +942,11 @@ int sctp_cmd_interpreter(sctp_event_t ev
 		       sctp_outq_teardown(&asoc->outqueue);
 		       break;
 
-		case SCTP_CMD_DELETE_TCB:
+		case SCTP_CMD_DELETE_TCB:			
+			if (local_cork) {
+				sctp_outq_uncork(&asoc->outqueue);
+				local_cork = 0;
+			}
 			/* Delete the current association.  */
 			sctp_cmd_delete_tcb(commands, asoc);
 			asoc = NULL;
@@ -936,7 +1004,7 @@ int sctp_cmd_interpreter(sctp_event_t ev
 			new_obj = sctp_make_cookie_echo(asoc, chunk);
 			if (!new_obj) {
 				if (cmd->obj.ptr)
-					sctp_free_chunk(cmd->obj.ptr);
+					sctp_chunk_free(cmd->obj.ptr);
 				goto nomem;
 			}
 			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
@@ -957,7 +1025,7 @@ int sctp_cmd_interpreter(sctp_event_t ev
 			asoc->overall_error_count = 0;
 
 			/* Generate a SHUTDOWN chunk.  */
-			new_obj = sctp_make_shutdown(asoc);
+			new_obj = sctp_make_shutdown(asoc, chunk);
 			if (!new_obj)
 				goto nomem;
 			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
@@ -982,9 +1050,13 @@ int sctp_cmd_interpreter(sctp_event_t ev
 			break;
 
 		case SCTP_CMD_REPLY:
+			/* If an caller has not already corked, do cork. */
+			if (!asoc->outqueue.cork) {
+				sctp_outq_cork(&asoc->outqueue);
+				local_cork = 1;
+			}
 			/* Send a chunk to our peer.  */
-			error = sctp_outq_tail(&asoc->outqueue,
-					       cmd->obj.ptr);
+			error = sctp_outq_tail(&asoc->outqueue, cmd->obj.ptr);
 			break;
 
 		case SCTP_CMD_SEND_PKT:
@@ -1002,7 +1074,8 @@ int sctp_cmd_interpreter(sctp_event_t ev
 
 		case SCTP_CMD_TRANSMIT:
 			/* Kick start transmission. */
-			error = sctp_outq_flush(&asoc->outqueue, 0);
+			error = sctp_outq_uncork(&asoc->outqueue);
+			local_cork = 0;
 			break;
 
 		case SCTP_CMD_ECN_CE:
@@ -1167,19 +1240,28 @@ int sctp_cmd_interpreter(sctp_event_t ev
 					 GFP_ATOMIC);
 			break;
 
+		case SCTP_CMD_SETUP_T4:
+			sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr);
+			break;
+
+		case SCTP_CMD_PROCESS_OPERR:
+			sctp_cmd_process_operr(commands, asoc, chunk);
+			break;
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
 			       cmd->verb, cmd->obj.ptr);
 			break;
 		};
 		if (error)
-			return error;
+			break;
 	}
 
+out:
+	if (local_cork)
+		sctp_outq_uncork(&asoc->outqueue);
 	return error;
-
 nomem:
 	error = -ENOMEM;
-	return error;
+	goto out;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_statefuns.c linux-2.4.26-pre6/net/sctp/sm_statefuns.c
--- linux-2.4.25/net/sctp/sm_statefuns.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/sm_statefuns.c	2004-03-25 00:19:36.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2002 International Business Machines, Corp.
  * Copyright (c) 2001-2002 Intel Corp.
  * Copyright (c) 2002      Nokia Corp.
  *
@@ -45,6 +45,8 @@
  *    Dajiang Zhang 	    <dajiang.zhang@nokia.com>
  *    Daisy Chang	    <daisyc@us.ibm.com>
  *    Ardelle Fan	    <ardelle.fan@intel.com>
+ *    Ryan Layer	    <rmlayer@us.ibm.com>
+ *    Kevin Gao		    <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -101,7 +103,7 @@ sctp_disposition_t sctp_sf_do_4_C(const 
 				  void *arg,
 				  sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	struct sctp_ulpevent *ev;
 
 	/* RFC 2960 6.10 Bundling
@@ -185,10 +187,10 @@ sctp_disposition_t sctp_sf_do_5_1B_init(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
-	sctp_chunk_t *repl;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_chunk *repl;
 	struct sctp_association *new_asoc;
-	sctp_chunk_t *err_chunk;
+	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
 	sctp_unrecognized_param_t *unk_param;
 	struct sock *sk;
@@ -212,9 +214,9 @@ sctp_disposition_t sctp_sf_do_5_1B_init(
 	 * on the TCP-style socket exceed the max backlog, respond with an
 	 * ABORT.
 	 */
-	if ((SCTP_SS_LISTENING != sk->state) ||
-	    ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) &&
-	     (sk->ack_backlog >= sk->max_ack_backlog)))
+	if (!sctp_sstate(sk, LISTENING) ||
+	    (sctp_style(sk, TCP) &&
+	     (sk->sk_ack_backlog >= sk->sk_max_ack_backlog)))
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 
 	/* Verify the INIT chunk before processing it. */
@@ -232,7 +234,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(
 					ntohs(err_chunk->chunk_hdr->length) -
 					sizeof(sctp_chunkhdr_t));
 
-			sctp_free_chunk(err_chunk);
+			sctp_chunk_free(err_chunk);
 
 			if (packet) {
 				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
@@ -303,7 +305,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(
 		 * parameter type.
 		 */
 		sctp_addto_chunk(repl, len, unk_param);
-		sctp_free_chunk(err_chunk);
+		sctp_chunk_free(err_chunk);
 	}
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
@@ -320,7 +322,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(
 
 nomem_ack:
 	if (err_chunk)
-		sctp_free_chunk(err_chunk);
+		sctp_chunk_free(err_chunk);
 nomem_init:
 	sctp_association_free(new_asoc);
 nomem:
@@ -361,10 +363,10 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c
 				       void *arg,
 				       sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	sctp_init_chunk_t *initchunk;
 	__u32 init_tag;
-	sctp_chunk_t *err_chunk;
+	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
 	sctp_disposition_t ret;
 
@@ -386,7 +388,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c
 	 *   error and close the association by transmitting an ABORT.
 	 */
 	if (!init_tag) {
-		sctp_chunk_t *reply = sctp_make_abort(asoc, chunk, 0);
+		struct sctp_chunk *reply = sctp_make_abort(asoc, chunk, 0);
 		if (!reply)
 			goto nomem;
 
@@ -416,7 +418,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c
 					ntohs(err_chunk->chunk_hdr->length) -
 					sizeof(sctp_chunkhdr_t));
 
-			sctp_free_chunk(err_chunk);
+			sctp_chunk_free(err_chunk);
 
 			if (packet) {
 				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
@@ -519,13 +521,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(co
 				      const sctp_subtype_t type, void *arg,
 				      sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	struct sctp_association *new_asoc;
 	sctp_init_chunk_t *peer_init;
-	sctp_chunk_t *repl;
+	struct sctp_chunk *repl;
 	struct sctp_ulpevent *ev;
 	int error = 0;
-	sctp_chunk_t *err_chk_p;
+	struct sctp_chunk *err_chk_p;
 
 	/* If the packet is an OOTB packet which is temporarily on the
 	 * control endpoint, respond with an ABORT.
@@ -537,7 +539,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(co
 	 * are in good shape.
 	 */
         chunk->subh.cookie_hdr =
-		(sctp_signed_cookie_t *)chunk->skb->data;
+		(struct sctp_signed_cookie *)chunk->skb->data;
 	skb_pull(chunk->skb,
 		 ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
 
@@ -623,7 +625,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(co
 	return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
-	sctp_free_chunk(repl);
+	sctp_chunk_free(repl);
 nomem_repl:
 nomem_init:
 	sctp_association_free(new_asoc);
@@ -704,7 +706,7 @@ sctp_disposition_t sctp_sf_heartbeat(con
 				     sctp_cmd_seq_t *commands)
 {
 	struct sctp_transport *transport = (struct sctp_transport *) arg;
-	sctp_chunk_t *reply;
+	struct sctp_chunk *reply;
 	sctp_sender_hb_info_t hbinfo;
 	size_t paylen = 0;
 
@@ -738,7 +740,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(
 {
 	struct sctp_transport *transport = (struct sctp_transport *) arg;
 
-	if (asoc->overall_error_count >= asoc->overall_error_threshold) {
+	if (asoc->overall_error_count > asoc->max_retrans) {
 		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -801,8 +803,8 @@ sctp_disposition_t sctp_sf_beat_8_3(cons
 				    void *arg,
 				    sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
-	sctp_chunk_t *reply;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_chunk *reply;
 	size_t paylen = 0;
 
 	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
@@ -868,7 +870,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	union sctp_addr from_addr;
 	struct sctp_transport *link;
 	sctp_sender_hb_info_t *hbinfo;
@@ -919,24 +921,25 @@ sctp_disposition_t sctp_sf_backbeat_8_3(
  * condition.
  */
 static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
-				      sctp_chunk_t *init,
+				      struct sctp_chunk *init,
 				      sctp_cmd_seq_t *commands)
 {
 	int len;
 	struct sctp_packet *pkt;
-	sctp_addr_param_t *addrparm;
-	sctp_errhdr_t *errhdr;
+	union sctp_addr_param *addrparm;
+	struct sctp_errhdr *errhdr;
 	struct sctp_endpoint *ep;
-	char buffer[sizeof(sctp_errhdr_t) + sizeof(sctp_addr_param_t)];
+	char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)];
+	struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family);
 
 	/* Build the error on the stack.   We are way to malloc crazy
 	 * throughout the code today.
 	 */
-	errhdr = (sctp_errhdr_t *)buffer;
-	addrparm = (sctp_addr_param_t *)errhdr->variable;
+	errhdr = (struct sctp_errhdr *)buffer;
+	addrparm = (union sctp_addr_param *)errhdr->variable;
 
 	/* Copy into a parm format. */
-	len = sockaddr2sctp_addr(ssa, addrparm);
+	len = af->to_addr_param(ssa, addrparm);
 	len += sizeof(sctp_errhdr_t);
 
 	errhdr->cause = SCTP_ERROR_RESTART;
@@ -971,7 +974,7 @@ out:
  */
 static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
 				       const struct sctp_association *asoc,
-				       sctp_chunk_t *init,
+				       struct sctp_chunk *init,
 				       sctp_cmd_seq_t *commands)
 {
 	struct sctp_transport *new_addr, *addr;
@@ -1112,10 +1115,10 @@ static sctp_disposition_t sctp_sf_do_une
 	void *arg, sctp_cmd_seq_t *commands)
 {
 	sctp_disposition_t retval;
-	sctp_chunk_t *chunk = arg;
-	sctp_chunk_t *repl;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_chunk *repl;
 	struct sctp_association *new_asoc;
-	sctp_chunk_t *err_chunk;
+	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
 	sctp_unrecognized_param_t *unk_param;
 	int len;
@@ -1191,7 +1194,7 @@ static sctp_disposition_t sctp_sf_do_une
 	 * since there are no peer addresses to check against.
 	 * Upon return an ABORT will have been sent if needed.
 	 */
-	if (asoc->state != SCTP_STATE_COOKIE_WAIT) {
+	if (!sctp_state(asoc, COOKIE_WAIT)) {
 		if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk,
 						 commands)) {
 			retval = SCTP_DISPOSITION_CONSUME;
@@ -1238,7 +1241,6 @@ static sctp_disposition_t sctp_sf_do_une
 		 * parameter type.
 		 */
 		sctp_addto_chunk(repl, len, unk_param);
-		sctp_free_chunk(err_chunk);
 	}
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
@@ -1254,7 +1256,7 @@ static sctp_disposition_t sctp_sf_do_une
 
 cleanup:
 	if (err_chunk)
-		sctp_free_chunk(err_chunk);
+		sctp_chunk_free(err_chunk);
 	return retval;
 nomem:
 	retval = SCTP_DISPOSITION_NOMEM;
@@ -1377,13 +1379,13 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupi
  */
 static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
 					const struct sctp_association *asoc,
-					sctp_chunk_t *chunk,
+					struct sctp_chunk *chunk,
 					sctp_cmd_seq_t *commands,
 					struct sctp_association *new_asoc)
 {
 	sctp_init_chunk_t *peer_init;
 	struct sctp_ulpevent *ev;
-	sctp_chunk_t *repl;
+	struct sctp_chunk *repl;
 
 	/* new_asoc is a brand-new association, so these are not yet
 	 * side effects--it is safe to run them here.
@@ -1429,7 +1431,7 @@ static sctp_disposition_t sctp_sf_do_dup
 	return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
-	sctp_free_chunk(repl);
+	sctp_chunk_free(repl);
 nomem:
 	return SCTP_DISPOSITION_NOMEM;
 }
@@ -1444,13 +1446,13 @@ nomem:
 /* This case represents an initialization collision.  */
 static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
 					const struct sctp_association *asoc,
-					sctp_chunk_t *chunk,
+					struct sctp_chunk *chunk,
 					sctp_cmd_seq_t *commands,
 					struct sctp_association *new_asoc)
 {
 	sctp_init_chunk_t *peer_init;
 	struct sctp_ulpevent *ev;
-	sctp_chunk_t *repl;
+	struct sctp_chunk *repl;
 
 	/* new_asoc is a brand-new association, so these are not yet
 	 * side effects--it is safe to run them here.
@@ -1492,7 +1494,7 @@ static sctp_disposition_t sctp_sf_do_dup
 	return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
-	sctp_free_chunk(repl);
+	sctp_chunk_free(repl);
 nomem:
 	return SCTP_DISPOSITION_NOMEM;
 }
@@ -1507,10 +1509,10 @@ nomem:
  */
 /* This case represents an initialization collision.  */
 static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep,
-				      const struct sctp_association *asoc,
-				      sctp_chunk_t *chunk,
-				      sctp_cmd_seq_t *commands,
-				      struct sctp_association *new_asoc)
+					const struct sctp_association *asoc,
+					struct sctp_chunk *chunk,
+					sctp_cmd_seq_t *commands,
+					struct sctp_association *new_asoc)
 {
 	/* The cookie should be silently discarded.
 	 * The endpoint SHOULD NOT change states and should leave
@@ -1528,13 +1530,13 @@ static sctp_disposition_t sctp_sf_do_dup
  */
 /* This case represents an initialization collision.  */
 static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
-				      const struct sctp_association *asoc,
-				      sctp_chunk_t *chunk,
-				      sctp_cmd_seq_t *commands,
-				      struct sctp_association *new_asoc)
+					const struct sctp_association *asoc,
+					struct sctp_chunk *chunk,
+					sctp_cmd_seq_t *commands,
+					struct sctp_association *new_asoc)
 {
 	struct sctp_ulpevent *ev = NULL;
-	sctp_chunk_t *repl;
+	struct sctp_chunk *repl;
 
 	/* Clarification from Implementor's Guide:
 	 * D) When both local and remote tags match the endpoint should
@@ -1610,16 +1612,16 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupc
 					sctp_cmd_seq_t *commands)
 {
 	sctp_disposition_t retval;
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	struct sctp_association *new_asoc;
 	int error = 0;
 	char action;
-	sctp_chunk_t *err_chk_p;
+	struct sctp_chunk *err_chk_p;
 
 	/* "Decode" the chunk.  We have no optional parameters so we
 	 * are in good shape.
 	 */
-        chunk->subh.cookie_hdr = (sctp_signed_cookie_t *)chunk->skb->data;
+        chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
 	skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
 		 sizeof(sctp_chunkhdr_t));
 
@@ -1708,7 +1710,7 @@ sctp_disposition_t sctp_sf_shutdown_pend
 	void *arg,
 	sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 
 	if (!sctp_vtag_verify_either(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -1731,7 +1733,7 @@ sctp_disposition_t sctp_sf_shutdown_sent
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 
 	if (!sctp_vtag_verify_either(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -1785,27 +1787,20 @@ sctp_disposition_t sctp_sf_cookie_echoed
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	sctp_errhdr_t *err;
 
-	err = (sctp_errhdr_t *)(chunk->skb->data);
-
-	/* If we have gotten too many failures, give up.  */
-	if (1 + asoc->counters[SCTP_COUNTER_INIT_ERROR] >
-					 asoc->max_init_attempts) {
-		/* INIT_FAILED will issue an ulpevent.  */
-		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-				SCTP_U32(err->cause));
-		return SCTP_DISPOSITION_DELETE_TCB;
-	}
-
 	/* Process the error here */
-	switch (err->cause) {
-	case SCTP_ERROR_STALE_COOKIE:
-		return sctp_sf_do_5_2_6_stale(ep, asoc, type, arg, commands);
-	default:
-		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+	/* FUTURE FIXME:  When PR-SCTP related and other optional
+	 * parms are emitted, this will have to change to handle multiple
+	 * errors.
+	 */
+	sctp_walk_errors(err, chunk->chunk_hdr) {
+		if (SCTP_ERROR_STALE_COOKIE == err->cause)
+			return sctp_sf_do_5_2_6_stale(ep, asoc, type, 
+							arg, commands);
 	}
+	return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 }
 
 /*
@@ -1839,14 +1834,14 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal
 					  void *arg,
 					  sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	time_t stale;
 	sctp_cookie_preserve_param_t bht;
 	sctp_errhdr_t *err;
 	struct list_head *pos;
 	struct sctp_transport *t;
-	sctp_chunk_t *reply;
-	sctp_bind_addr_t *bp;
+	struct sctp_chunk *reply;
+	struct sctp_bind_addr *bp;
 	int attempts;
 
 	attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
@@ -1874,14 +1869,14 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal
 	 * yield a higher probability of success on the reattempt.
 	 */
 	stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t)));
-	stale = stale << 1 / 1000;
+	stale = (stale * 2) / 1000;
 
 	bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE;
 	bht.param_hdr.length = htons(sizeof(bht));
 	bht.lifespan_increment = htonl(stale);
 
 	/* Build that new INIT chunk.  */
-	bp = (sctp_bind_addr_t *) &asoc->base.bind_addr;
+	bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
 	reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht));
 	if (!reply)
 		goto nomem;
@@ -1954,23 +1949,24 @@ sctp_disposition_t sctp_sf_do_9_1_abort(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
+	unsigned len;
 	__u16 error = SCTP_ERROR_NO_ERROR;
 
 	if (!sctp_vtag_verify_either(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
-	if (chunk && (ntohs(chunk->chunk_hdr->length) >=
-			(sizeof(struct sctp_chunkhdr) +
-			sizeof(struct sctp_errhdr))))
+	/* Check that chunk header looks valid.  */
+	len = ntohs(chunk->chunk_hdr->length);
+	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
+
  	/* ASSOC_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
 	SCTP_INC_STATS(SctpAborteds);
 	SCTP_DEC_STATS(SctpCurrEstab);
 
-	/* BUG?  This does not look complete... */
 	return SCTP_DISPOSITION_ABORT;
 }
 
@@ -1985,7 +1981,8 @@ sctp_disposition_t sctp_sf_cookie_wait_a
 				     void *arg,
 				     sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
+	unsigned len;
 	__u16 error = SCTP_ERROR_NO_ERROR;
 
 	if (!sctp_vtag_verify_either(chunk, asoc))
@@ -1997,9 +1994,9 @@ sctp_disposition_t sctp_sf_cookie_wait_a
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
 
-	if (chunk && (ntohs(chunk->chunk_hdr->length) >=
-			(sizeof(struct sctp_chunkhdr) +
-			sizeof(struct sctp_errhdr))))
+	/* Check that chunk header looks valid.  */
+	len = ntohs(chunk->chunk_hdr->length);
+	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
 	/* CMD_INIT_FAILED will DELETE_TCB. */
@@ -2064,9 +2061,10 @@ sctp_disposition_t sctp_sf_do_9_2_shutdo
 					   void *arg,
 					   sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	sctp_shutdownhdr_t *sdh;
 	sctp_disposition_t disposition;
+	struct sctp_ulpevent *ev;
 
 	/* Convert the elaborate header.  */
 	sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
@@ -2097,12 +2095,28 @@ sctp_disposition_t sctp_sf_do_9_2_shutdo
 							  arg, commands);
 	}
 
+	if (SCTP_DISPOSITION_NOMEM == disposition)
+		goto out;
+
 	/*  - verify, by checking the Cumulative TSN Ack field of the
 	 *    chunk, that all its outstanding DATA chunks have been
 	 *    received by the SHUTDOWN sender.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
 			SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack));
+
+	/* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
+	 * When a peer sends a SHUTDOWN, SCTP delivers this notification to
+	 * inform the application that it should cease sending data.
+	 */
+	ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
+	if (!ev) {
+		disposition = SCTP_DISPOSITION_NOMEM;
+		goto out;	
+	}
+	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+
+out:
 	return disposition;
 }
 
@@ -2119,8 +2133,8 @@ sctp_disposition_t sctp_sf_do_9_2_reshut
 				    void *arg,
 				    sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = (sctp_chunk_t *) arg;
-	sctp_chunk_t *reply;
+	struct sctp_chunk *chunk = (struct sctp_chunk *) arg;
+	struct sctp_chunk *reply;
 
 	reply = sctp_make_shutdown_ack(asoc, chunk);
 	if (NULL == reply)
@@ -2174,7 +2188,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(co
 				      sctp_cmd_seq_t *commands)
 {
 	sctp_cwrhdr_t *cwr;
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 
 	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
 	 * that the value in the Verification Tag field of the
@@ -2230,7 +2244,7 @@ sctp_disposition_t sctp_sf_do_ecne(const
 				   sctp_cmd_seq_t *commands)
 {
 	sctp_ecnehdr_t *ecne;
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 
 	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
 	 * that the value in the Verification Tag field of the
@@ -2287,9 +2301,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	sctp_datahdr_t *data_hdr;
-	sctp_chunk_t *err;
+	struct sctp_chunk *err;
 	size_t datalen;
 	sctp_verb_t deliver;
 	int tmp;
@@ -2311,9 +2325,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(
 	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
 
 	tsn = ntohl(data_hdr->tsn);
-
 	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
-	SCTP_DEBUG_PRINTK("eat_data: skb->head %p.\n", chunk->skb->head);
 
 	/* ASSERT:  Now skb->data is really the user data.  */
 
@@ -2328,9 +2340,13 @@ sctp_disposition_t sctp_sf_eat_data_6_2(
 	 */
 
 	if (!chunk->ecn_ce_done) {
+		struct sctp_af *af;
 		chunk->ecn_ce_done = 1;
-		if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) &&
-		    asoc->peer.ecn_capable) {
+
+		af = sctp_get_af_specific(
+			ipver2af(chunk->skb->nh.iph->version));
+
+		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
 			/* Do real work as sideffect. */
 			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
 					SCTP_U32(tsn));
@@ -2373,7 +2389,8 @@ sctp_disposition_t sctp_sf_eat_data_6_2(
 	 * PMTU.  In cases, such as loopback, this might be a rather
 	 * large spill over.
 	 */
-	if (asoc->rwnd_over || (datalen > asoc->rwnd + asoc->frag_point)) {
+	if (!asoc->rwnd || asoc->rwnd_over ||
+	    (datalen > asoc->rwnd + asoc->frag_point)) {
 
 		/* If this is the next TSN, consider reneging to make
 		 * room.   Note: Playing nice with a confused sender.  A
@@ -2545,9 +2562,9 @@ sctp_disposition_t sctp_sf_eat_data_fast
 				     void *arg,
 				     sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	sctp_datahdr_t *data_hdr;
-	sctp_chunk_t *err;
+	struct sctp_chunk *err;
 	size_t datalen;
 	int tmp;
 	__u32 tsn;
@@ -2583,9 +2600,13 @@ sctp_disposition_t sctp_sf_eat_data_fast
 	 * chunk later.
 	 */
 	if (!chunk->ecn_ce_done) {
+		struct sctp_af *af;
 		chunk->ecn_ce_done = 1;
-		if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) &&
-		    asoc->peer.ecn_capable) {
+
+		af = sctp_get_af_specific(
+			ipver2af(chunk->skb->nh.iph->version));
+
+		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
 			/* Do real work as sideffect. */
 			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
 					SCTP_U32(tsn));
@@ -2720,7 +2741,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	sctp_sackhdr_t *sackh;
 	__u32 ctsn;
 
@@ -2733,6 +2754,9 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(
 
 	/* Pull the SACK chunk from the data buffer */
 	sackh = sctp_sm_pull_sack(chunk);
+	/* Was this a bogus SACK? */
+	if (!sackh)
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 	chunk->subh.sack_hdr = sackh;
 	ctsn = ntohl(sackh->cum_tsn_ack);
 
@@ -2782,8 +2806,8 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(
 					sctp_cmd_seq_t *commands)
 {
 	struct sctp_packet *packet = NULL;
-	sctp_chunk_t *chunk = arg;
-	sctp_chunk_t *abort;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_chunk *abort;
 
 	packet = sctp_ootb_pkt_new(asoc, chunk);
 
@@ -2827,7 +2851,7 @@ sctp_disposition_t sctp_sf_operr_notify(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	struct sctp_ulpevent *ev;
 
 	while (chunk->chunk_end > chunk->skb->data) {
@@ -2841,6 +2865,9 @@ sctp_disposition_t sctp_sf_operr_notify(
 			sctp_ulpevent_free(ev);
 			goto nomem;
 		}
+
+		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
+				SCTP_CHUNK(chunk));	
 	}
 	return SCTP_DISPOSITION_CONSUME;
 
@@ -2864,8 +2891,8 @@ sctp_disposition_t sctp_sf_do_9_2_final(
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
-	sctp_chunk_t *reply;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_chunk *reply;
 	struct sctp_ulpevent *ev;
 
 	/* 10.2 H) SHUTDOWN COMPLETE notification
@@ -2932,7 +2959,7 @@ sctp_disposition_t sctp_sf_ootb(const st
 				void *arg,
 				sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 	struct sk_buff *skb = chunk->skb;
 	sctp_chunkhdr_t *ch;
 	__u8 *ch_end;
@@ -2984,8 +3011,8 @@ sctp_disposition_t sctp_sf_shut_8_4_5(co
 				      sctp_cmd_seq_t *commands)
 {
 	struct sctp_packet *packet = NULL;
-	sctp_chunk_t *chunk = arg;
-	sctp_chunk_t *shut;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_chunk *shut;
 
 	packet = sctp_ootb_pkt_new(asoc, chunk);
 
@@ -3040,6 +3067,143 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa
 	return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands);
 }
 
+/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.  */
+sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
+				     const struct sctp_association *asoc,
+				     const sctp_subtype_t type, void *arg,
+				     sctp_cmd_seq_t *commands)
+{
+	struct sctp_chunk	*chunk = arg;
+	struct sctp_chunk	*asconf_ack = NULL;
+	sctp_addiphdr_t		*hdr;
+	__u32			serial;
+
+	hdr = (sctp_addiphdr_t *)chunk->skb->data;
+	serial = ntohl(hdr->serial);
+
+	/* ADDIP 4.2 C1) Compare the value of the serial number to the value
+	 * the endpoint stored in a new association variable
+	 * 'Peer-Serial-Number'. 
+	 */
+	if (serial == asoc->peer.addip_serial + 1) {
+   		/* ADDIP 4.2 C2) If the value found in the serial number is
+		 * equal to the ('Peer-Serial-Number' + 1), the endpoint MUST
+		 * do V1-V5.
+		 */
+		asconf_ack = sctp_process_asconf((struct sctp_association *)
+						 asoc, chunk);
+		if (!asconf_ack)
+			return SCTP_DISPOSITION_NOMEM;
+	} else if (serial == asoc->peer.addip_serial) {
+		/* ADDIP 4.2 C3) If the value found in the serial number is
+		 * equal to the value stored in the 'Peer-Serial-Number'
+		 * IMPLEMENTATION NOTE: As an optimization a receiver may wish
+		 * to save the last ASCONF-ACK for some predetermined period of 		 * time and instead of re-processing the ASCONF (with the same
+		 * serial number) it may just re-transmit the ASCONF-ACK.
+		 */
+		if (asoc->addip_last_asconf_ack)
+			asconf_ack = asoc->addip_last_asconf_ack;
+		else
+			return SCTP_DISPOSITION_DISCARD;
+	} else {
+		/* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since 
+		 * it must be either a stale packet or from an attacker.
+		 */	
+		return SCTP_DISPOSITION_DISCARD;
+	}
+
+	/* ADDIP 4.2 C5) In both cases C2 and C3 the ASCONF-ACK MUST be sent
+	 * back to the source address contained in the IP header of the ASCONF
+	 * being responded to.
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack));
+	
+	return SCTP_DISPOSITION_CONSUME;
+}
+
+/*
+ * ADDIP Section 4.3 General rules for address manipulation
+ * When building TLV parameters for the ASCONF Chunk that will add or
+ * delete IP addresses the D0 to D13 rules should be applied:
+ */
+sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
+					 const struct sctp_association *asoc,
+	 				 const sctp_subtype_t type, void *arg,
+					 sctp_cmd_seq_t *commands)
+{
+	struct sctp_chunk	*asconf_ack = arg;
+	struct sctp_chunk	*last_asconf = asoc->addip_last_asconf;
+	struct sctp_chunk	*abort;
+	sctp_addiphdr_t		*addip_hdr;
+	__u32			sent_serial, rcvd_serial;
+
+	addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data;
+	rcvd_serial = ntohl(addip_hdr->serial);
+
+	if (last_asconf) {
+		addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
+		sent_serial = ntohl(addip_hdr->serial);
+	} else {
+		sent_serial = asoc->addip_serial - 1;
+	}
+
+	/* D0) If an endpoint receives an ASCONF-ACK that is greater than or
+	 * equal to the next serial number to be used but no ASCONF chunk is
+	 * outstanding the endpoint MUST ABORT the association. Note that a
+	 * sequence number is greater than if it is no more than 2^^31-1
+	 * larger than the current sequence number (using serial arithmetic).
+	 */
+	if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) &&
+	    !(asoc->addip_last_asconf)) {
+		abort = sctp_make_abort(asoc, asconf_ack,
+					sizeof(sctp_errhdr_t));
+		if (abort) {
+			sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, NULL, 0);
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(abort));
+		}
+		/* We are going to ABORT, so we might as well stop
+		 * processing the rest of the chunks in the packet.
+		 */
+		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+				SCTP_U32(SCTP_ERROR_ASCONF_ACK));
+		SCTP_INC_STATS(SctpAborteds);
+		SCTP_DEC_STATS(SctpCurrEstab);
+		return SCTP_DISPOSITION_ABORT;
+	}
+
+	if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+
+		if (!sctp_process_asconf_ack((struct sctp_association *)asoc,
+					     asconf_ack))
+			return SCTP_DISPOSITION_CONSUME;
+
+		abort = sctp_make_abort(asoc, asconf_ack,
+					sizeof(sctp_errhdr_t));
+		if (abort) {
+			sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, NULL, 0);
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(abort));
+		}
+		/* We are going to ABORT, so we might as well stop
+		 * processing the rest of the chunks in the packet.
+		 */
+		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+				SCTP_U32(SCTP_ERROR_ASCONF_ACK));
+		SCTP_INC_STATS(SctpAborteds);
+		SCTP_DEC_STATS(SctpCurrEstab);
+		return SCTP_DISPOSITION_ABORT;
+	}
+
+	return SCTP_DISPOSITION_DISCARD;
+}
+
 /*
  * Process an unknown chunk.
  *
@@ -3069,8 +3233,8 @@ sctp_disposition_t sctp_sf_unk_chunk(con
 				     void *arg,
 				     sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *unk_chunk = arg;
-	sctp_chunk_t *err_chunk;
+	struct sctp_chunk *unk_chunk = arg;
+	struct sctp_chunk *err_chunk;
 	sctp_chunkhdr_t *hdr;
 
 	SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk);
@@ -3182,82 +3346,6 @@ sctp_disposition_t sctp_sf_pdiscard(cons
 	return SCTP_DISPOSITION_CONSUME;
 }
 
-#if 0
-/*
- * We did something stupid but got lucky.  Namely, we sent a HEARTBEAT
- * before the association was all the way up and we did NOT get an
- * ABORT.
- *
- * Log the fact and then process normally.
- *
- * Section: Not specified
- * Verification Tag:  8.5 Verification Tag [Normal verification]
- * Inputs
- * (endpoint, asoc, chunk)
- *
- * Outputs
- * (asoc, reply_msg, msg_up, timers, counters)
- *
- * The return value is the disposition of the chunk.
- */
-sctp_disposition_t lucky(const struct sctp_endpoint *ep,
-			 const struct sctp_association *asoc,
-			 const sctp_subtype_t type,
-			 void *arg,
-			 sctp_cmd_seq_t *commands)
-{
-	sctp_chunk_t *chunk = arg;
-
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. ...
-	 */
-	if (chunk->sctp_hdr->vtag != asoc->c.my_vtag)
-		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
-	return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-	return SCTP_DISPOSITION_NOMEM;
-}
-#endif /* 0 */
-
-#if 0
-/*
- * The other end is doing something very stupid.  We'll ignore them
- * after logging their idiocy. :-)
- *
- * Section: Not specified
- * Verification Tag:  8.5 Verification Tag [Normal verification]
- * Inputs
- * (endpoint, asoc, chunk)
- *
- * Outputs
- * (asoc, reply_msg, msg_up, timers, counters)
- *
- * The return value is the disposition of the chunk.
- */
-sctp_disposition_t other_stupid(const struct sctp_endpoint *ep,
-				const struct sctp_association *asoc,
-				const sctp_subtype_t type,
-				void *arg,
-				sctp_cmd_seq_t *commands)
-{
-	sctp_chunk_t *chunk = arg;
-
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. ...
-	 */
-	if (chunk->sctp_hdr->vtag != asoc->c.my_vtag)
-		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
-	return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-	return SCTP_DISPOSITION_NOMEM;
-}
-#endif /* 0 */
 
 /*
  * The other end is violating protocol.
@@ -3348,7 +3436,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(c
 				       void *arg,
 				       sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *repl;
+	struct sctp_chunk *repl;
 
 	/* The comment below says that we enter COOKIE-WAIT AFTER
 	 * sending the INIT, but that doesn't actually work in our
@@ -3454,7 +3542,7 @@ sctp_disposition_t sctp_sf_do_prm_send(c
 				       void *arg,
 				       sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = arg;
+	struct sctp_chunk *chunk = arg;
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk));
 	return SCTP_DISPOSITION_CONSUME;
@@ -3564,7 +3652,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_ab
 	 * if necessary to fill gaps.
 	 */
 	struct msghdr *msg = arg;
-	sctp_chunk_t *abort;
+	struct sctp_chunk *abort;
 	sctp_disposition_t retval;
 
 	retval = SCTP_DISPOSITION_CONSUME;
@@ -3697,7 +3785,7 @@ sctp_disposition_t sctp_sf_cookie_wait_p
 	sctp_cmd_seq_t *commands)
 {
 	struct msghdr *msg = arg;
-	sctp_chunk_t *abort;
+	struct sctp_chunk *abort;
 	sctp_disposition_t retval;
 
 	/* Stop T1-init timer */
@@ -3870,6 +3958,26 @@ sctp_disposition_t sctp_sf_do_prm_reques
 }
 
 /*
+ * ADDIP Section 4.1 ASCONF Chunk Procedures
+ * When an endpoint has an ASCONF signaled change to be sent to the
+ * remote endpoint it should do A1 to A9
+ */
+sctp_disposition_t sctp_sf_do_prm_asconf(const struct sctp_endpoint *ep,
+					const struct sctp_association *asoc,
+					const sctp_subtype_t type,
+					void *arg,
+					sctp_cmd_seq_t *commands)
+{
+	struct sctp_chunk *chunk = arg;
+
+	sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk));
+	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
+			SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk));
+	return SCTP_DISPOSITION_CONSUME;
+}
+
+/*
  * Ignore the primitive event
  *
  * The return value is the disposition of the primitive.
@@ -3909,14 +4017,14 @@ sctp_disposition_t sctp_sf_do_9_2_start_
 	void *arg,
 	sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *reply;
+	struct sctp_chunk *reply;
 
 	/* Once all its outstanding data has been acknowledged, the
 	 * endpoint shall send a SHUTDOWN chunk to its peer including
 	 * in the Cumulative TSN Ack field the last sequential TSN it
 	 * has received from the peer.
 	 */
-	reply = sctp_make_shutdown(asoc);
+	reply = sctp_make_shutdown(asoc, NULL);
 	if (!reply)
 		goto nomem;
 
@@ -3971,8 +4079,8 @@ sctp_disposition_t sctp_sf_do_9_2_shutdo
 	void *arg,
 	sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *chunk = (sctp_chunk_t *) arg;
-	sctp_chunk_t *reply;
+	struct sctp_chunk *chunk = (struct sctp_chunk *) arg;
+	struct sctp_chunk *reply;
 
 	/* If it has no more outstanding DATA chunks, the SHUTDOWN receiver
 	 * shall send a SHUTDOWN ACK ...
@@ -4051,7 +4159,7 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(
 {
 	struct sctp_transport *transport = arg;
 
-	if (asoc->overall_error_count >= asoc->overall_error_threshold) {
+	if (asoc->overall_error_count >= asoc->max_retrans) {
 		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -4152,8 +4260,8 @@ sctp_disposition_t sctp_sf_t1_timer_expi
 					   void *arg,
 					   sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *repl;
-	sctp_bind_addr_t *bp;
+	struct sctp_chunk *repl;
+	struct sctp_bind_addr *bp;
 	sctp_event_timeout_t timer = (sctp_event_timeout_t) arg;
 	int timeout;
 	int attempts;
@@ -4164,11 +4272,10 @@ sctp_disposition_t sctp_sf_t1_timer_expi
 
 	SCTP_DEBUG_PRINTK("Timer T1 expired.\n");
 
-	if ((timeout < asoc->max_init_timeo) &&
-	    (attempts < asoc->max_init_attempts)) {
+	if (attempts < asoc->max_init_attempts) {
 		switch (timer) {
 		case SCTP_EVENT_TIMEOUT_T1_INIT:
-			bp = (sctp_bind_addr_t *) &asoc->base.bind_addr;
+			bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
 			repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
 			break;
 
@@ -4219,10 +4326,10 @@ sctp_disposition_t sctp_sf_t2_timer_expi
 					   void *arg,
 					   sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *reply = NULL;
+	struct sctp_chunk *reply = NULL;
 
 	SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
-	if (asoc->overall_error_count >= asoc->overall_error_threshold) {
+	if (asoc->overall_error_count >= asoc->max_retrans) {
 		/* Note:  CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -4233,7 +4340,7 @@ sctp_disposition_t sctp_sf_t2_timer_expi
 
 	switch (asoc->state) {
 	case SCTP_STATE_SHUTDOWN_SENT:
-		reply = sctp_make_shutdown(asoc);
+		reply = sctp_make_shutdown(asoc, NULL);
 		break;
 
 	case SCTP_STATE_SHUTDOWN_ACK_SENT:
@@ -4267,6 +4374,69 @@ nomem:
 	return SCTP_DISPOSITION_NOMEM;
 }
 
+/*
+ * ADDIP Section 4.1 ASCONF CHunk Procedures
+ * If the T4 RTO timer expires the endpoint should do B1 to B5
+ */
+sctp_disposition_t sctp_sf_t4_timer_expire(
+	const struct sctp_endpoint *ep,
+	const struct sctp_association *asoc,
+	const sctp_subtype_t type,
+	void *arg,
+	sctp_cmd_seq_t *commands)
+{
+	struct sctp_chunk *chunk = asoc->addip_last_asconf;
+	struct sctp_transport *transport = chunk->transport;
+
+	/* ADDIP 4.1 B1) Increment the error counters and perform path failure
+	 * detection on the appropriate destination address as defined in
+	 * RFC2960 [5] section 8.1 and 8.2.
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport));
+
+	/* Reconfig T4 timer and transport. */
+	sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk));
+
+	/* ADDIP 4.1 B2) Increment the association error counters and perform
+	 * endpoint failure detection on the association as defined in
+	 * RFC2960 [5] section 8.1 and 8.2.
+	 * association error counter is incremented in SCTP_CMD_STRIKE.
+	 */
+	if (asoc->overall_error_count >= asoc->max_retrans) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+				SCTP_U32(SCTP_ERROR_NO_ERROR));
+		SCTP_INC_STATS(SctpAborteds);
+		SCTP_INC_STATS(SctpCurrEstab);
+		return SCTP_DISPOSITION_ABORT;
+	}
+
+	/* ADDIP 4.1 B3) Back-off the destination address RTO value to which
+	 * the ASCONF chunk was sent by doubling the RTO timer value.
+	 * This is done in SCTP_CMD_STRIKE.
+	 */
+
+	/* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible
+	 * choose an alternate destination address (please refer to RFC2960
+	 * [5] section 6.4.1). An endpoint MUST NOT add new parameters to this
+	 * chunk, it MUST be the same (including its serial number) as the last 
+	 * ASCONF sent.
+	 */
+	sctp_chunk_hold(asoc->addip_last_asconf);
+	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+			SCTP_CHUNK(asoc->addip_last_asconf));
+
+	/* ADDIP 4.1 B5) Restart the T-4 RTO timer. Note that if a different
+	 * destination is selected, then the RTO used will be that of the new
+	 * destination address.
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
+			SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+
+	return SCTP_DISPOSITION_CONSUME;
+}
+
 /* sctpimpguide-05 Section 2.12.2
  * The sender of the SHUTDOWN MAY also start an overall guard timer
  * 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
@@ -4279,7 +4449,7 @@ sctp_disposition_t sctp_sf_t5_timer_expi
 					   void *arg,
 					   sctp_cmd_seq_t *commands)
 {
-	sctp_chunk_t *reply = NULL;
+	struct sctp_chunk *reply = NULL;
 
 	SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
 
@@ -4399,22 +4569,27 @@ sctp_disposition_t sctp_sf_timer_ignore(
  ********************************************************************/
 
 /* Pull the SACK chunk based on the SACK header. */
-sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *chunk)
+struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
 {
-	sctp_sackhdr_t *sack;
+	struct sctp_sackhdr *sack;
+	unsigned int len;
 	__u16 num_blocks;
 	__u16 num_dup_tsns;
 
-	/* FIXME:  Protect ourselves from reading too far into
+	/* Protect ourselves from reading too far into
 	 * the skb from a bogus sender.
 	 */
-	sack = (sctp_sackhdr_t *) chunk->skb->data;
-	skb_pull(chunk->skb, sizeof(sctp_sackhdr_t));
+	sack = (struct sctp_sackhdr *) chunk->skb->data;
 
 	num_blocks = ntohs(sack->num_gap_ack_blocks);
 	num_dup_tsns = ntohs(sack->num_dup_tsns);
+	len = sizeof(struct sctp_sackhdr);
+	len = (num_blocks + num_dup_tsns) * sizeof(__u32);
+	if (len > chunk->skb->len)
+		return NULL;
+
+	skb_pull(chunk->skb, len);
 
-	skb_pull(chunk->skb, (num_blocks + num_dup_tsns) * sizeof(__u32));
 	return sack;
 }
 
@@ -4423,12 +4598,12 @@ sctp_sackhdr_t *sctp_sm_pull_sack(sctp_c
  */
 struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
 				  const struct sctp_association *asoc,
-				  sctp_chunk_t *chunk,
+				  struct sctp_chunk *chunk,
 				  const void *payload,
 				  size_t paylen)
 {
 	struct sctp_packet *packet;
-	sctp_chunk_t *abort;
+	struct sctp_chunk *abort;
 
 	packet = sctp_ootb_pkt_new(asoc, chunk);
 
@@ -4458,7 +4633,7 @@ struct sctp_packet *sctp_abort_pkt_new(c
 
 /* Allocate a packet for responding in the OOTB conditions.  */
 struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
-				 const sctp_chunk_t *chunk)
+				 const struct sctp_chunk *chunk)
 {
 	struct sctp_packet *packet;
 	struct sctp_transport *transport;
@@ -4476,13 +4651,21 @@ struct sctp_packet *sctp_ootb_pkt_new(co
 	if (asoc) {
 		vtag = asoc->peer.i.init_tag;
 	} else {
-		/* Special case the INIT as there is no vtag yet. */
-		if (SCTP_CID_INIT == chunk->chunk_hdr->type) {
+		/* Special case the INIT and stale COOKIE_ECHO as there is no
+		 * vtag yet.
+		 */
+		switch(chunk->chunk_hdr->type) {
+		case SCTP_CID_INIT:
+		{
 			sctp_init_chunk_t *init;
+
 			init = (sctp_init_chunk_t *)chunk->chunk_hdr;
 			vtag = ntohl(init->init_hdr.init_tag);
-		} else {
+			break;
+		}
+		default:	
 			vtag = ntohl(chunk->sctp_hdr->vtag);
+			break;
 		}
 	}
 
@@ -4524,15 +4707,21 @@ void sctp_ootb_pkt_free(struct sctp_pack
 /* Send a stale cookie error when a invalid COOKIE ECHO chunk is found  */
 void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
 				const struct sctp_association *asoc,
-				const sctp_chunk_t *chunk,
+				const struct sctp_chunk *chunk,
 				sctp_cmd_seq_t *commands,
-				sctp_chunk_t *err_chunk)
+				struct sctp_chunk *err_chunk)
 {
 	struct sctp_packet *packet;
 
 	if (err_chunk) {
 		packet = sctp_ootb_pkt_new(asoc, chunk);
 		if (packet) {
+			struct sctp_signed_cookie *cookie;
+
+			/* Override the OOTB vtag from the cookie. */
+			cookie = chunk->subh.cookie_hdr;
+			packet->vtag = cookie->c.peer_vtag;
+			
 			/* Set the skb to the belonging sock for accounting. */
 			err_chunk->skb->sk = ep->base.sk;
 			sctp_packet_append_chunk(packet, err_chunk);
@@ -4540,6 +4729,6 @@ void sctp_send_stale_cookie_err(const st
 					SCTP_PACKET(packet));
 			SCTP_INC_STATS(SctpOutCtrlChunks);
 		} else
-			sctp_free_chunk (err_chunk);
+			sctp_chunk_free (err_chunk);
 	}
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_statetable.c linux-2.4.26-pre6/net/sctp/sm_statetable.c
--- linux-2.4.25/net/sctp/sm_statetable.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/sm_statetable.c	2004-03-25 00:20:41.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  *
@@ -49,7 +49,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
-static sctp_sm_table_entry_t bug = {
+static const sctp_sm_table_entry_t bug = {
 	.fn = sctp_sf_bug, 
 	.name = "sctp_sf_bug"
 };
@@ -64,9 +64,9 @@ static sctp_sm_table_entry_t bug = {
 	} \
 	return &_table[event_subtype._type][(int)state];
 
-sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
-					    sctp_state_t state,
-					    sctp_subtype_t event_subtype)
+const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
+						  sctp_state_t state,
+						  sctp_subtype_t event_subtype)
 {
 	switch (event_type) {
 	case SCTP_EVENT_T_CHUNK:
@@ -418,7 +418,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_ev
  *
  * For base protocol (RFC 2960).
  */
-sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
 	TYPE_SCTP_DATA,
 	TYPE_SCTP_INIT,
 	TYPE_SCTP_INIT_ACK,
@@ -436,53 +436,57 @@ sctp_sm_table_entry_t chunk_event_table[
 	TYPE_SCTP_SHUTDOWN_COMPLETE,
 }; /* state_fn_t chunk_event_table[][] */
 
-static sctp_sm_table_entry_t
-chunk_event_table_asconf[SCTP_STATE_NUM_STATES] = {
-	/* SCTP_STATE_EMPTY */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_CLOSED */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_COOKIE_WAIT */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_COOKIE_ECHOED */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_ESTABLISHED */
-	{.fn = sctp_sf_discard_chunk,
-	 .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"},
-	/* SCTP_STATE_SHUTDOWN_PENDING */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_SHUTDOWN_SENT */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_SHUTDOWN_RECEIVED */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_SHUTDOWN_ACK_SENT */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-};	/* chunk asconf */
+#define TYPE_SCTP_ASCONF { \
+	/* SCTP_STATE_EMPTY */ \
+	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+	/* SCTP_STATE_CLOSED */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_COOKIE_WAIT */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_COOKIE_ECHOED */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_ESTABLISHED */ \
+	{.fn = sctp_sf_do_asconf, .name = "sctp_sf_do_asconf"}, \
+	/* SCTP_STATE_SHUTDOWN_PENDING */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_SHUTDOWN_SENT */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+} /* TYPE_SCTP_ASCONF */
 
-static sctp_sm_table_entry_t
-chunk_event_table_asconf_ack[SCTP_STATE_NUM_STATES] = {
-	/* SCTP_STATE_EMPTY */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_CLOSED */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_COOKIE_WAIT */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_COOKIE_ECHOED */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_ESTABLISHED */
-	{.fn = sctp_sf_discard_chunk,
-	 .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"},
-	/* SCTP_STATE_SHUTDOWN_PENDING */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_SHUTDOWN_SENT */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_SHUTDOWN_RECEIVED */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-	/* SCTP_STATE_SHUTDOWN_ACK_SENT */
-	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
-};	/* chunk asconf_ack */
+#define TYPE_SCTP_ASCONF_ACK { \
+	/* SCTP_STATE_EMPTY */ \
+	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+	/* SCTP_STATE_CLOSED */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_COOKIE_WAIT */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_COOKIE_ECHOED */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_ESTABLISHED */ \
+	{.fn = sctp_sf_do_asconf_ack, .name = "sctp_sf_do_asconf_ack"}, \
+	/* SCTP_STATE_SHUTDOWN_PENDING */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_SHUTDOWN_SENT */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+} /* TYPE_SCTP_ASCONF_ACK */
+
+/* The primary index for this table is the chunk type.
+ * The secondary index for this table is the state.
+ */
+const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+	TYPE_SCTP_ASCONF,
+	TYPE_SCTP_ASCONF_ACK,
+}; /*state_fn_t addip_chunk_event_table[][] */
 
-static sctp_sm_table_entry_t
+static const sctp_sm_table_entry_t
 chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
 	/* SCTP_STATE_EMPTY */
 	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"},
@@ -627,16 +631,37 @@ chunk_event_table_unknown[SCTP_STATE_NUM
 	 .name = "sctp_sf_do_prm_requestheartbeat"},          \
 } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
 
+#define TYPE_SCTP_PRIMITIVE_ASCONF { \
+	/* SCTP_STATE_EMPTY */ \
+	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	/* SCTP_STATE_CLOSED */ \
+	{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+	/* SCTP_STATE_COOKIE_WAIT */ \
+	{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+	/* SCTP_STATE_COOKIE_ECHOED */ \
+	{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+	/* SCTP_STATE_ESTABLISHED */ \
+	{.fn = sctp_sf_do_prm_asconf, .name = "sctp_sf_do_prm_asconf"}, \
+	/* SCTP_STATE_SHUTDOWN_PENDING */ \
+	{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+	/* SCTP_STATE_SHUTDOWN_SENT */ \
+	{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+	{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+	{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
+} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
 
 /* The primary index for this table is the primitive type.
  * The secondary index for this table is the state.
  */
-sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
+const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
 	TYPE_SCTP_PRIMITIVE_ASSOCIATE,
 	TYPE_SCTP_PRIMITIVE_SHUTDOWN,
 	TYPE_SCTP_PRIMITIVE_ABORT,
 	TYPE_SCTP_PRIMITIVE_SEND,
 	TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT,
+	TYPE_SCTP_PRIMITIVE_ASCONF,
 };
 
 #define TYPE_SCTP_OTHER_NO_PENDING_TSN  { \
@@ -662,7 +687,7 @@ sctp_sm_table_entry_t primitive_event_ta
 	{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
 }
 
-sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
+const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
 	TYPE_SCTP_OTHER_NO_PENDING_TSN,
 };
 
@@ -771,6 +796,27 @@ sctp_sm_table_entry_t other_event_table[
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 }
 
+#define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \
+	/* SCTP_STATE_EMPTY */ \
+	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	/* SCTP_STATE_CLOSED */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	/* SCTP_STATE_COOKIE_WAIT */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	/* SCTP_STATE_COOKIE_ECHOED */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	/* SCTP_STATE_ESTABLISHED */ \
+	{.fn = sctp_sf_t4_timer_expire, .name = "sctp_sf_t4_timer_expire"}, \
+	/* SCTP_STATE_SHUTDOWN_PENDING */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	/* SCTP_STATE_SHUTDOWN_SENT */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+}
+
 #define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \
 	/* SCTP_STATE_EMPTY */ \
 	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
@@ -783,7 +829,7 @@ sctp_sm_table_entry_t other_event_table[
 	/* SCTP_STATE_ESTABLISHED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_SHUTDOWN_PENDING */ \
-	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
+	{.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \
 	/* SCTP_STATE_SHUTDOWN_SENT */ \
 	{.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \
 	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
@@ -856,34 +902,35 @@ sctp_sm_table_entry_t other_event_table[
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 }
 
-sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
+const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
 	TYPE_SCTP_EVENT_TIMEOUT_NONE,
 	TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE,
 	TYPE_SCTP_EVENT_TIMEOUT_T1_INIT,
 	TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
 	TYPE_SCTP_EVENT_TIMEOUT_T3_RTX,
+	TYPE_SCTP_EVENT_TIMEOUT_T4_RTO,
 	TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
 	TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT,
 	TYPE_SCTP_EVENT_TIMEOUT_SACK,
 	TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
 };
 
-sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, sctp_state_t state)
+const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, 
+						     sctp_state_t state)
 {
 	if (state > SCTP_STATE_MAX)
 		return &bug;
 
-	if (cid >= 0 && cid <= SCTP_CID_BASE_MAX) {
+	if (cid >= 0 && cid <= SCTP_CID_BASE_MAX)
 		return &chunk_event_table[cid][state];
-	}
 
-	switch (cid) {
-	case SCTP_CID_ASCONF:
-		return &chunk_event_table_asconf[state];
+	if (sctp_addip_enable) {
+		if (cid == SCTP_CID_ASCONF)
+			return &addip_chunk_event_table[0][state];
 
-	case SCTP_CID_ASCONF_ACK:
-		return &chunk_event_table_asconf_ack[state];
-	default:
-		return &chunk_event_table_unknown[state];
+		if (cid == SCTP_CID_ASCONF_ACK)
+			return &addip_chunk_event_table[1][state];
 	}
+
+	return &chunk_event_table_unknown[state];
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/socket.c linux-2.4.26-pre6/net/sctp/socket.c
--- linux-2.4.25/net/sctp/socket.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/socket.c	2004-03-25 00:18:01.000000000 +0000
@@ -1,6 +1,7 @@
-/* Copyright (c) 1999-2000 Cisco, Inc.
+/* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
+ * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 International Business Machines, Corp.
  * Copyright (c) 2001-2003 Intel Corp.
  * Copyright (c) 2001-2002 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -48,6 +49,9 @@
  *    Sridhar Samudrala     <samudrala@us.ibm.com>
  *    Inaky Perez-Gonzalez  <inaky.gonzalez@intel.com>
  *    Ardelle Fan	    <ardelle.fan@intel.com>
+ *    Ryan Layer	    <rmlayer@us.ibm.com>
+ *    Anup Pemmaiah         <pemmaiah@cc.usu.edu>
+ *    Kevin Gao             <kevin.gao@intel.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -62,6 +66,7 @@
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/crypto.h>
 
 #include <net/ip.h>
 #include <net/icmp.h>
@@ -82,22 +87,30 @@
 /* Forward declarations for internal helper functions. */
 static int sctp_writeable(struct sock *sk);
 static inline int sctp_wspace(struct sctp_association *asoc);
-static inline void sctp_set_owner_w(sctp_chunk_t *chunk);
+static inline void sctp_set_owner_w(struct sctp_chunk *chunk);
 static void sctp_wfree(struct sk_buff *skb);
 static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p,
-				int msg_len);
+				size_t msg_len);
 static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p);
 static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
 static int sctp_wait_for_accept(struct sock *sk, long timeo);
+static void sctp_wait_for_close(struct sock *sk, long timeo);
 static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int);
-static int sctp_bindx_add(struct sock *, struct sockaddr_storage *, int);
-static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int);
+static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
+static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
+static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
+static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);
+static int sctp_send_asconf(struct sctp_association *asoc,
+			    struct sctp_chunk *chunk);
 static int sctp_do_bind(struct sock *, union sctp_addr *, int);
 static int sctp_autobind(struct sock *sk);
 static void sctp_sock_migrate(struct sock *, struct sock *,
 			      struct sctp_association *, sctp_socket_type_t);
 static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
 
+extern kmem_cache_t *sctp_bucket_cachep;
+extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc);
+
 /* Look up the association by its id.  If this is not a UDP-style
  * socket, the ID field is always ignored.
  */
@@ -105,32 +118,61 @@ struct sctp_association *sctp_id2assoc(s
 {
 	struct sctp_association *asoc = NULL;
 
-	/* If this is not a UDP-style socket, assoc id should be
-	 * ignored.
-	 */
-	if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) {
+	/* If this is not a UDP-style socket, assoc id should be ignored. */
+	if (!sctp_style(sk, UDP)) {
+		/* Return NULL if the socket state is not ESTABLISHED. It
+		 * could be a TCP-style listening socket or a socket which
+		 * hasn't yet called connect() to establish an association.
+		 */
+		if (!sctp_sstate(sk, ESTABLISHED))
+			return NULL;
+
+		/* Get the first and the only association from the list. */
 		if (!list_empty(&sctp_sk(sk)->ep->asocs))
 			asoc = list_entry(sctp_sk(sk)->ep->asocs.next,
 					  struct sctp_association, asocs);
 		return asoc;
 	}
 
-	/* First, verify that this is a kernel address. */
-	if (sctp_is_valid_kaddr((unsigned long) id)) {
-		struct sctp_association *temp;
-
-		/* Verify that this _is_ an sctp_association
-		 * data structure and if so, that the socket matches.
-		 */
-		temp = (struct sctp_association *)id;
-		if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) &&
-		    (temp->base.sk == sk))
-			asoc = temp;
-	}
+	/* Otherwise this is a UDP-style socket. */
+	asoc = (struct sctp_association *)id;
+	if (!sctp_assoc_valid(sk, asoc))
+		return NULL;
 
 	return asoc;
 }
 
+/* Look up the transport from an address and an assoc id. If both address and
+ * id are specified, the associations matching the address and the id should be
+ * the same.
+ */
+struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
+					      struct sockaddr_storage *addr,
+					      sctp_assoc_t id)
+{
+	struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
+	struct sctp_transport *transport;
+	union sctp_addr *laddr = (union sctp_addr *)addr;
+
+	laddr->v4.sin_port = ntohs(laddr->v4.sin_port);
+	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
+					       (union sctp_addr *)addr,
+					       &transport);
+	laddr->v4.sin_port = htons(laddr->v4.sin_port);
+
+	if (!addr_asoc)
+		return NULL;
+
+	id_asoc = sctp_id2assoc(sk, id);
+	if (id_asoc && (id_asoc != addr_asoc))
+		return NULL;
+
+	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
+						(union sctp_addr *)addr);
+
+	return transport;
+}
+
 /* API 3.1.2 bind() - UDP Style Syntax
  * The syntax of bind() is,
  *
@@ -139,10 +181,7 @@ struct sctp_association *sctp_id2assoc(s
  *   sd      - the socket descriptor returned by socket().
  *   addr    - the address structure (struct sockaddr_in or struct
  *             sockaddr_in6 [RFC 2553]),
- *   addrlen - the size of the address structure.
- *
- * The caller should use struct sockaddr_storage described in RFC 2553
- * to represent addr for portability reason.
+ *   addr_len - the size of the address structure.
  */
 int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
@@ -178,7 +217,7 @@ static struct sctp_af *sctp_sockaddr_af(
 		return NULL;
 
 	/* Does this PF support this AF? */
-	if (!opt->pf->af_supported(addr->sa.sa_family))
+	if (!opt->pf->af_supported(addr->sa.sa_family, opt))
 		return NULL;
 
 	/* If we get this far, af is valid. */
@@ -195,7 +234,7 @@ SCTP_STATIC int sctp_do_bind(struct sock
 {
 	struct sctp_opt *sp = sctp_sk(sk);
 	struct sctp_endpoint *ep = sp->ep;
-	sctp_bind_addr_t *bp = &ep->base.bind_addr;
+	struct sctp_bind_addr *bp = &ep->base.bind_addr;
 	struct sctp_af *af;
 	unsigned short snum;
 	int ret = 0;
@@ -243,7 +282,7 @@ SCTP_STATIC int sctp_do_bind(struct sock
 
 	/* Refresh ephemeral port.  */
 	if (!snum)
-		snum = (sk)->num;
+		snum = sk->num;
 
 	/* Add the address to the bind address list.  */
 	sctp_local_bh_disable();
@@ -260,116 +299,45 @@ SCTP_STATIC int sctp_do_bind(struct sock
 
 	/* Copy back into socket for getsockname() use. */
 	if (!ret) {
-		(sk)->sport = htons((sk)->num);
+		sk->sport = htons(sk->num);
 		af->to_sk_saddr(addr, sk);
 	}
 
 	return ret;
 }
 
-/* API 8.1 sctp_bindx()
- *
- * The syntax of sctp_bindx() is,
- *
- *   ret = sctp_bindx(int sd,
- *                    struct sockaddr_storage *addrs,
- * 		      int addrcnt,
- * 		      int flags);
- *
- * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
- * If the sd is an IPv6 socket, the addresses passed can either be IPv4
- * or IPv6 addresses.
- *
- * A single address may be specified as INADDR_ANY or IPV6_ADDR_ANY, see
- * section 3.1.2 for this usage.
- *
- * addrs is a pointer to an array of one or more socket addresses.  Each
- * address is contained in a struct sockaddr_storage, so each address is
- * fixed length. The caller specifies the number of addresses in the
- * array with addrcnt.
- *
- * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns -1,
- * and sets errno to the appropriate error code. [ Editor's note: need
- * to fill in all error code? ]
- *
- * For SCTP, the port given in each socket address must be the same, or
- * sctp_bindx() will fail, setting errno to EINVAL .
- *
- * The flags parameter is formed from the bitwise OR of zero or
- * more of the following currently defined flags:
- *
- *     SCTP_BINDX_ADD_ADDR
- *     SCTP_BINDX_REM_ADDR
- *
- * SCTP_BIND_ADD_ADDR directs SCTP to add the given addresses to the
- * association, and SCTP_BIND_REM_ADDR directs SCTP to remove the given
- * addresses from the association. The two flags are mutually exclusive;
- * if both are given, sctp_bindx() will fail with EINVAL.  A caller may not
- * remove all addresses from an association; sctp_bindx() will reject such
- * an attempt with EINVAL.
- *
- * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate
- * additional addresses with an endpoint after calling bind().  Or use
- * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening
- * socket is associated with so that no new association accepted will be
- * associated with those addresses.
- *
- * SCTP_BIND_ADD_ADDR is defined as 0, so that it becomes the default
- * behavior for sctp_bindx() when no flags are given.
- *
- * Adding and removing addresses from a connected association is optional
- * functionality. Implementations that do not support this functionality
- * should return EOPNOTSUPP.
- *
- * NOTE: This could be integrated into sctp_setsockopt_bindx(),
- * but keeping it this way makes it easier if sometime sys_bindx is
- * added.
- */
-
-/* Unprotected by locks. Call only with socket lock sk->lock held! See
- * sctp_bindx() for a lock-protected call.
- */
-
-static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs,
-			int addrcnt, int flags)
-{
-	int retval = 0;
-
-	SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, "
-			  "flags: %s)\n", sk, addrs, addrcnt,
-			  (BINDX_ADD_ADDR == flags) ? "ADD" :
-			  ((BINDX_REM_ADDR == flags) ? "REM" : "BOGUS"));
-
-	switch (flags) {
-	case BINDX_ADD_ADDR:
-		retval = sctp_bindx_add(sk, addrs, addrcnt);
-		break;
-
-	case BINDX_REM_ADDR:
-		retval = sctp_bindx_rem(sk, addrs, addrcnt);
-		break;
-
-	default:
-		retval = -EINVAL;
-		break;
-        };
-
-	return retval;
-}
-
-/* BINDX with locks.
+ /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
  *
- * NOTE: Currently unused at all ...
- */
-int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt,
-	       int flags)
-{
-	int retval;
-
-	sctp_lock_sock(sk);
-	retval = __sctp_bindx(sk, addrs, addrcnt, flags);
-	sctp_release_sock(sk);
+ * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged 
+ * at any one time.  If a sender, after sending an ASCONF chunk, decides
+ * it needs to transfer another ASCONF Chunk, it MUST wait until the 
+ * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a
+ * subsequent ASCONF. Note this restriction binds each side, so at any 
+ * time two ASCONF may be in-transit on any given association (one sent 
+ * from each endpoint).
+ */
+static int sctp_send_asconf(struct sctp_association *asoc,
+			    struct sctp_chunk *chunk)
+{
+	int		retval = 0;
+
+	/* If there is an outstanding ASCONF chunk, queue it for later
+	 * transmission.
+	 */	
+	if (asoc->addip_last_asconf) {
+		__skb_queue_tail(&asoc->addip_chunks, (struct sk_buff *)chunk);
+		goto out;	
+	}
+
+	/* Hold the chunk until an ASCONF_ACK is received. */
+	sctp_chunk_hold(chunk);
+	retval = sctp_primitive_ASCONF(asoc, chunk);
+	if (retval)
+		sctp_chunk_free(chunk);
+	else
+		asoc->addip_last_asconf = chunk;
 
+out:
 	return retval;
 }
 
@@ -383,88 +351,147 @@ int sctp_bindx(struct sock *sk, struct s
  * If any of them fails, then the operation will be reversed and the
  * ones that were added will be removed.
  *
- * Only __sctp_bindx() is supposed to call this function.
+ * Only sctp_setsockopt_bindx() is supposed to call this function.
  */
-int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
+int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 {
 	int cnt;
 	int retval = 0;
-	int addr_len;
+	void *addr_buf;
+	struct sockaddr *sa_addr;
+	struct sctp_af *af;
 
 	SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n",
 			  sk, addrs, addrcnt);
 
+	addr_buf = addrs;
 	for (cnt = 0; cnt < addrcnt; cnt++) {
 		/* The list may contain either IPv4 or IPv6 address;
 		 * determine the address length for walking thru the list.
 		 */
-		switch (((struct sockaddr *)&addrs[cnt])->sa_family) {
-		case AF_INET:
-			addr_len = sizeof(struct sockaddr_in);
-			break;
-
-		case AF_INET6:
-			addr_len = sizeof(struct sockaddr_in6);
-			break;
-
-		default:
+		sa_addr = (struct sockaddr *)addr_buf;
+		af = sctp_get_af_specific(sa_addr->sa_family);
+		if (!af) {
 			retval = -EINVAL;
 			goto err_bindx_add;
-		};
+		}
 
-		retval = sctp_do_bind(sk, (union sctp_addr *)&addrs[cnt],
-				      addr_len);
+		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, 
+				      af->sockaddr_len);
+
+		addr_buf += af->sockaddr_len;
 
 err_bindx_add:
 		if (retval < 0) {
-			/* Failed. Cleanup the ones that has been added */
+			/* Failed. Cleanup the ones that have been added */
 			if (cnt > 0)
 				sctp_bindx_rem(sk, addrs, cnt);
 			return retval;
 		}
 	}
 
-	/* Notify the peer(s), assuming we have (an) association(s).
-	 * FIXME: for UDP, we have a 1-1-many mapping amongst sk, ep and asoc,
-	 *        so we don't have to do much work on locating associations.
-	 *
-	 * However, when the separation of ep and asoc kicks in, especially
-	 * for TCP style connection, it becomes n-1-n mapping.  We will need
-	 * to do more fine work.  Until then, hold my peace.
-	 *							--xguo
-	 *
-	 * Really, I don't think that will be a problem.  The bind()
-	 * call on a socket will either know the endpoint
-	 * (e.g. TCP-style listen()ing socket, or UDP-style socket),
-	 * or exactly one association.  The former case is EXACTLY
-	 * what we have now.  In the former case we know the
-	 * association already.					--piggy
-	 *
-	 * This code will be working on either a UDP style or a TCP style
-	 * socket, or say either an endpoint or an association. The socket
-	 * type verification code need to be added later before calling the
-	 * ADDIP code.
-	 * 							--daisy
-	 */
+	return retval;
+}
 
-#if CONFIG_IP_SCTP_ADDIP
-	/* Add these addresses to all associations on this endpoint.  */
-	if (retval >= 0) {
-		struct list_head *pos;
-		struct sctp_endpoint *ep;
-		struct sctp_association *asoc;
-		ep = sctp_sk(sk)->ep;
+/* Send an ASCONF chunk with Add IP address parameters to all the peers of the
+ * associations that are part of the endpoint indicating that a list of local
+ * addresses are added to the endpoint.
+ *
+ * If any of the addresses is already in the bind address list of the 
+ * association, we do not send the chunk for that association.  But it will not
+ * affect other associations.
+ *
+ * Only sctp_setsockopt_bindx() is supposed to call this function.
+ */
+static int sctp_send_asconf_add_ip(struct sock		*sk, 
+				   struct sockaddr	*addrs,
+				   int 			addrcnt)
+{
+	struct sctp_opt			*sp;
+	struct sctp_endpoint		*ep;
+	struct sctp_association		*asoc;
+	struct sctp_bind_addr		*bp;
+	struct sctp_chunk		*chunk;
+	struct sctp_sockaddr_entry	*laddr;
+	union sctp_addr			*addr;
+	void				*addr_buf;
+	struct sctp_af			*af;
+	struct list_head		*pos;
+	struct list_head		*p;
+	int 				i;
+	int 				retval = 0;
+
+	if (!sctp_addip_enable)
+		return retval;
+
+	sp = sctp_sk(sk);
+	ep = sp->ep;
+
+	SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
+			  __FUNCTION__, sk, addrs, addrcnt);
+
+	list_for_each(pos, &ep->asocs) {
+		asoc = list_entry(pos, struct sctp_association, asocs);
 
-		list_for_each(pos, &ep->asocs) {
-			asoc = list_entry(pos, struct sctp_association, asocs);
+		if (!asoc->peer.asconf_capable)
+			continue;
+
+		if (asoc->peer.addip_disabled_mask & SCTP_PARAM_ADD_IP)
+			continue;
 
-			sctp_addip_addr_config(asoc,
-					       SCTP_PARAM_ADD_IP,
-					       addrs, addrcnt);
+		if (!sctp_state(asoc, ESTABLISHED))
+			continue;
+
+		/* Check if any address in the packed array of addresses is
+	         * in the bind address list of the association. If so, 
+		 * do not send the asconf chunk to its peer, but continue with 
+		 * other associations.
+		 */
+		addr_buf = addrs;
+		for (i = 0; i < addrcnt; i++) {
+			addr = (union sctp_addr *)addr_buf;
+			af = sctp_get_af_specific(addr->v4.sin_family);
+			if (!af) {
+				retval = -EINVAL;
+				goto out;
+			}
+
+			if (sctp_assoc_lookup_laddr(asoc, addr))
+				break;
+
+			addr_buf += af->sockaddr_len;
 		}
+		if (i < addrcnt)
+			continue;
+
+		/* Use the first address in bind addr list of association as
+		 * Address Parameter of ASCONF CHUNK.
+		 */
+		sctp_read_lock(&asoc->base.addr_lock);
+		bp = &asoc->base.bind_addr;
+		p = bp->address_list.next;
+		laddr = list_entry(p, struct sctp_sockaddr_entry, list);
+		sctp_read_unlock(&asoc->base.addr_lock);
+
+		chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs,
+						   addrcnt, SCTP_PARAM_ADD_IP);
+		if (!chunk) {
+			retval = -ENOMEM;
+			goto out;
+		}
+
+		retval = sctp_send_asconf(asoc, chunk);
+
+		/* FIXME: After sending the add address ASCONF chunk, we
+		 * cannot append the address to the association's binding
+		 * address list, because the new address may be used as the
+		 * source of a message sent to the peer before the ASCONF
+		 * chunk is received by the peer.  So we should wait until
+		 * ASCONF_ACK is received.
+		 */
 	}
-#endif
 
+out:
 	return retval;
 }
 
@@ -481,63 +508,54 @@ err_bindx_add:
  * At least one address has to be left; if only one address is
  * available, the operation will return -EBUSY.
  *
- * Only __sctp_bindx() is supposed to call this function.
+ * Only sctp_setsockopt_bindx() is supposed to call this function.
  */
-int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
+int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 {
 	struct sctp_opt *sp = sctp_sk(sk);
 	struct sctp_endpoint *ep = sp->ep;
 	int cnt;
-	sctp_bind_addr_t *bp = &ep->base.bind_addr;
+	struct sctp_bind_addr *bp = &ep->base.bind_addr;
 	int retval = 0;
 	union sctp_addr saveaddr;
+	void *addr_buf;
+	struct sockaddr *sa_addr;
+	struct sctp_af *af;
 
 	SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n",
 			  sk, addrs, addrcnt);
 
+	addr_buf = addrs;
 	for (cnt = 0; cnt < addrcnt; cnt++) {
-		/* If there is only one bind address, there is nothing more
-		 * to be removed (we need at least one address here).
+		/* If the bind address list is empty or if there is only one
+		 * bind address, there is nothing more to be removed (we need
+		 * at least one address here).
 		 */
-		if (list_empty(&bp->address_list)) {
+		if (list_empty(&bp->address_list) ||
+		    (sctp_list_single_entry(&bp->address_list))) {
 			retval = -EBUSY;
 			goto err_bindx_rem;
 		}
 
 		/* The list may contain either IPv4 or IPv6 address;
-		 * determine the address length for walking thru the list.
+		 * determine the address length to copy the address to
+		 * saveaddr. 
 		 */
-		switch (((struct sockaddr *)&addrs[cnt])->sa_family) {
-		case AF_INET:
-			saveaddr = *((union sctp_addr *)
-				     &addrs[cnt]);
-			saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
-			/* Verify the port.  */
-			if (saveaddr.v4.sin_port != bp->port) {
-				retval = -EINVAL;
-				goto err_bindx_rem;
-			}
-			break;
-
-		case AF_INET6:
-			saveaddr = *((union sctp_addr *)
-				     &addrs[cnt]);
-			saveaddr.v6.sin6_port =
-				ntohs(saveaddr.v6.sin6_port);
-			/* verify the port */
-			if (saveaddr.v6.sin6_port != bp->port) {
-				retval = -EINVAL;
-				goto err_bindx_rem;
-			}
-			break;
-
-		default:
+		sa_addr = (struct sockaddr *)addr_buf;
+		af = sctp_get_af_specific(sa_addr->sa_family);
+		if (!af) {
 			retval = -EINVAL;
 			goto err_bindx_rem;
-		};
+		}
+		memcpy(&saveaddr, sa_addr, af->sockaddr_len); 
+		saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
+		if (saveaddr.v4.sin_port != bp->port) {
+			retval = -EINVAL;
+			goto err_bindx_rem;
+		}
 
-		/* FIXME - There is probably a need to check if sk->saddr and
-		 * sk->rcv_addr are currently set to one of the addresses to
+		/* FIXME - There is probably a need to check if sk->sk_saddr and
+		 * sk->sk_rcv_addr are currently set to one of the addresses to
 		 * be removed. This is something which needs to be looked into
 		 * when we are fixing the outstanding issues with multi-homing
 		 * socket routing and failover schemes. Refer to comments in
@@ -551,6 +569,7 @@ int sctp_bindx_rem(struct sock *sk, stru
 		sctp_write_unlock(&ep->base.addr_lock);
 		sctp_local_bh_enable();
 
+		addr_buf += af->sockaddr_len;
 err_bindx_rem:
 		if (retval < 0) {
 			/* Failed. Add the ones that has been removed back */
@@ -560,43 +579,167 @@ err_bindx_rem:
 		}
 	}
 
-	/*
-	 * This code will be working on either a UDP style or a TCP style
-	 * socket, * or say either an endpoint or an association. The socket
-	 * type verification code need to be added later before calling the
-	 * ADDIP code.
-	 * 							--daisy
-	 */
-#if CONFIG_IP_SCTP_ADDIP
-	/* Remove these addresses from all associations on this endpoint.  */
-	if (retval >= 0) {
-		struct list_head *pos;
-		struct sctp_endpoint *ep;
-		struct sctp_association *asoc;
+	return retval;
+}
 
-		ep = sctp_sk(sk)->ep;
-		list_for_each(pos, &ep->asocs) {
-			asoc = list_entry(pos, struct sctp_association, asocs);
-			sctp_addip_addr_config(asoc, SCTP_PARAM_DEL_IP,
-					       addrs, addrcnt);
+/* Send an ASCONF chunk with Delete IP address parameters to all the peers of
+ * the associations that are part of the endpoint indicating that a list of
+ * local addresses are removed from the endpoint.
+ *
+ * If any of the addresses is already in the bind address list of the 
+ * association, we do not send the chunk for that association.  But it will not
+ * affect other associations.
+ *
+ * Only sctp_setsockopt_bindx() is supposed to call this function.
+ */
+static int sctp_send_asconf_del_ip(struct sock		*sk,
+				   struct sockaddr	*addrs,
+				   int			addrcnt)
+{
+	struct sctp_opt		*sp;
+	struct sctp_endpoint	*ep;
+	struct sctp_association	*asoc;
+	struct sctp_bind_addr	*bp;
+	struct sctp_chunk	*chunk;
+	union sctp_addr		*laddr;
+	void			*addr_buf;
+	struct sctp_af		*af;
+	struct list_head	*pos;
+	int 			i;
+	int 			retval = 0;
+
+	if (!sctp_addip_enable)
+		return retval;
+
+	sp = sctp_sk(sk);
+	ep = sp->ep;
+
+	SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
+			  __FUNCTION__, sk, addrs, addrcnt);
+
+	list_for_each(pos, &ep->asocs) {
+		asoc = list_entry(pos, struct sctp_association, asocs);
+
+		if (!asoc->peer.asconf_capable)
+			continue;
+
+		if (asoc->peer.addip_disabled_mask & SCTP_PARAM_DEL_IP)
+			continue;
+
+		if (!sctp_state(asoc, ESTABLISHED))
+			continue;
+
+		/* Check if any address in the packed array of addresses is
+	         * not present in the bind address list of the association.
+		 * If so, do not send the asconf chunk to its peer, but
+		 * continue with other associations.
+		 */
+		addr_buf = addrs;
+		for (i = 0; i < addrcnt; i++) {
+			laddr = (union sctp_addr *)addr_buf;
+			af = sctp_get_af_specific(laddr->v4.sin_family);
+			if (!af) {
+				retval = -EINVAL;
+				goto out;
+			}
+
+			if (!sctp_assoc_lookup_laddr(asoc, laddr))
+				break;
+
+			addr_buf += af->sockaddr_len;
 		}
+		if (i < addrcnt)
+			continue;
+
+		/* Find one address in the association's bind address list
+		 * that is not in the packed array of addresses. This is to
+		 * make sure that we do not delete all the addresses in the
+		 * association.
+		 */
+		sctp_read_lock(&asoc->base.addr_lock);
+		bp = &asoc->base.bind_addr;
+		laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
+					       addrcnt, sp);
+		sctp_read_unlock(&asoc->base.addr_lock);
+		if (!laddr)
+			continue;
+
+		chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt,
+						   SCTP_PARAM_DEL_IP);
+		if (!chunk) {
+			retval = -ENOMEM;
+			goto out;
+		}
+
+		retval = sctp_send_asconf(asoc, chunk);
+
+		/* FIXME: After sending the delete address ASCONF chunk, we
+		 * cannot remove the addresses from the association's bind
+		 * address list, because there maybe some packet send to
+		 * the delete addresses, so we should wait until ASCONF_ACK
+		 * packet is received.
+		 */
 	}
-#endif
+out:
 	return retval;
 }
 
-/* Helper for tunneling sys_bindx() requests through sctp_setsockopt()
+/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
+ *
+ * API 8.1
+ * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt,
+ *                int flags);
+ *
+ * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
+ * If the sd is an IPv6 socket, the addresses passed can either be IPv4
+ * or IPv6 addresses.
+ *
+ * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
+ * Section 3.1.2 for this usage.
+ *
+ * addrs is a pointer to an array of one or more socket addresses. Each
+ * address is contained in its appropriate structure (i.e. struct
+ * sockaddr_in or struct sockaddr_in6) the family of the address type
+ * must be used to distengish the address length (note that this
+ * representation is termed a "packed array" of addresses). The caller
+ * specifies the number of addresses in the array with addrcnt.
+ *
+ * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns
+ * -1, and sets errno to the appropriate error code.
+ *
+ * For SCTP, the port given in each socket address must be the same, or
+ * sctp_bindx() will fail, setting errno to EINVAL.
+ *
+ * The flags parameter is formed from the bitwise OR of zero or more of
+ * the following currently defined flags:
+ *
+ * SCTP_BINDX_ADD_ADDR
+ *
+ * SCTP_BINDX_REM_ADDR
+ *
+ * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the
+ * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given
+ * addresses from the association. The two flags are mutually exclusive;
+ * if both are given, sctp_bindx() will fail with EINVAL. A caller may
+ * not remove all addresses from an association; sctp_bindx() will
+ * reject such an attempt with EINVAL.
+ *
+ * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate
+ * additional addresses with an endpoint after calling bind().  Or use
+ * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening
+ * socket is associated with so that no new association accepted will be
+ * associated with those addresses. If the endpoint supports dynamic
+ * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a
+ * endpoint to send the appropriate message to the peer to change the
+ * peers address lists.
+ *
+ * Adding and removing addresses from a connected association is
+ * optional functionality. Implementations that do not support this
+ * functionality should return EOPNOTSUPP.
  *
  * Basically do nothing but copying the addresses from user to kernel
- * land and invoking sctp_bindx on the sk. This is used for tunneling
- * the sctp_bindx() [sys_bindx()] request through sctp_setsockopt()
- * from userspace.
- *
- * Note I don't use move_addr_to_kernel(): the reason is we would be
- * iterating over an array of struct sockaddr_storage passing always
- * what we know is a good size (sizeof (struct sock...)), so it is
- * pointless. Instead check the whole area for read access and copy
- * it.
+ * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
+ * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
  *
  * We don't use copy_from_user() for optimization: we first do the
  * sanity checks (buffer size -fast- and access check-healthy
@@ -616,38 +759,77 @@ err_bindx_rem:
  *
  * Returns 0 if ok, <0 errno code on error.
  */
-SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
-				      struct sockaddr_storage *addrs,
-				      int addrssize, int op)
+SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs,
+				      int addrs_size, int op)
 {
-	struct sockaddr_storage *kaddrs;
+	struct sockaddr *kaddrs;
 	int err;
-	size_t addrcnt;
+	int addrcnt = 0;
+	int walk_size = 0;
+	struct sockaddr *sa_addr;
+	void *addr_buf;
+	struct sctp_af *af;
 
-	SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p"
-			  " addrssize %d opt %d\n", sk, addrs, addrssize, op);
+	SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
+			  " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
 
-	/* Do we have an integer number of structs sockaddr_storage?  */
-	if (unlikely(addrssize <= 0 ||
-		     addrssize % sizeof(struct sockaddr_storage) != 0))
+	if (unlikely(addrs_size <= 0))
 		return -EINVAL;
 
 	/* Check the user passed a healthy pointer.  */
-	if (unlikely(!access_ok(VERIFY_READ, addrs, addrssize)))
+	if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
 		return -EFAULT;
 
 	/* Alloc space for the address array in kernel memory.  */
-	kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL);
+	kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
 	if (unlikely(!kaddrs))
 		return -ENOMEM;
 
-	if (copy_from_user(kaddrs, addrs, addrssize)) {
+	if (__copy_from_user(kaddrs, addrs, addrs_size)) {
 		kfree(kaddrs);
 		return -EFAULT;
 	}
 
-	addrcnt = addrssize / sizeof(struct sockaddr_storage);
-	err = __sctp_bindx(sk, kaddrs, addrcnt, op);   /* Do the work. */
+	/* Walk through the addrs buffer and count the number of addresses. */ 
+	addr_buf = kaddrs;
+	while (walk_size < addrs_size) {
+		sa_addr = (struct sockaddr *)addr_buf;
+		af = sctp_get_af_specific(sa_addr->sa_family);
+
+		/* If the address family is not supported or if this address
+		 * causes the address buffer to overflow return EINVAL.
+		 */ 
+		if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
+			kfree(kaddrs);
+			return -EINVAL;
+		}
+		addrcnt++;
+		addr_buf += af->sockaddr_len;
+		walk_size += af->sockaddr_len;
+	}
+
+	/* Do the work. */
+	switch (op) {
+	case SCTP_BINDX_ADD_ADDR:
+		err = sctp_bindx_add(sk, kaddrs, addrcnt);
+		if (err)
+			goto out;
+		err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt);
+		break;
+
+	case SCTP_BINDX_REM_ADDR:
+		err = sctp_bindx_rem(sk, kaddrs, addrcnt);
+		if (err)
+			goto out;
+		err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt);
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+        };
+
+out:
 	kfree(kaddrs);
 
 	return err;
@@ -671,6 +853,37 @@ SCTP_STATIC int sctp_setsockopt_bindx(st
  *
  * If sd in the close() call is a branched-off socket representing only
  * one association, the shutdown is performed on that association only.
+ *
+ * 4.1.6 close() - TCP Style Syntax
+ *
+ * Applications use close() to gracefully close down an association.
+ *
+ * The syntax is:
+ *
+ *    int close(int sd);
+ *
+ *      sd      - the socket descriptor of the association to be closed.
+ *
+ * After an application calls close() on a socket descriptor, no further
+ * socket operations will succeed on that descriptor.
+ *
+ * API 7.1.4 SO_LINGER
+ *
+ * An application using the TCP-style socket can use this option to
+ * perform the SCTP ABORT primitive.  The linger option structure is:
+ *
+ *  struct  linger {
+ *     int     l_onoff;                // option on/off
+ *     int     l_linger;               // linger time
+ * };
+ *
+ * To enable the option, set l_onoff to 1.  If the l_linger value is set
+ * to 0, calling close() is the same as the ABORT primitive.  If the
+ * value is set to a negative value, the setsockopt() call will return
+ * an error.  If the value is set to a positive value linger_time, the
+ * close() can be blocked for at most linger_time ms.  If the graceful
+ * shutdown phase does not finish during this period, close() will
+ * return but the graceful shutdown phase continues in the system.
  */
 SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
 {
@@ -678,10 +891,10 @@ SCTP_STATIC void sctp_close(struct sock 
 	struct sctp_association *asoc;
 	struct list_head *pos, *temp;
 
-	SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p...)\n", sk);
+	SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout);
 
 	sctp_lock_sock(sk);
-	sk->shutdown = SHUTDOWN_MASK;
+	sk->sk_shutdown = SHUTDOWN_MASK;
 
 	ep = sctp_sk(sk)->ep;
 
@@ -689,21 +902,31 @@ SCTP_STATIC void sctp_close(struct sock 
 	list_for_each_safe(pos, temp, &ep->asocs) {
 		asoc = list_entry(pos, struct sctp_association, asocs);
 
-		/* A closed association can still be in the list if it
-		 * belongs to a TCP-style listening socket that is not
-		 * yet accepted.
-		 */
-		if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) &&
-		    (SCTP_STATE_CLOSED == asoc->state)) {
-			sctp_unhash_established(asoc);
-			sctp_association_free(asoc);
+		if (sctp_style(sk, TCP)) {
+			/* A closed association can still be in the list if
+			 * it belongs to a TCP-style listening socket that is
+			 * not yet accepted. If so, free it. If not, send an
+			 * ABORT or SHUTDOWN based on the linger options.
+			 */
+			if (sctp_state(asoc, CLOSED)) {
+				sctp_unhash_established(asoc);
+				sctp_association_free(asoc);
+
+			} else if (sk->linger && !sk->sk_lingertime)
+				sctp_primitive_ABORT(asoc, NULL);
+			else
+				sctp_primitive_SHUTDOWN(asoc, NULL);
 		} else
 			sctp_primitive_SHUTDOWN(asoc, NULL);
 	}
 
 	/* Clean up any skbs sitting on the receive queue.  */
-	skb_queue_purge(&sk->receive_queue);
-	skb_queue_purge(&sctp_sk(sk)->pd_lobby);
+	sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
+	sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
+
+	/* On a TCP-style socket, block for at most linger_time if set. */
+	if (sctp_style(sk, TCP) && timeout)
+		sctp_wait_for_close(sk, timeout);
 
 	/* This will run the backlog queue.  */
 	sctp_release_sock(sk);
@@ -768,8 +991,8 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 	struct sctp_opt *sp;
 	struct sctp_endpoint *ep;
 	struct sctp_association *new_asoc=NULL, *asoc=NULL;
-	struct sctp_transport *transport;
-	sctp_chunk_t *chunk = NULL;
+	struct sctp_transport *transport, *chunk_tp;
+	struct sctp_chunk *chunk;
 	union sctp_addr to;
 	struct sockaddr *msg_name = NULL;
 	struct sctp_sndrcvinfo default_sinfo = { 0 };
@@ -781,10 +1004,11 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 	sctp_scope_t scope;
 	long timeo;
 	__u16 sinfo_flags = 0;
-	struct sk_buff_head chunks;
+	struct sctp_datamsg *datamsg;
+	struct list_head *pos;
 	int msg_flags = msg->msg_flags;
 
-	SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %d)\n",
+	SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %u)\n",
 			  sk, msg, msg_len);
 
 	err = 0;
@@ -793,8 +1017,8 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 
 	SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name);
 
-	if ((SCTP_SOCKET_TCP == sp->type) &&
-	    (SCTP_SS_ESTABLISHED != sk->state)) {
+	/* We cannot send a message over a TCP-style listening socket. */
+	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) {
 		err = -EPIPE;
 		goto out_nounlock;
 	}
@@ -812,7 +1036,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 	 * the address we will send to.
 	 * For a peeled-off socket, msg_name is ignored.
 	 */
-	if ((SCTP_SOCKET_UDP_HIGH_BANDWIDTH != sp->type) && msg->msg_name) {
+	if (!sctp_style(sk, UDP_HIGH_BANDWIDTH) && msg->msg_name) {
 		int msg_namelen = msg->msg_namelen;
 
 		err = sctp_verify_addr(sk, (union sctp_addr *)msg->msg_name,
@@ -840,9 +1064,15 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 		associd = sinfo->sinfo_assoc_id;
 	}
 
-	SCTP_DEBUG_PRINTK("msg_len: %Zd, sinfo_flags: 0x%x\n",
+	SCTP_DEBUG_PRINTK("msg_len: %u, sinfo_flags: 0x%x\n",
 			  msg_len, sinfo_flags);
 
+	/* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */
+	if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) {
+		err = -EINVAL;
+		goto out_nounlock;
+	}
+
 	/* If MSG_EOF is set, no data can be sent. Disallow sending zero
 	 * length messages when MSG_EOF|MSG_ABORT is not set.
 	 * If MSG_ABORT is set, the message length could be non zero with
@@ -854,22 +1084,33 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 		goto out_nounlock;
 	}
 
-	sctp_lock_sock(sk);
+	/* If MSG_ADDR_OVER is set, there must be an address
+	 * specified in msg_name.
+	 */
+	if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) {
+		err = -EINVAL;
+		goto out_nounlock;
+	}
 
 	transport = NULL;
 
 	SCTP_DEBUG_PRINTK("About to look up association.\n");
 
+	sctp_lock_sock(sk);
+
 	/* If a msg_name has been specified, assume this is to be used.  */
 	if (msg_name) {
 		/* Look for a matching association on the endpoint. */
 		asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
 		if (!asoc) {
 			/* If we could not find a matching association on the
-			 * endpoint, make sure that there is no peeled-off
-			 * association on another socket.
+			 * endpoint, make sure that it is not a TCP-style
+			 * socket that already has an association or there is
+			 * no peeled-off association on another socket.
 			 */
-			if (sctp_endpoint_is_peeled_off(ep, &to)) {
+			if ((sctp_style(sk, TCP) &&
+			     sctp_sstate(sk, ESTABLISHED)) ||
+			    sctp_endpoint_is_peeled_off(ep, &to)) {
 				err = -EADDRNOTAVAIL;
 				goto out_unlock;
 			}
@@ -877,22 +1118,20 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 	} else {
 		asoc = sctp_id2assoc(sk, associd);
 		if (!asoc) {
-			err = -EINVAL;
+			err = -EPIPE;
 			goto out_unlock;
 		}
 	}
 
 	if (asoc) {
-		SCTP_DEBUG_PRINTK("Just looked up association: "
-				  "%s. \n", asoc->debug_name);
+		SCTP_DEBUG_PRINTK("Just looked up association: %p.\n", asoc);
 
-		/* We cannot send a message on a TCP-style SCTP_SS_ESTABLISHED 
+		/* We cannot send a message on a TCP-style SCTP_SS_ESTABLISHED
 		 * socket that has an association in CLOSED state. This can
 		 * happen when an accepted socket has an association that is
-		 * already CLOSED. 
+		 * already CLOSED.
 		 */
-		if ((SCTP_STATE_CLOSED == asoc->state) &&
-		    (SCTP_SOCKET_TCP == sp->type)) {
+		if (sctp_state(asoc, CLOSED) && sctp_style(sk, TCP)) {
 			err = -EPIPE;
 			goto out_unlock;
 		}
@@ -976,8 +1215,8 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 					= sinit->sinit_max_attempts;
 			}
 			if (sinit->sinit_max_init_timeo) {
-				asoc->max_init_timeo
-					= sinit->sinit_max_init_timeo * HZ;
+				asoc->max_init_timeo = 
+				 SCTP_MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo);
 			}
 		}
 
@@ -1001,11 +1240,11 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 		/* If the user didn't specify SNDRCVINFO, make up one with
 		 * some defaults.
 		 */
-		default_sinfo.sinfo_stream = asoc->defaults.stream;
-		default_sinfo.sinfo_flags = asoc->defaults.flags;
-		default_sinfo.sinfo_ppid = asoc->defaults.ppid;
-		default_sinfo.sinfo_context = asoc->defaults.context;
-		default_sinfo.sinfo_timetolive = asoc->defaults.timetolive;
+		default_sinfo.sinfo_stream = asoc->default_stream;
+		default_sinfo.sinfo_flags = asoc->default_flags;
+		default_sinfo.sinfo_ppid = asoc->default_ppid;
+		default_sinfo.sinfo_context = asoc->default_context;
+		default_sinfo.sinfo_timetolive = asoc->default_timetolive;
 		default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc);
 		sinfo = &default_sinfo;
 	}
@@ -1013,7 +1252,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 	/* API 7.1.7, the sndbuf size per association bounds the
 	 * maximum size of data that can be sent in a single send call.
 	 */
-	if (msg_len > sk->sndbuf) {
+	if (msg_len > sk->sk_sndbuf) {
 		err = -EMSGSIZE;
 		goto out_free;
 	}
@@ -1043,64 +1282,71 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 			goto out_free;
 	}
 
-	/* Break the message into multiple chunks of maximum size. */
-	skb_queue_head_init(&chunks);
-	err = sctp_datachunks_from_user(asoc, sinfo, msg, msg_len, &chunks);
-	if (err)
-		goto out_free;
+	/* If an address is passed with the sendto/sendmsg call, it is used
+	 * to override the primary destination address in the TCP model, or
+	 * when MSG_ADDR_OVER flag is set in the UDP model.
+	 */
+	if ((sctp_style(sk, TCP) && msg_name) ||
+	    (sinfo_flags & MSG_ADDR_OVER)) {
+		chunk_tp = sctp_assoc_lookup_paddr(asoc, &to);
+		if (!chunk_tp) {
+			err = -EINVAL;
+			goto out_free;
+		}
+	} else
+		chunk_tp = NULL;
 
 	/* Auto-connect, if we aren't connected already. */
-	if (SCTP_STATE_CLOSED == asoc->state) {
+	if (sctp_state(asoc, CLOSED)) {
 		err = sctp_primitive_ASSOCIATE(asoc, NULL);
 		if (err < 0)
 			goto out_free;
 		SCTP_DEBUG_PRINTK("We associated primitively.\n");
 	}
 
+	/* Break the message into multiple chunks of maximum size. */
+	datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
+	if (!datamsg) {
+		err = -ENOMEM;
+		goto out_free;
+	}
+
 	/* Now send the (possibly) fragmented message. */
-	while ((chunk = (sctp_chunk_t *)__skb_dequeue(&chunks))) {
+	list_for_each(pos, &datamsg->chunks) {
+		chunk = list_entry(pos, struct sctp_chunk, frag_list);
+		sctp_datamsg_track(chunk);
 
 		/* Do accounting for the write space.  */
 		sctp_set_owner_w(chunk);
 
-		/* This flag, in the UDP model, requests the SCTP stack to
-		 * override the primary destination address with the
-		 * address found with the sendto/sendmsg call.
-		 */
-		if (sinfo_flags & MSG_ADDR_OVER) {
-			if (!msg->msg_name) {
-				err = -EINVAL;
-				goto out_free;
-			}
-			chunk->transport = sctp_assoc_lookup_paddr(asoc, &to);
-			if (!chunk->transport) {
-				err = -EINVAL;
-				goto out_free;
-			}
-		}
+		chunk->transport = chunk_tp;
 
-		/* Send it to the lower layers.  */
-		sctp_primitive_SEND(asoc, chunk);
+		/* Send it to the lower layers.  Note:  all chunks
+		 * must either fail or succeed.   The lower layer
+		 * works that way today.  Keep it that way or this
+		 * breaks.
+		 */
+		err = sctp_primitive_SEND(asoc, chunk);
+		/* Did the lower layer accept the chunk? */
+		if (err)
+			sctp_chunk_free(chunk);
 		SCTP_DEBUG_PRINTK("We sent primitively.\n");
 	}
 
-	if (!err) {
+	sctp_datamsg_free(datamsg);
+	if (err)
+		goto out_free;
+	else
 		err = msg_len;
-		goto out_unlock;
-	}
+
 	/* If we are already past ASSOCIATE, the lower
 	 * layers are responsible for association cleanup.
 	 */
-	goto out_free_chunk;
+	goto out_unlock;
 
 out_free:
 	if (new_asoc)
 		sctp_association_free(asoc);
-
-out_free_chunk:
-	if (chunk)
-		sctp_free_chunk(chunk);
-
 out_unlock:
 	sctp_release_sock(sk);
 
@@ -1190,8 +1436,7 @@ SCTP_STATIC int sctp_recvmsg(struct sock
 
 	sctp_lock_sock(sk);
 
-	if ((SCTP_SOCKET_TCP == sp->type) &&
-	    (SCTP_SS_ESTABLISHED != sk->state)) {
+	if (sctp_style(sk, TCP) && !sctp_sstate(sk, ESTABLISHED)) {
 		err = -ENOTCONN;
 		goto out;
 	}
@@ -1229,7 +1474,7 @@ SCTP_STATIC int sctp_recvmsg(struct sock
 		sctp_ulpevent_read_sndrcvinfo(event, msg);
 #if 0
 	/* FIXME: we should be calling IP/IPv6 layers.  */
-	if (sk->protinfo.af_inet.cmsg_flags)
+	if (sk->sk_protinfo.af_inet.cmsg_flags)
 		ip_cmsg_recv(msg, skb);
 #endif
 
@@ -1244,14 +1489,14 @@ SCTP_STATIC int sctp_recvmsg(struct sock
 		if (flags & MSG_PEEK)
 			goto out_free;
 		sctp_skb_pull(skb, copied);
-		skb_queue_head(&sk->receive_queue, skb);
+		skb_queue_head(&sk->sk_receive_queue, skb);
 
 		/* When only partial message is copied to the user, increase
 		 * rwnd by that amount. If all the data in the skb is read,
-		 * rwnd is updated when the skb's destructor is called via
-		 * sctp_ulpevent_free().
+		 * rwnd is updated when the event is freed.
 		 */
-		sctp_assoc_rwnd_increase(event->event_asoc, copied);
+		sctp_assoc_rwnd_increase(event->sndrcvinfo.sinfo_assoc_id,
+					 copied);
 		goto out;
 	} else if ((event->msg_flags & MSG_NOTIFICATION) ||
 		   (event->msg_flags & MSG_EOR))
@@ -1260,12 +1505,30 @@ SCTP_STATIC int sctp_recvmsg(struct sock
 		msg->msg_flags &= ~MSG_EOR;
 
 out_free:
-	sctp_ulpevent_free(event); /* Free the skb. */
+	if (flags & MSG_PEEK) {
+		/* Release the skb reference acquired after peeking the skb in
+		 * sctp_skb_recv_datagram().
+		 */
+		kfree_skb(skb);
+	} else {
+		/* Free the event which includes releasing the reference to
+		 * the owner of the skb, freeing the skb and updating the
+		 * rwnd.
+		 */
+		sctp_ulpevent_free(event);
+	}
 out:
 	sctp_release_sock(sk);
 	return err;
 }
 
+/* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS)
+ *
+ * This option is a on/off flag.  If enabled no SCTP message
+ * fragmentation will be performed.  Instead if a message being sent
+ * exceeds the current PMTU size, the message will NOT be sent and
+ * instead a error will be indicated to the user.
+ */
 static int sctp_setsockopt_disable_fragments(struct sock *sk,
 						    char *optval, int optlen)
 {
@@ -1292,13 +1555,24 @@ static int sctp_setsockopt_events(struct
 	return 0;
 }
 
+/* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE)
+ *
+ * This socket option is applicable to the UDP-style socket only.  When
+ * set it will cause associations that are idle for more than the
+ * specified number of seconds to automatically close.  An association
+ * being idle is defined an association that has NOT sent or received
+ * user data.  The special value of '0' indicates that no automatic
+ * close of any associations should be performed.  The option expects an
+ * integer defining the number of seconds of idle time before an
+ * association is closed.
+ */
 static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
 					    int optlen)
 {
 	struct sctp_opt *sp = sctp_sk(sk);
 
 	/* Applicable to UDP-style socket only */
-	if (SCTP_SOCKET_TCP == sp->type)
+	if (sctp_style(sk, TCP))
 		return -EOPNOTSUPP;
 	if (optlen != sizeof(int))
 		return -EINVAL;
@@ -1309,12 +1583,41 @@ static int sctp_setsockopt_autoclose(str
 	return 0;
 }
 
+/* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
+ *
+ * Applications can enable or disable heartbeats for any peer address of
+ * an association, modify an address's heartbeat interval, force a
+ * heartbeat to be sent immediately, and adjust the address's maximum
+ * number of retransmissions sent before an address is considered
+ * unreachable.  The following structure is used to access and modify an
+ * address's parameters:
+ *
+ *  struct sctp_paddrparams {
+ *      sctp_assoc_t            spp_assoc_id;
+ *      struct sockaddr_storage spp_address;
+ *      uint32_t                spp_hbinterval;
+ *      uint16_t                spp_pathmaxrxt;
+ *  };
+ *
+ *   spp_assoc_id    - (UDP style socket) This is filled in the application,
+ *                     and identifies the association for this query.
+ *   spp_address     - This specifies which address is of interest.
+ *   spp_hbinterval  - This contains the value of the heartbeat interval,
+ *                     in milliseconds.  A value of 0, when modifying the
+ *                     parameter, specifies that the heartbeat on this
+ *                     address should be disabled. A value of UINT32_MAX
+ *                     (4294967295), when modifying the parameter,
+ *                     specifies that a heartbeat should be sent
+ *                     immediately to the peer address, and the current
+ *                     interval should remain unchanged.
+ *   spp_pathmaxrxt  - This contains the maximum number of
+ *                     retransmissions before this address shall be
+ *                     considered unreachable.
+ */
 static int sctp_setsockopt_peer_addr_params(struct sock *sk,
 					    char *optval, int optlen)
 {
 	struct sctp_paddrparams params;
-	struct sctp_association *asoc;
-	union sctp_addr *addr;
 	struct sctp_transport *trans;
 	int error;
 
@@ -1323,15 +1626,10 @@ static int sctp_setsockopt_peer_addr_par
 	if (copy_from_user(&params, optval, optlen))
 		return -EFAULT;
 
-	asoc = sctp_id2assoc(sk, params.spp_assoc_id);
-	if (!asoc)
-		return -EINVAL;
-
-	addr = (union sctp_addr *) &(params.spp_address);
-
-	trans = sctp_assoc_lookup_paddr(asoc, addr);
+	trans = sctp_addr_id2transport(sk, &params.spp_address,
+				       params.spp_assoc_id);
 	if (!trans)
-		return -ENOENT;
+		return -EINVAL;
 
 	/* Applications can enable or disable heartbeats for any peer address
 	 * of an association, modify an address's heartbeat interval, force a
@@ -1345,7 +1643,7 @@ static int sctp_setsockopt_peer_addr_par
 	 * and the current interval should remain unchanged.
 	 */
 	if (0xffffffff == params.spp_hbinterval) {
-		error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans);
+		error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans);
 		if (error)
 			return error;
 	} else {
@@ -1355,7 +1653,8 @@ static int sctp_setsockopt_peer_addr_par
 	 */
 		if (params.spp_hbinterval) {
 			trans->hb_allowed = 1;
-			trans->hb_interval = params.spp_hbinterval * HZ / 1000;
+			trans->hb_interval = 
+				SCTP_MSECS_TO_JIFFIES(params.spp_hbinterval);
 		} else
 			trans->hb_allowed = 0;
 	}
@@ -1368,17 +1667,41 @@ static int sctp_setsockopt_peer_addr_par
 	return 0;
 }
 
+/* 7.1.3 Initialization Parameters (SCTP_INITMSG)
+ *
+ * Applications can specify protocol parameters for the default association
+ * initialization.  The option name argument to setsockopt() and getsockopt()
+ * is SCTP_INITMSG.
+ *
+ * Setting initialization parameters is effective only on an unconnected
+ * socket (for UDP-style sockets only future associations are effected
+ * by the change).  With TCP-style sockets, this option is inherited by
+ * sockets derived from a listener socket.
+ */
 static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen)
 {
+	struct sctp_initmsg sinit;
+	struct sctp_opt *sp = sctp_sk(sk);
+
 	if (optlen != sizeof(struct sctp_initmsg))
 		return -EINVAL;
-	if (copy_from_user(&sctp_sk(sk)->initmsg, optval, optlen))
+	if (copy_from_user(&sinit, optval, optlen))
 		return -EFAULT;
+
+	if (sinit.sinit_num_ostreams)
+		sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;	
+	if (sinit.sinit_max_instreams)
+		sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;	
+	if (sinit.sinit_max_attempts)
+		sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;	
+	if (sinit.sinit_max_init_timeo)
+		sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;	
+
 	return 0;
 }
 
 /*
- * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM)
+ * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM)
  *
  *   Applications that wish to use the sendto() system call may wish to
  *   specify a default set of parameters that would normally be supplied
@@ -1396,6 +1719,7 @@ static int sctp_setsockopt_default_send_
 {
 	struct sctp_sndrcvinfo info;
 	struct sctp_association *asoc;
+	struct sctp_opt *sp = sctp_sk(sk);
 
 	if (optlen != sizeof(struct sctp_sndrcvinfo))
 		return -EINVAL;
@@ -1403,54 +1727,54 @@ static int sctp_setsockopt_default_send_
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
-	if (!asoc)
+	if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP))
 		return -EINVAL;
 
-	asoc->defaults.stream = info.sinfo_stream;
-	asoc->defaults.flags = info.sinfo_flags;
-	asoc->defaults.ppid = info.sinfo_ppid;
-	asoc->defaults.context = info.sinfo_context;
-	asoc->defaults.timetolive = info.sinfo_timetolive;
+	if (asoc) {
+		asoc->default_stream = info.sinfo_stream;
+		asoc->default_flags = info.sinfo_flags;
+		asoc->default_ppid = info.sinfo_ppid;
+		asoc->default_context = info.sinfo_context;
+		asoc->default_timetolive = info.sinfo_timetolive;
+	} else {
+		sp->default_stream = info.sinfo_stream;
+		sp->default_flags = info.sinfo_flags;
+		sp->default_ppid = info.sinfo_ppid;
+		sp->default_context = info.sinfo_context;
+		sp->default_timetolive = info.sinfo_timetolive;
+	}
+
 	return 0;
 }
 
-/* 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
+/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
  *
  * Requests that the local SCTP stack use the enclosed peer address as
  * the association primary.  The enclosed address must be one of the
  * association peer's addresses.
  */
-static int sctp_setsockopt_peer_prim(struct sock *sk, char *optval, int optlen)
+static int sctp_setsockopt_primary_addr(struct sock *sk, char *optval,
+					int optlen)
 {
-	struct sctp_setpeerprim prim;
-	struct sctp_association *asoc;
-	union sctp_addr *addr;
+	struct sctp_prim prim;
 	struct sctp_transport *trans;
 
-	if (optlen != sizeof(struct sctp_setpeerprim))
+	if (optlen != sizeof(struct sctp_prim))
 		return -EINVAL;
 
-	if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim)))
+	if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
 		return -EFAULT;
 
-	asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
-	if (!asoc)
-		return -EINVAL;
-
-	/* Find the requested address. */
-	addr = (union sctp_addr *) &(prim.sspp_addr);
-
-	trans = sctp_assoc_lookup_paddr(asoc, addr);
+	trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id);
 	if (!trans)
-		return -ENOENT;
+		return -EINVAL;
 
-	sctp_assoc_set_primary(asoc, trans);
+	sctp_assoc_set_primary(trans->asoc, trans);
 
 	return 0;
 }
 
 /*
- *
  * 7.1.5 SCTP_NODELAY
  *
  * Turn on/off any Nagle-like algorithm.  This means that packets are
@@ -1461,17 +1785,235 @@ static int sctp_setsockopt_peer_prim(str
 static int sctp_setsockopt_nodelay(struct sock *sk, char *optval,
 					int optlen)
 {
-	__u8 val;
+	int val;
 
-	if (optlen < sizeof(__u8))
+	if (optlen < sizeof(int))
 		return -EINVAL;
-	if (get_user(val, (__u8 *)optval))
+	if (get_user(val, (int *)optval))
 		return -EFAULT;
 
 	sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1;
 	return 0;
 }
 
+/*
+ *
+ * 7.1.1 SCTP_RTOINFO
+ *
+ * The protocol parameters used to initialize and bound retransmission
+ * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access
+ * and modify these parameters.
+ * All parameters are time values, in milliseconds.  A value of 0, when
+ * modifying the parameters, indicates that the current value should not
+ * be changed.
+ *
+ */
+static int sctp_setsockopt_rtoinfo(struct sock *sk, char *optval, int optlen) {
+	struct sctp_rtoinfo rtoinfo;
+	struct sctp_association *asoc;
+
+	if (optlen != sizeof (struct sctp_rtoinfo))
+		return -EINVAL;
+
+	if (copy_from_user(&rtoinfo, optval, optlen))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
+
+	/* Set the values to the specific association */
+	if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
+		return -EINVAL;
+
+	if (asoc) {
+		if (rtoinfo.srto_initial != 0)
+			asoc->rto_initial = 
+				SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_initial);
+		if (rtoinfo.srto_max != 0)
+			asoc->rto_max = SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_max);
+		if (rtoinfo.srto_min != 0)
+			asoc->rto_min = SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_min);
+	} else {
+		/* If there is no association or the association-id = 0
+		 * set the values to the endpoint.
+		 */
+		struct sctp_opt *sp = sctp_sk(sk);
+
+		if (rtoinfo.srto_initial != 0)
+			sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
+		if (rtoinfo.srto_max != 0)
+			sp->rtoinfo.srto_max = rtoinfo.srto_max;
+		if (rtoinfo.srto_min != 0)
+			sp->rtoinfo.srto_min = rtoinfo.srto_min;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * 7.1.2 SCTP_ASSOCINFO
+ *
+ * This option is used to tune the the maximum retransmission attempts
+ * of the association.
+ * Returns an error if the new association retransmission value is
+ * greater than the sum of the retransmission value  of the peer.
+ * See [SCTP] for more information.
+ *
+ */
+static int sctp_setsockopt_associnfo(struct sock *sk, char *optval, int optlen)
+{
+
+	struct sctp_assocparams assocparams;
+	struct sctp_association *asoc;
+
+	if (optlen != sizeof(struct sctp_assocparams))
+		return -EINVAL;
+	if (copy_from_user(&assocparams, optval, optlen))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
+
+	if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))
+		return -EINVAL;
+
+	/* Set the values to the specific association */
+	if (asoc) {
+		if (assocparams.sasoc_asocmaxrxt != 0)
+			asoc->max_retrans = assocparams.sasoc_asocmaxrxt;
+		if (assocparams.sasoc_cookie_life != 0) {
+			asoc->cookie_life.tv_sec =
+					assocparams.sasoc_cookie_life / 1000;
+			asoc->cookie_life.tv_usec =
+					(assocparams.sasoc_cookie_life % 1000)
+					* 1000;
+		}
+	} else {
+		/* Set the values to the endpoint */
+		struct sctp_opt *sp = sctp_sk(sk);
+
+		if (assocparams.sasoc_asocmaxrxt != 0)
+			sp->assocparams.sasoc_asocmaxrxt =
+						assocparams.sasoc_asocmaxrxt;
+		if (assocparams.sasoc_cookie_life != 0)
+			sp->assocparams.sasoc_cookie_life =
+						assocparams.sasoc_cookie_life;
+	}
+	return 0;
+}
+
+/*
+ * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR)
+ *
+ * This socket option is a boolean flag which turns on or off mapped V4
+ * addresses.  If this option is turned on and the socket is type
+ * PF_INET6, then IPv4 addresses will be mapped to V6 representation.
+ * If this option is turned off, then no mapping will be done of V4
+ * addresses and a user will receive both PF_INET6 and PF_INET type
+ * addresses on the socket.
+ */
+static int sctp_setsockopt_mappedv4(struct sock *sk, char *optval, int optlen)
+{
+	int val;
+	struct sctp_opt *sp = sctp_sk(sk);
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+	if (get_user(val, (int *)optval))
+		return -EFAULT;
+	if (val)
+		sp->v4mapped = 1;
+	else
+		sp->v4mapped = 0;
+
+	return 0;
+}
+
+/*
+ * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
+ *
+ * This socket option specifies the maximum size to put in any outgoing
+ * SCTP chunk.  If a message is larger than this size it will be
+ * fragmented by SCTP into the specified size.  Note that the underlying
+ * SCTP implementation may fragment into smaller sized chunks when the
+ * PMTU of the underlying association is smaller than the value set by
+ * the user.
+ */
+static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen)
+{
+	int val;
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+	if (get_user(val, (int *)optval))
+		return -EFAULT;
+	if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
+		return -EINVAL;
+	sctp_sk(sk)->user_frag = val;
+
+	return 0;
+}
+
+
+/*
+ *  7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
+ *
+ *   Requests that the peer mark the enclosed address as the association
+ *   primary. The enclosed address must be one of the association's
+ *   locally bound addresses. The following structure is used to make a
+ *   set primary request:
+ */
+static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
+					     int optlen)
+{
+	struct sctp_opt		*sp;
+	struct sctp_endpoint	*ep;
+	struct sctp_association	*asoc = NULL;
+	struct sctp_setpeerprim	prim;
+	struct sctp_chunk	*chunk;
+	int 			err;
+
+	sp = sctp_sk(sk);
+	ep = sp->ep;
+
+	if (!sctp_addip_enable)
+		return -EPERM;
+
+	if (optlen != sizeof(struct sctp_setpeerprim))
+		return -EINVAL;
+
+	if (copy_from_user(&prim, optval, optlen))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
+	if (!asoc) 
+		return -EINVAL;
+
+	if (!asoc->peer.asconf_capable)
+		return -EPERM;
+
+	if (asoc->peer.addip_disabled_mask & SCTP_PARAM_SET_PRIMARY)
+		return -EPERM;
+
+	if (!sctp_state(asoc, ESTABLISHED))
+		return -ENOTCONN;
+
+	if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
+		return -EADDRNOTAVAIL;
+
+	/* Create an ASCONF chunk with SET_PRIMARY parameter	*/
+	chunk = sctp_make_asconf_set_prim(asoc,
+					  (union sctp_addr *)&prim.sspp_addr);
+	if (!chunk)
+		return -ENOMEM;
+
+	err = sctp_send_asconf(asoc, chunk);
+
+	SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n");
+
+	return err;
+}
+
+
 /* API 6.2 setsockopt(), getsockopt()
  *
  * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -1495,7 +2037,6 @@ SCTP_STATIC int sctp_setsockopt(struct s
 				char *optval, int optlen)
 {
 	int retval = 0;
-	char *tmp;
 
 	SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p... optname: %d)\n",
 			  sk, optname);
@@ -1512,41 +2053,26 @@ SCTP_STATIC int sctp_setsockopt(struct s
 		goto out_nounlock;
 	}
 
-	sctp_lock_sock(sk);
-
-	switch (optname) {
-	case SCTP_SOCKOPT_DEBUG_NAME:
-		/* BUG! we don't ever seem to free this memory. --jgrimm */
-		if (NULL == (tmp = kmalloc(optlen + 1, GFP_KERNEL))) {
-			retval = -ENOMEM;
-			goto out_unlock;
-		}
-
-		if (copy_from_user(tmp, optval, optlen)) {
-			retval = -EFAULT;
-			goto out_unlock;
-		}
-		tmp[optlen] = '\000';
-		sctp_sk(sk)->ep->debug_name = tmp;
-		break;
+	sctp_lock_sock(sk);
 
+	switch (optname) {
 	case SCTP_SOCKOPT_BINDX_ADD:
 		/* 'optlen' is the size of the addresses buffer. */
-		retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *)
-					       optval, optlen, BINDX_ADD_ADDR);
+		retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval,
+					       optlen, SCTP_BINDX_ADD_ADDR);
 		break;
 
 	case SCTP_SOCKOPT_BINDX_REM:
 		/* 'optlen' is the size of the addresses buffer. */
-		retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *)
-					       optval, optlen, BINDX_REM_ADDR);
+		retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval,
+					       optlen, SCTP_BINDX_REM_ADDR);
 		break;
 
 	case SCTP_DISABLE_FRAGMENTS:
 		retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);
 		break;
 
-	case SCTP_SET_EVENTS:
+	case SCTP_EVENTS:
 		retval = sctp_setsockopt_events(sk, optval, optlen);
 		break;
 
@@ -1554,33 +2080,43 @@ SCTP_STATIC int sctp_setsockopt(struct s
 		retval = sctp_setsockopt_autoclose(sk, optval, optlen);
 		break;
 
-	case SCTP_SET_PEER_ADDR_PARAMS:
+	case SCTP_PEER_ADDR_PARAMS:
 		retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
 		break;
 
 	case SCTP_INITMSG:
 		retval = sctp_setsockopt_initmsg(sk, optval, optlen);
 		break;
-
-	case SCTP_SET_DEFAULT_SEND_PARAM:
+	case SCTP_DEFAULT_SEND_PARAM:
 		retval = sctp_setsockopt_default_send_param(sk, optval,
 							    optlen);
 		break;
-
+	case SCTP_PRIMARY_ADDR:
+		retval = sctp_setsockopt_primary_addr(sk, optval, optlen);
+		break;
 	case SCTP_SET_PEER_PRIMARY_ADDR:
-		retval = sctp_setsockopt_peer_prim(sk, optval, optlen);
+		retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen);
 		break;
-
 	case SCTP_NODELAY:
 		retval = sctp_setsockopt_nodelay(sk, optval, optlen);
 		break;
-
+	case SCTP_RTOINFO:
+		retval = sctp_setsockopt_rtoinfo(sk, optval, optlen);
+		break;
+	case SCTP_ASSOCINFO:
+		retval = sctp_setsockopt_associnfo(sk, optval, optlen);
+		break;
+	case SCTP_I_WANT_MAPPED_V4_ADDR:
+		retval = sctp_setsockopt_mappedv4(sk, optval, optlen);
+		break;
+	case SCTP_MAXSEG:
+		retval = sctp_setsockopt_maxseg(sk, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
 	};
 
-out_unlock:
 	sctp_release_sock(sk);
 
 out_nounlock:
@@ -1629,9 +2165,8 @@ SCTP_STATIC int sctp_connect(struct sock
 	 * is already connected.
 	 * It cannot be done even on a TCP-style listening socket.
 	 */
-	if ((SCTP_SS_ESTABLISHED == sk->state) ||
-	    ((SCTP_SOCKET_TCP == sp->type) &&
-	     (SCTP_SS_LISTENING == sk->state))) {
+	if (sctp_sstate(sk, ESTABLISHED) ||
+	    (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
 		err = -EISCONN;
 		goto out_unlock;
 	}
@@ -1700,11 +2235,11 @@ SCTP_STATIC int sctp_connect(struct sock
 	}
 
 	/* Initialize sk's dport and daddr for getpeername() */
-	(sk)->dport = htons(asoc->peer.port);
+	sk->dport = htons(asoc->peer.port);
 	af = sctp_get_af_specific(to.sa.sa_family);
-	af->to_sk_daddr(&to, sk); 
+	af->to_sk_daddr(&to, sk);
 
-	timeo = sock_sndtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK);
+	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
 	err = sctp_wait_for_connect(asoc, &timeo);
 
 out_unlock:
@@ -1740,17 +2275,17 @@ SCTP_STATIC struct sock *sctp_accept(str
 	sp = sctp_sk(sk);
 	ep = sp->ep;
 
-	if (SCTP_SOCKET_TCP != sp->type) {
+	if (!sctp_style(sk, TCP)) {
 		error = -EOPNOTSUPP;
 		goto out;
 	}
 
-	if (SCTP_SS_LISTENING != sk->state) {
+	if (!sctp_sstate(sk, LISTENING)) {
 		error = -EINVAL;
 		goto out;
 	}
 
-	timeo = sock_rcvtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK);
+	timeo = sock_rcvtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
 
 	error = sctp_wait_for_accept(sk, timeo);
 	if (error)
@@ -1791,17 +2326,14 @@ SCTP_STATIC int sctp_ioctl(struct sock *
 SCTP_STATIC int sctp_init_sock(struct sock *sk)
 {
 	struct sctp_endpoint *ep;
-	struct sctp_protocol *proto;
 	struct sctp_opt *sp;
 
 	SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk);
 
-	proto = sctp_get_protocol();
-
 	sp = sctp_sk(sk);
 
 	/* Initialize the SCTP per socket area.  */
-	switch (sk->type) {
+	switch (sk->sk_type) {
 	case SOCK_SEQPACKET:
 		sp->type = SCTP_SOCKET_UDP;
 		break;
@@ -1812,45 +2344,51 @@ SCTP_STATIC int sctp_init_sock(struct so
 		return -ESOCKTNOSUPPORT;
 	}
 
-	/* FIXME:  The next draft (04) of the SCTP Sockets Extensions
-	 * should include a socket option for manipulating these
-	 * message parameters (and a few others).
+	/* Initialize default send parameters. These parameters can be
+	 * modified with the SCTP_DEFAULT_SEND_PARAM socket option.
 	 */
 	sp->default_stream = 0;
 	sp->default_ppid = 0;
+	sp->default_flags = 0;
+	sp->default_context = 0;
+	sp->default_timetolive = 0;
 
 	/* Initialize default setup parameters. These parameters
 	 * can be modified with the SCTP_INITMSG socket option or
 	 * overridden by the SCTP_INIT CMSG.
 	 */
-	sp->initmsg.sinit_num_ostreams   = proto->max_outstreams;
-	sp->initmsg.sinit_max_instreams  = proto->max_instreams;
-	sp->initmsg.sinit_max_attempts   = proto->max_retrans_init;
-	sp->initmsg.sinit_max_init_timeo = proto->rto_max / HZ;
+	sp->initmsg.sinit_num_ostreams   = sctp_max_outstreams;
+	sp->initmsg.sinit_max_instreams  = sctp_max_instreams;
+	sp->initmsg.sinit_max_attempts   = sctp_max_retrans_init;
+	sp->initmsg.sinit_max_init_timeo = JIFFIES_TO_MSECS(sctp_rto_max);
 
 	/* Initialize default RTO related parameters.  These parameters can
 	 * be modified for with the SCTP_RTOINFO socket option.
-	 * FIXME: These are not used yet.
 	 */
-	sp->rtoinfo.srto_initial = proto->rto_initial;
-	sp->rtoinfo.srto_max     = proto->rto_max;
-	sp->rtoinfo.srto_min     = proto->rto_min;
-
-	/* Initialize default event subscriptions.
-	 * the struct sock is initialized to zero, so only
-	 * enable the events needed.  By default, UDP-style
-	 * sockets enable io and association change notifications.
-	 */
-	if (SCTP_SOCKET_UDP == sp->type) {
-		sp->subscribe.sctp_data_io_event     = 1;
-		sp->subscribe.sctp_association_event = 1;
-	}
+	sp->rtoinfo.srto_initial = JIFFIES_TO_MSECS(sctp_rto_initial);
+	sp->rtoinfo.srto_max     = JIFFIES_TO_MSECS(sctp_rto_max);
+	sp->rtoinfo.srto_min     = JIFFIES_TO_MSECS(sctp_rto_min);
+
+	/* Initialize default association related parameters. These parameters
+	 * can be modified with the SCTP_ASSOCINFO socket option.
+	 */
+	sp->assocparams.sasoc_asocmaxrxt = sctp_max_retrans_association;
+	sp->assocparams.sasoc_number_peer_destinations = 0;
+	sp->assocparams.sasoc_peer_rwnd = 0;
+	sp->assocparams.sasoc_local_rwnd = 0;
+	sp->assocparams.sasoc_cookie_life = 
+		JIFFIES_TO_MSECS(sctp_valid_cookie_life);
+
+	/* Initialize default event subscriptions. By default, all the
+	 * options are off. 
+	 */
+	memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe));
 
 	/* Default Peer Address Parameters.  These defaults can
-	 * be modified via SCTP_SET_PEER_ADDR_PARAMS
+	 * be modified via SCTP_PEER_ADDR_PARAMS
 	 */
-	sp->paddrparam.spp_hbinterval = proto->hb_interval / HZ;
-	sp->paddrparam.spp_pathmaxrxt = proto->max_retrans_path;
+	sp->paddrparam.spp_hbinterval = JIFFIES_TO_MSECS(sctp_hb_interval);
+	sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
 
 	/* If enabled no SCTP message fragmentation will be performed.
 	 * Configure through SCTP_DISABLE_FRAGMENTS socket option.
@@ -1860,13 +2398,20 @@ SCTP_STATIC int sctp_init_sock(struct so
 	/* Turn on/off any Nagle-like algorithm.  */
 	sp->nodelay           = 1;
 
+	/* Enable by default. */
+	sp->v4mapped          = 1;
+
 	/* Auto-close idle associations after the configured
 	 * number of seconds.  A value of 0 disables this
 	 * feature.  Configure through the SCTP_AUTOCLOSE socket option,
 	 * for UDP-style sockets only.
 	 */
 	sp->autoclose         = 0;
-	sp->pf = sctp_get_pf_specific(sk->family);
+
+	/* User specified fragmentation limit. */
+	sp->user_frag         = 0;
+
+	sp->pf = sctp_get_pf_specific(sk->sk_family);
 
 	/* Control variables for partial data delivery. */
 	sp->pd_mode           = 0;
@@ -1922,7 +2467,7 @@ SCTP_STATIC void sctp_shutdown(struct so
 	struct sctp_endpoint *ep;
 	struct sctp_association *asoc;
 
-	if (SCTP_SOCKET_TCP != sctp_sk(sk)->type)
+	if (!sctp_style(sk, TCP))
 		return;
 
 	if (how & SEND_SHUTDOWN) {
@@ -1974,17 +2519,25 @@ static int sctp_getsockopt_sctp_status(s
 	status.sstat_state = asoc->state;
 	status.sstat_rwnd =  asoc->peer.rwnd;
 	status.sstat_unackdata = asoc->unack_data;
-	status.sstat_penddata = asoc->peer.tsn_map.pending_data;
+
+	status.sstat_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map);
 	status.sstat_instrms = asoc->c.sinit_max_instreams;
 	status.sstat_outstrms = asoc->c.sinit_num_ostreams;
+	/* Just in time frag_point update. */
+	if (sctp_sk(sk)->user_frag)
+		asoc->frag_point
+			= min_t(int, asoc->frag_point, sctp_sk(sk)->user_frag);
 	status.sstat_fragmentation_point = asoc->frag_point;
 	status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
 	memcpy(&status.sstat_primary.spinfo_address,
 	       &(transport->ipaddr), sizeof(union sctp_addr));
+	/* Map ipv4 address into v4-mapped-on-v6 address.  */
+	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
+		(union sctp_addr *)&status.sstat_primary.spinfo_address);
 	status.sstat_primary.spinfo_state = transport->active;
 	status.sstat_primary.spinfo_cwnd = transport->cwnd;
 	status.sstat_primary.spinfo_srtt = transport->srtt;
-	status.sstat_primary.spinfo_rto = transport->rto;
+	status.sstat_primary.spinfo_rto = JIFFIES_TO_MSECS(transport->rto);
 	status.sstat_primary.spinfo_mtu = transport->pmtu;
 
 	if (put_user(len, optlen)) {
@@ -2005,6 +2558,64 @@ out:
 	return (retval);
 }
 
+
+/* 7.2.2 Peer Address Information (SCTP_GET_PEER_ADDR_INFO)
+ *
+ * Applications can retrieve information about a specific peer address
+ * of an association, including its reachability state, congestion
+ * window, and retransmission timer values.  This information is
+ * read-only.
+ */
+static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
+					  char *optval, int *optlen)
+{
+	struct sctp_paddrinfo pinfo;
+	struct sctp_transport *transport;
+	int retval = 0;
+
+	if (len != sizeof(pinfo)) {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	if (copy_from_user(&pinfo, optval, sizeof(pinfo))) {
+		retval = -EFAULT;
+		goto out;
+	}
+
+	transport = sctp_addr_id2transport(sk, &pinfo.spinfo_address,
+					   pinfo.spinfo_assoc_id);
+	if (!transport)
+		return -EINVAL;
+
+	pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
+	pinfo.spinfo_state = transport->active;
+	pinfo.spinfo_cwnd = transport->cwnd;
+	pinfo.spinfo_srtt = transport->srtt;
+	pinfo.spinfo_rto = JIFFIES_TO_MSECS(transport->rto);
+	pinfo.spinfo_mtu = transport->pmtu;
+
+	if (put_user(len, optlen)) {
+		retval = -EFAULT;
+		goto out;
+	}
+
+	if (copy_to_user(optval, &pinfo, len)) {
+		retval = -EFAULT;
+		goto out;
+	}
+
+out:
+	return (retval);
+}
+
+/* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS)
+ *
+ * This option is a on/off flag.  If enabled no SCTP message
+ * fragmentation will be performed.  Instead if a message being sent
+ * exceeds the current PMTU size, the message will NOT be sent and
+ * instead a error will be indicated to the user.
+ */
 static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
 						    char *optval, int *optlen)
 {
@@ -2022,7 +2633,13 @@ static int sctp_getsockopt_disable_fragm
 	return 0;
 }
 
-static int sctp_getsockopt_set_events(struct sock *sk, int len, char *optval, int *optlen)
+/* 7.1.15 Set notification and ancillary events (SCTP_EVENTS)
+ *
+ * This socket option is used to specify various notifications and
+ * ancillary data the user wishes to receive.
+ */
+static int sctp_getsockopt_events(struct sock *sk, int len, char *optval,
+				  int *optlen)
 {
 	if (len != sizeof(struct sctp_event_subscribe))
 		return -EINVAL;
@@ -2031,10 +2648,21 @@ static int sctp_getsockopt_set_events(st
 	return 0;
 }
 
+/* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE)
+ *
+ * This socket option is applicable to the UDP-style socket only.  When
+ * set it will cause associations that are idle for more than the
+ * specified number of seconds to automatically close.  An association
+ * being idle is defined an association that has NOT sent or received
+ * user data.  The special value of '0' indicates that no automatic
+ * close of any associations should be performed.  The option expects an
+ * integer defining the number of seconds of idle time before an
+ * association is closed.
+ */
 static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int *optlen)
 {
 	/* Applicable to UDP-style socket only */
-	if (SCTP_SOCKET_TCP == sctp_sk(sk)->type)
+	if (sctp_style(sk, TCP))
 		return -EOPNOTSUPP;
 	if (len != sizeof(int))
 		return -EINVAL;
@@ -2054,11 +2682,11 @@ SCTP_STATIC int sctp_do_peeloff(struct s
 	/* An association cannot be branched off from an already peeled-off
 	 * socket, nor is this supported for tcp style sockets.
 	 */
-	if (SCTP_SOCKET_UDP != sctp_sk(sk)->type)
+	if (!sctp_style(sk, UDP))
 		return -EINVAL;
 
 	/* Create a new socket.  */
-	err = sock_create(sk->family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
+	err = sock_create(sk->sk_family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
 	if (err < 0)
 		return err;
 
@@ -2114,12 +2742,41 @@ out:
 	return retval;
 }
 
+/* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
+ *
+ * Applications can enable or disable heartbeats for any peer address of
+ * an association, modify an address's heartbeat interval, force a
+ * heartbeat to be sent immediately, and adjust the address's maximum
+ * number of retransmissions sent before an address is considered
+ * unreachable.  The following structure is used to access and modify an
+ * address's parameters:
+ *
+ *  struct sctp_paddrparams {
+ *      sctp_assoc_t            spp_assoc_id;
+ *      struct sockaddr_storage spp_address;
+ *      uint32_t                spp_hbinterval;
+ *      uint16_t                spp_pathmaxrxt;
+ *  };
+ *
+ *   spp_assoc_id    - (UDP style socket) This is filled in the application,
+ *                     and identifies the association for this query.
+ *   spp_address     - This specifies which address is of interest.
+ *   spp_hbinterval  - This contains the value of the heartbeat interval,
+ *                     in milliseconds.  A value of 0, when modifying the
+ *                     parameter, specifies that the heartbeat on this
+ *                     address should be disabled. A value of UINT32_MAX
+ *                     (4294967295), when modifying the parameter,
+ *                     specifies that a heartbeat should be sent
+ *                     immediately to the peer address, and the current
+ *                     interval should remain unchanged.
+ *   spp_pathmaxrxt  - This contains the maximum number of
+ *                     retransmissions before this address shall be
+ *                     considered unreachable.
+ */
 static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
 						char *optval, int *optlen)
 {
 	struct sctp_paddrparams params;
-	struct sctp_association *asoc;
-	union sctp_addr *addr;
 	struct sctp_transport *trans;
 
 	if (len != sizeof(struct sctp_paddrparams))
@@ -2127,15 +2784,10 @@ static int sctp_getsockopt_peer_addr_par
 	if (copy_from_user(&params, optval, *optlen))
 		return -EFAULT;
 
-	asoc = sctp_id2assoc(sk, params.spp_assoc_id);
-	if (!asoc)
-		return -EINVAL;
-
-	addr = (union sctp_addr *) &(params.spp_address);
-
-	trans = sctp_assoc_lookup_paddr(asoc, addr);
+	trans = sctp_addr_id2transport(sk, &params.spp_address,
+				       params.spp_assoc_id);
 	if (!trans)
-		return -ENOENT;
+		return -EINVAL;
 
 	/* The value of the heartbeat interval, in milliseconds. A value of 0,
 	 * when modifying the parameter, specifies that the heartbeat on this
@@ -2144,7 +2796,7 @@ static int sctp_getsockopt_peer_addr_par
 	if (!trans->hb_allowed)
 		params.spp_hbinterval = 0;
 	else
-		params.spp_hbinterval = trans->hb_interval * 1000 / HZ;
+		params.spp_hbinterval = JIFFIES_TO_MSECS(trans->hb_interval);
 
 	/* spp_pathmaxrxt contains the maximum number of retransmissions
 	 * before this address shall be considered unreachable.
@@ -2153,11 +2805,24 @@ static int sctp_getsockopt_peer_addr_par
 
 	if (copy_to_user(optval, &params, len))
 		return -EFAULT;
-	*optlen = len;
+
+	if (put_user(len, optlen))
+		return -EFAULT;
 
 	return 0;
 }
 
+/* 7.1.3 Initialization Parameters (SCTP_INITMSG)
+ *
+ * Applications can specify protocol parameters for the default association
+ * initialization.  The option name argument to setsockopt() and getsockopt()
+ * is SCTP_INITMSG.
+ *
+ * Setting initialization parameters is effective only on an unconnected
+ * socket (for UDP-style sockets only future associations are effected
+ * by the change).  With TCP-style sockets, this option is inherited by
+ * sockets derived from a listener socket.
+ */
 static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *optlen)
 {
 	if (len != sizeof(struct sctp_initmsg))
@@ -2168,7 +2833,7 @@ static int sctp_getsockopt_initmsg(struc
 }
 
 static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
-					char *optval, int *optlen)
+					  char *optval, int *optlen)
 {
 	sctp_assoc_t id;
 	struct sctp_association *asoc;
@@ -2181,9 +2846,7 @@ static int sctp_getsockopt_peer_addrs_nu
 	if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
 		return -EFAULT;
 
-	/*
-	 *  For UDP-style sockets, id specifies the association to query.
-	 */
+	/* For UDP-style sockets, id specifies the association to query.  */
 	asoc = sctp_id2assoc(sk, id);
 	if (!asoc)
 		return -EINVAL;
@@ -2191,21 +2854,22 @@ static int sctp_getsockopt_peer_addrs_nu
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
 		cnt ++;
 	}
-	if (copy_to_user(optval, &cnt, sizeof(int)))
-		return -EFAULT;
 
-	return 0;
+	return cnt;
 }
 
 static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
-				char *optval, int *optlen)
+				      char *optval, int *optlen)
 {
 	struct sctp_association *asoc;
 	struct list_head *pos;
 	int cnt = 0;
 	struct sctp_getaddrs getaddrs;
 	struct sctp_transport *from;
-	struct sockaddr_storage *to;
+	void *to;
+	union sctp_addr temp;
+	struct sctp_opt *sp = sctp_sk(sk);
+	int addrlen;
 
 	if (len != sizeof(struct sctp_getaddrs))
 		return -EINVAL;
@@ -2214,19 +2878,22 @@ static int sctp_getsockopt_peer_addrs(st
 		return -EFAULT;
 
 	if (getaddrs.addr_num <= 0) return -EINVAL;
-	/*
-	 *  For UDP-style sockets, id specifies the association to query.
-	 */
+
+	/* For UDP-style sockets, id specifies the association to query.  */
 	asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
 	if (!asoc)
 		return -EINVAL;
 
-	to = getaddrs.addrs;
+	to = (void *)getaddrs.addrs;
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
 		from = list_entry(pos, struct sctp_transport, transports);
-		if (copy_to_user(to, &from->ipaddr, sizeof(from->ipaddr)))
+		memcpy(&temp, &from->ipaddr, sizeof(temp));
+		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+		addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
+		temp.v4.sin_port = htons(temp.v4.sin_port);
+		if (copy_to_user(to, &temp, addrlen))
 			return -EFAULT;
-		to ++;
+		to += addrlen ;
 		cnt ++;
 		if (cnt >= getaddrs.addr_num) break;
 	}
@@ -2241,7 +2908,7 @@ static int sctp_getsockopt_local_addrs_n
 						char *optval, int *optlen)
 {
 	sctp_assoc_t id;
-	sctp_bind_addr_t *bp;
+	struct sctp_bind_addr *bp;
 	struct sctp_association *asoc;
 	struct list_head *pos;
 	int cnt = 0;
@@ -2270,22 +2937,23 @@ static int sctp_getsockopt_local_addrs_n
 	list_for_each(pos, &bp->address_list) {
 		cnt ++;
 	}
-	if (copy_to_user(optval, &cnt, sizeof(int)))
-		return -EFAULT;
 
-	return 0;
+	return cnt;
 }
 
 static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
 					char *optval, int *optlen)
 {
-	sctp_bind_addr_t *bp;
+	struct sctp_bind_addr *bp;
 	struct sctp_association *asoc;
 	struct list_head *pos;
 	int cnt = 0;
 	struct sctp_getaddrs getaddrs;
-	struct sockaddr_storage_list *from;
-	struct sockaddr_storage *to;
+	struct sctp_sockaddr_entry *from;
+	void *to;
+	union sctp_addr temp;
+	struct sctp_opt *sp = sctp_sk(sk);
+	int addrlen;
 
 	if (len != sizeof(struct sctp_getaddrs))
 		return -EINVAL;
@@ -2309,14 +2977,18 @@ static int sctp_getsockopt_local_addrs(s
 		bp = &asoc->base.bind_addr;
 	}
 
-	to = getaddrs.addrs;
+	to = (void *)getaddrs.addrs;
 	list_for_each(pos, &bp->address_list) {
 		from = list_entry(pos,
-				struct sockaddr_storage_list,
+				struct sctp_sockaddr_entry,
 				list);
-		if (copy_to_user(to, &from->a, sizeof(from->a)))
+		memcpy(&temp, &from->a, sizeof(temp));
+		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
+		temp.v4.sin_port = htons(temp.v4.sin_port);
+		if (copy_to_user(to, &temp, addrlen))
 			return -EFAULT;
-		to ++;
+		to += addrlen;
 		cnt ++;
 		if (cnt >= getaddrs.addr_num) break;
 	}
@@ -2327,35 +2999,43 @@ static int sctp_getsockopt_local_addrs(s
 	return 0;
 }
 
-/* 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
+/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
  *
  * Requests that the local SCTP stack use the enclosed peer address as
  * the association primary.  The enclosed address must be one of the
  * association peer's addresses.
  */
-static int sctp_getsockopt_peer_prim(struct sock *sk, int len,
-				char *optval, int *optlen)
+static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
+					char *optval, int *optlen)
 {
-	struct sctp_setpeerprim prim;
+	struct sctp_prim prim;
 	struct sctp_association *asoc;
+	struct sctp_opt *sp = sctp_sk(sk);
 
-	if (len != sizeof(struct sctp_setpeerprim))
+	if (len != sizeof(struct sctp_prim))
 		return -EINVAL;
 
-	if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim)))
+	if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
 		return -EFAULT;
 
-	asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
+	asoc = sctp_id2assoc(sk, prim.ssp_assoc_id);
 	if (!asoc)
 		return -EINVAL;
 
 	if (!asoc->peer.primary_path)
 		return -ENOTCONN;
-
-	memcpy(&prim.sspp_addr, &asoc->peer.primary_path->ipaddr,
+	
+	asoc->peer.primary_path->ipaddr.v4.sin_port =
+		htons(asoc->peer.primary_path->ipaddr.v4.sin_port);
+	memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
 	       sizeof(union sctp_addr));
+	asoc->peer.primary_path->ipaddr.v4.sin_port =
+		ntohs(asoc->peer.primary_path->ipaddr.v4.sin_port);
+
+	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
+			(union sctp_addr *)&prim.ssp_addr);
 
-	if (copy_to_user(optval, &prim, sizeof(struct sctp_setpeerprim)))
+	if (copy_to_user(optval, &prim, sizeof(struct sctp_prim)))
 		return -EFAULT;
 
 	return 0;
@@ -2363,12 +3043,14 @@ static int sctp_getsockopt_peer_prim(str
 
 /*
  *
- * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM)
+ * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM)
  *
  *   Applications that wish to use the sendto() system call may wish to
  *   specify a default set of parameters that would normally be supplied
  *   through the inclusion of ancillary data.  This socket option allows
  *   such an application to set the default sctp_sndrcvinfo structure.
+
+
  *   The application that wishes to use this socket option simply passes
  *   in to this call the sctp_sndrcvinfo structure defined in Section
  *   5.2.2) The input parameters accepted by this call include
@@ -2383,6 +3065,7 @@ static int sctp_getsockopt_default_send_
 {
 	struct sctp_sndrcvinfo info;
 	struct sctp_association *asoc;
+	struct sctp_opt *sp = sctp_sk(sk);
 
 	if (len != sizeof(struct sctp_sndrcvinfo))
 		return -EINVAL;
@@ -2390,14 +3073,22 @@ static int sctp_getsockopt_default_send_
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
-	if (!asoc)
+	if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP))
 		return -EINVAL;
 
-	info.sinfo_stream = asoc->defaults.stream;
-	info.sinfo_flags = asoc->defaults.flags;
-	info.sinfo_ppid = asoc->defaults.ppid;
-	info.sinfo_context = asoc->defaults.context;
-	info.sinfo_timetolive = asoc->defaults.timetolive;
+	if (asoc) {
+		info.sinfo_stream = asoc->default_stream;
+		info.sinfo_flags = asoc->default_flags;
+		info.sinfo_ppid = asoc->default_ppid;
+		info.sinfo_context = asoc->default_context;
+		info.sinfo_timetolive = asoc->default_timetolive;
+	} else {
+		info.sinfo_stream = sp->default_stream;
+		info.sinfo_flags = sp->default_flags;
+		info.sinfo_ppid = sp->default_ppid;
+		info.sinfo_context = sp->default_context;
+		info.sinfo_timetolive = sp->default_timetolive;
+	}
 
 	if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo)))
 		return -EFAULT;
@@ -2416,14 +3107,14 @@ static int sctp_getsockopt_default_send_
  */
 
 static int sctp_getsockopt_nodelay(struct sock *sk, int len,
-					char *optval, int *optlen)
+				   char *optval, int *optlen)
 {
-	__u8 val;
+	int val;
 
-	if (len < sizeof(__u8))
+	if (len < sizeof(int))
 		return -EINVAL;
 
-	len = sizeof(__u8);
+	len = sizeof(int);
 	val = (sctp_sk(sk)->nodelay == 1);
 	if (put_user(len, optlen))
 		return -EFAULT;
@@ -2432,6 +3123,185 @@ static int sctp_getsockopt_nodelay(struc
 	return 0;
 }
 
+/*
+ *
+ * 7.1.1 SCTP_RTOINFO
+ *
+ * The protocol parameters used to initialize and bound retransmission
+ * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access
+ * and modify these parameters.
+ * All parameters are time values, in milliseconds.  A value of 0, when
+ * modifying the parameters, indicates that the current value should not
+ * be changed.
+ *
+ */
+static int sctp_getsockopt_rtoinfo(struct sock *sk, int len, char *optval,
+				int *optlen) {
+	struct sctp_rtoinfo rtoinfo;
+	struct sctp_association *asoc;
+
+	if (len != sizeof (struct sctp_rtoinfo))
+		return -EINVAL;
+
+	if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo)))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
+
+	if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
+		return -EINVAL;
+
+	/* Values corresponding to the specific association. */
+	if (asoc) {
+		rtoinfo.srto_initial = JIFFIES_TO_MSECS(asoc->rto_initial);
+		rtoinfo.srto_max = JIFFIES_TO_MSECS(asoc->rto_max);
+		rtoinfo.srto_min = JIFFIES_TO_MSECS(asoc->rto_min);
+	} else {
+		/* Values corresponding to the endpoint. */
+		struct sctp_opt *sp = sctp_sk(sk);
+
+		rtoinfo.srto_initial = sp->rtoinfo.srto_initial;
+		rtoinfo.srto_max = sp->rtoinfo.srto_max;
+		rtoinfo.srto_min = sp->rtoinfo.srto_min;
+	}
+
+	if (put_user(len, optlen))
+		return -EFAULT;
+
+	if (copy_to_user(optval, &rtoinfo, len))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ *
+ * 7.1.2 SCTP_ASSOCINFO
+ *
+ * This option is used to tune the the maximum retransmission attempts
+ * of the association.
+ * Returns an error if the new association retransmission value is
+ * greater than the sum of the retransmission value  of the peer.
+ * See [SCTP] for more information.
+ *
+ */
+static int sctp_getsockopt_associnfo(struct sock *sk, int len, char *optval,
+				     int *optlen)
+{
+
+	struct sctp_assocparams assocparams;
+	struct sctp_association *asoc;
+	struct list_head *pos;
+	int cnt = 0;
+
+	if (len != sizeof (struct sctp_assocparams))
+		return -EINVAL;
+
+	if (copy_from_user(&assocparams, optval,
+			sizeof (struct sctp_assocparams)))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
+
+	if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))
+		return -EINVAL;
+
+	/* Values correspoinding to the specific association */
+	if (assocparams.sasoc_assoc_id != 0) {
+		assocparams.sasoc_asocmaxrxt = asoc->max_retrans;
+		assocparams.sasoc_peer_rwnd = asoc->peer.rwnd;
+		assocparams.sasoc_local_rwnd = asoc->a_rwnd;
+		assocparams.sasoc_cookie_life = (asoc->cookie_life.tv_sec
+						* 1000) +
+						(asoc->cookie_life.tv_usec
+						/ 1000);
+
+		list_for_each(pos, &asoc->peer.transport_addr_list) {
+			cnt ++;
+		}
+
+		assocparams.sasoc_number_peer_destinations = cnt;
+	} else {
+		/* Values corresponding to the endpoint */
+		struct sctp_opt *sp = sctp_sk(sk);
+
+		assocparams.sasoc_asocmaxrxt = sp->assocparams.sasoc_asocmaxrxt;
+		assocparams.sasoc_peer_rwnd = sp->assocparams.sasoc_peer_rwnd;
+		assocparams.sasoc_local_rwnd = sp->assocparams.sasoc_local_rwnd;
+		assocparams.sasoc_cookie_life =
+					sp->assocparams.sasoc_cookie_life;
+		assocparams.sasoc_number_peer_destinations =
+					sp->assocparams.
+					sasoc_number_peer_destinations;
+	}
+
+	if (put_user(len, optlen))
+		return -EFAULT;
+
+	if (copy_to_user(optval, &assocparams, len))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR)
+ *
+ * This socket option is a boolean flag which turns on or off mapped V4
+ * addresses.  If this option is turned on and the socket is type
+ * PF_INET6, then IPv4 addresses will be mapped to V6 representation.
+ * If this option is turned off, then no mapping will be done of V4
+ * addresses and a user will receive both PF_INET6 and PF_INET type
+ * addresses on the socket.
+ */
+static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
+				    char *optval, int *optlen)
+{
+	int val;
+	struct sctp_opt *sp = sctp_sk(sk);
+
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+	val = sp->v4mapped;
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
+ *
+ * This socket option specifies the maximum size to put in any outgoing
+ * SCTP chunk.  If a message is larger than this size it will be
+ * fragmented by SCTP into the specified size.  Note that the underlying
+ * SCTP implementation may fragment into smaller sized chunks when the
+ * PMTU of the underlying association is smaller than the value set by
+ * the user.
+ */
+static int sctp_getsockopt_maxseg(struct sock *sk, int len,
+				  char *optval, int *optlen)
+{
+	int val;
+
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+
+	val = sctp_sk(sk)->user_frag;
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
+
+	return 0;
+}
+
 SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
 				char *optval, int *optlen)
 {
@@ -2466,8 +3336,8 @@ SCTP_STATIC int sctp_getsockopt(struct s
 		retval = sctp_getsockopt_disable_fragments(sk, len, optval,
 							   optlen);
 		break;
-	case SCTP_SET_EVENTS:
-		retval = sctp_getsockopt_set_events(sk, len, optval, optlen);
+	case SCTP_EVENTS:
+		retval = sctp_getsockopt_events(sk, len, optval, optlen);
 		break;
 	case SCTP_AUTOCLOSE:
 		retval = sctp_getsockopt_autoclose(sk, len, optval, optlen);
@@ -2475,7 +3345,7 @@ SCTP_STATIC int sctp_getsockopt(struct s
 	case SCTP_SOCKOPT_PEELOFF:
 		retval = sctp_getsockopt_peeloff(sk, len, optval, optlen);
 		break;
-	case SCTP_GET_PEER_ADDR_PARAMS:
+	case SCTP_PEER_ADDR_PARAMS:
 		retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
 							  optlen);
 		break;
@@ -2498,16 +3368,32 @@ SCTP_STATIC int sctp_getsockopt(struct s
 		retval = sctp_getsockopt_local_addrs(sk, len, optval,
 						     optlen);
 		break;
-	case SCTP_SET_DEFAULT_SEND_PARAM:
+	case SCTP_DEFAULT_SEND_PARAM:
 		retval = sctp_getsockopt_default_send_param(sk, len,
 							    optval, optlen);
 		break;
-	case SCTP_SET_PEER_PRIMARY_ADDR:
-		retval = sctp_getsockopt_peer_prim(sk, len, optval, optlen);
+	case SCTP_PRIMARY_ADDR:
+		retval = sctp_getsockopt_primary_addr(sk, len, optval, optlen);
 		break;
 	case SCTP_NODELAY:
 		retval = sctp_getsockopt_nodelay(sk, len, optval, optlen);
 		break;
+	case SCTP_RTOINFO:
+		retval = sctp_getsockopt_rtoinfo(sk, len, optval, optlen);
+		break;
+	case SCTP_ASSOCINFO:
+		retval = sctp_getsockopt_associnfo(sk, len, optval, optlen);
+		break;
+	case SCTP_I_WANT_MAPPED_V4_ADDR:
+		retval = sctp_getsockopt_mappedv4(sk, len, optval, optlen);
+		break;
+	case SCTP_MAXSEG:
+		retval = sctp_getsockopt_maxseg(sk, len, optval, optlen);
+		break;
+	case SCTP_GET_PEER_ADDR_INFO:
+		retval = sctp_getsockopt_peer_addr_info(sk, len, optval,
+							optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -2531,7 +3417,7 @@ static void sctp_unhash(struct sock *sk)
  *
  * The port hash table (contained in the 'global' SCTP protocol storage
  * returned by struct sctp_protocol *sctp_get_protocol()). The hash
- * table is an array of 4096 lists (sctp_bind_hashbucket_t). Each
+ * table is an array of 4096 lists (sctp_bind_hashbucket). Each
  * list (the list number is the port number hashed out, so as you
  * would expect from a hash function, all the ports in a given list have
  * such a number that hashes out to the same list number; you were
@@ -2539,13 +3425,13 @@ static void sctp_unhash(struct sock *sk)
  * link to the socket (struct sock) that uses it, the port number and
  * a fastreuse flag (FIXME: NPI ipg).
  */
-static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head,
-					      unsigned short snum);
+static struct sctp_bind_bucket *sctp_bucket_create(
+	struct sctp_bind_hashbucket *head, unsigned short snum);
+
 static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
 {
-	sctp_bind_hashbucket_t *head; /* hash list */
-	sctp_bind_bucket_t *pp; /* hash list port iterator */
-	struct sctp_protocol *sctp = sctp_get_protocol();
+	struct sctp_bind_hashbucket *head; /* hash list */
+	struct sctp_bind_bucket *pp; /* hash list port iterator */
 	unsigned short snum;
 	int ret;
 
@@ -2554,14 +3440,13 @@ static long sctp_get_port_local(struct s
 	snum = addr->v4.sin_port;
 
 	SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum);
-
 	sctp_local_bh_disable();
 
 	if (snum == 0) {
 		/* Search for an available port.
 		 *
-		 * 'sctp->port_rover' was the last port assigned, so
-		 * we start to search from 'sctp->port_rover +
+		 * 'sctp_port_rover' was the last port assigned, so
+		 * we start to search from 'sctp_port_rover +
 		 * 1'. What we do is first check if port 'rover' is
 		 * already in the hash table; if not, we use that; if
 		 * it is, we try next.
@@ -2572,14 +3457,14 @@ static long sctp_get_port_local(struct s
 		int rover;
 		int index;
 
-		sctp_spin_lock(&sctp->port_alloc_lock);
-		rover = sctp->port_rover;
+		sctp_spin_lock(&sctp_port_alloc_lock);
+		rover = sctp_port_rover;
 		do {
 			rover++;
 			if ((rover < low) || (rover > high))
 				rover = low;
 			index = sctp_phashfn(rover);
-			head = &sctp->port_hashtable[index];
+			head = &sctp_port_hashtable[index];
 			sctp_spin_lock(&head->lock);
 			for (pp = head->chain; pp; pp = pp->next)
 				if (pp->port == rover)
@@ -2588,8 +3473,8 @@ static long sctp_get_port_local(struct s
 		next:
 			sctp_spin_unlock(&head->lock);
 		} while (--remaining > 0);
-		sctp->port_rover = rover;
-		sctp_spin_unlock(&sctp->port_alloc_lock);
+		sctp_port_rover = rover;
+		sctp_spin_unlock(&sctp_port_alloc_lock);
 
 		/* Exhausted local port range during search? */
 		ret = 1;
@@ -2609,7 +3494,7 @@ static long sctp_get_port_local(struct s
 		 * to the port number (snum) - we detect that with the
 		 * port iterator, pp being NULL.
 		 */
-		head = &sctp->port_hashtable[sctp_phashfn(snum)];
+		head = &sctp_port_hashtable[sctp_phashfn(snum)];
 		sctp_spin_lock(&head->lock);
 		for (pp = head->chain; pp; pp = pp->next) {
 			if (pp->port == snum)
@@ -2624,12 +3509,12 @@ static long sctp_get_port_local(struct s
 		 * used by other socket (pp->sk != NULL); that other
 		 * socket is going to be sk2.
 		 */
-		int sk_reuse = sk->reuse;
+		int sk_reuse = sk->sk_reuse;
 		struct sock *sk2 = pp->sk;
 
 		SCTP_DEBUG_PRINTK("sctp_get_port() found a "
 				  "possible match\n");
-		if (pp->fastreuse != 0 && sk->reuse != 0)
+		if (pp->fastreuse != 0 && sk->sk_reuse != 0)
 			goto success;
 
 		/* Run through the list of sockets bound to the port
@@ -2646,7 +3531,7 @@ static long sctp_get_port_local(struct s
 			struct sctp_endpoint *ep2;
 			ep2 = sctp_sk(sk2)->ep;
 
-			if (sk_reuse && sk2->reuse)
+			if (sk_reuse && sk2->sk_reuse)
 				continue;
 
 			if (sctp_bind_addr_match(&ep2->base.bind_addr, addr,
@@ -2670,12 +3555,12 @@ static long sctp_get_port_local(struct s
 		goto fail_unlock;
 
 	/* In either case (hit or miss), make sure fastreuse is 1 only
-	 * if sk->reuse is too (that is, if the caller requested
+	 * if sk->sk_reuse is too (that is, if the caller requested
 	 * SO_REUSEADDR on this socket -sk-).
 	 */
 	if (!pp->sk)
-		pp->fastreuse = sk->reuse ? 1 : 0;
-	else if (pp->fastreuse && sk->reuse == 0)
+		pp->fastreuse = sk->sk_reuse ? 1 : 0;
+	else if (pp->fastreuse && sk->sk_reuse == 0)
 		pp->fastreuse = 0;
 
 	/* We are set, so fill up all the data in the hash table
@@ -2717,7 +3602,7 @@ static int sctp_get_port(struct sock *sk
 	af->from_sk(&addr, sk);
 	addr.v4.sin_port = htons(snum);
 
-	/* Note: sk->num gets filled in if ephemeral port request. */
+	/* Note: sk->sk_num gets filled in if ephemeral port request. */
 	ret = sctp_get_port_local(sk, &addr);
 
 	return (ret ? 1 : 0);
@@ -2738,12 +3623,22 @@ SCTP_STATIC int sctp_seqpacket_listen(st
 	/* Only UDP style sockets that are not peeled off are allowed to
 	 * listen().
 	 */
-	if (SCTP_SOCKET_UDP != sp->type)
+	if (!sctp_style(sk, UDP))
 		return -EINVAL;
 
-	if (sk->state == SCTP_SS_LISTENING)
-		return 0;
+	/* If backlog is zero, disable listening. */
+	if (!backlog) {
+		if (sctp_sstate(sk, CLOSED))
+			return 0;
+		
+		sctp_unhash_endpoint(ep);
+		sk->sk_state = SCTP_SS_CLOSED;
+	}
 
+	/* Return if we are already listening. */
+	if (sctp_sstate(sk, LISTENING))
+		return 0;
+		
 	/*
 	 * If a bind() or sctp_bindx() is not called prior to a listen()
 	 * call that allows new associations to be accepted, the system
@@ -2758,7 +3653,7 @@ SCTP_STATIC int sctp_seqpacket_listen(st
 		if (sctp_autobind(sk))
 			return -EAGAIN;
 	}
-	sk->state = SCTP_SS_LISTENING;
+	sk->sk_state = SCTP_SS_LISTENING;
 	sctp_hash_endpoint(ep);
 	return 0;
 }
@@ -2774,7 +3669,16 @@ SCTP_STATIC int sctp_stream_listen(struc
 	struct sctp_opt *sp = sctp_sk(sk);
 	struct sctp_endpoint *ep = sp->ep;
 
-	if (sk->state == SCTP_SS_LISTENING)
+	/* If backlog is zero, disable listening. */
+	if (!backlog) {
+		if (sctp_sstate(sk, CLOSED))
+			return 0;
+		
+		sctp_unhash_endpoint(ep);
+		sk->sk_state = SCTP_SS_CLOSED;
+	}
+
+	if (sctp_sstate(sk, LISTENING))
 		return 0;
 
 	/*
@@ -2791,8 +3695,8 @@ SCTP_STATIC int sctp_stream_listen(struc
 		if (sctp_autobind(sk))
 			return -EAGAIN;
 	}
-	sk->state = SCTP_SS_LISTENING;
-	sk->max_ack_backlog = backlog;
+	sk->sk_state = SCTP_SS_LISTENING;
+	sk->sk_max_ack_backlog = backlog;
 	sctp_hash_endpoint(ep);
 	return 0;
 }
@@ -2863,41 +3767,40 @@ cleanup:
 unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
 {
 	struct sock *sk = sock->sk;
+	struct sctp_opt *sp = sctp_sk(sk);
 	unsigned int mask;
 
-	poll_wait(file, sk->sleep, wait);
+	poll_wait(file, sk->sk_sleep, wait);
+
+	/* A TCP-style listening socket becomes readable when the accept queue
+	 * is not empty.
+	 */
+	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
+		return (!list_empty(&sp->ep->asocs)) ?
+		       	(POLLIN | POLLRDNORM) : 0;
+
 	mask = 0;
 
 	/* Is there any exceptional events?  */
-	if (sk->err || !skb_queue_empty(&sk->error_queue))
+	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
 		mask |= POLLERR;
-	if (sk->shutdown == SHUTDOWN_MASK)
+	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
 	/* Is it readable?  Reconsider this code with TCP-style support.  */
-	if (!skb_queue_empty(&sk->receive_queue) ||
-	    (sk->shutdown & RCV_SHUTDOWN))
+	if (!skb_queue_empty(&sk->sk_receive_queue) ||
+	    (sk->sk_shutdown & RCV_SHUTDOWN))
 		mask |= POLLIN | POLLRDNORM;
 
-	/*
-	 * FIXME: We need to set SCTP_SS_DISCONNECTING for TCP-style and
-	 * peeled off sockets.  Additionally, TCP-style needs to consider
-	 * other establishment conditions.
-	 */
-	if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) {
-		/* The association is going away.  */
-		if (SCTP_SS_DISCONNECTING == sk->state)
-			mask |= POLLHUP;
-		/* The association is either gone or not ready.  */
-		if (SCTP_SS_CLOSED == sk->state)
-			return mask;
-	}
+	/* The association is either gone or not ready.  */
+	if (!sctp_style(sk, UDP) && sctp_sstate(sk, CLOSED))
+		return mask;
 
 	/* Is it writable?  */
 	if (sctp_writeable(sk)) {
 		mask |= POLLOUT | POLLWRNORM;
 	} else {
-		set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
 		/*
 		 * Since the socket is not locked, the buffer
 		 * might be made available after the writeable check and
@@ -2916,12 +3819,13 @@ unsigned int sctp_poll(struct file *file
  * 2nd Level Abstractions
  ********************************************************************/
 
-static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsigned short snum)
+static struct sctp_bind_bucket *sctp_bucket_create(
+	struct sctp_bind_hashbucket *head, unsigned short snum)
 {
-	sctp_bind_bucket_t *pp;
+	struct sctp_bind_bucket *pp;
 
 	SCTP_DEBUG_PRINTK( "sctp_bucket_create() begins, snum=%d\n", snum);
-	pp = kmalloc(sizeof(sctp_bind_bucket_t), GFP_ATOMIC);
+	pp = kmalloc(sizeof(struct sctp_bind_bucket), GFP_ATOMIC);
 	if (pp) {
 		pp->port = snum;
 		pp->fastreuse = 0;
@@ -2935,16 +3839,15 @@ static sctp_bind_bucket_t *sctp_bucket_c
 	return pp;
 }
 
-/* FIXME: Comments! */
+/* Release this socket's reference to a local port.  */
 static __inline__ void __sctp_put_port(struct sock *sk)
 {
-	struct sctp_protocol *sctp_proto = sctp_get_protocol();
-	sctp_bind_hashbucket_t *head =
-		&sctp_proto->port_hashtable[sctp_phashfn((sk)->num)];
-	sctp_bind_bucket_t *pp;
+	struct sctp_bind_hashbucket *head =
+		&sctp_port_hashtable[sctp_phashfn((sk)->num)];
+	struct sctp_bind_bucket *pp;
 
 	sctp_spin_lock(&head->lock);
-	pp = (sctp_bind_bucket_t *) sk->prev;
+	pp = (struct sctp_bind_bucket *) sk->prev;
 	if (sk->bind_next)
 		sk->bind_next->bind_pprev = sk->bind_pprev;
 	*(sk->bind_pprev) = sk->bind_next;
@@ -2981,7 +3884,7 @@ static int sctp_autobind(struct sock *sk
 	/* Initialize a local sockaddr structure to INADDR_ANY. */
 	af = sctp_sk(sk)->pf->af;
 
-	port = htons((sk)->num);
+	port = htons(sk->num);
 	af->inaddr_any(&autoaddr, port);
 
 	return sctp_do_bind(sk, &autoaddr, af->sockaddr_len);
@@ -3110,19 +4013,19 @@ static int sctp_wait_for_packet(struct s
 	int error;
 	DECLARE_WAITQUEUE(wait, current);
 
+	add_wait_queue_exclusive(sk->sk_sleep, &wait);
 	__set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue_exclusive(sk->sleep, &wait);
 
 	/* Socket errors? */
 	error = sock_error(sk);
 	if (error)
 		goto out;
 
-	if (!skb_queue_empty(&sk->receive_queue))
+	if (!skb_queue_empty(&sk->sk_receive_queue))
 		goto ready;
 
 	/* Socket shut down?  */
-	if (sk->shutdown & RCV_SHUTDOWN)
+	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		goto out;
 
 	/* Sequenced packets can come disconnected.  If so we report the
@@ -3131,8 +4034,7 @@ static int sctp_wait_for_packet(struct s
 	error = -ENOTCONN;
 
 	/* Is there a good reason to think that we may receive some data?  */
-	if ((list_empty(&sctp_sk(sk)->ep->asocs)) &&
-	    (sk->state != SCTP_SS_LISTENING))
+	if (list_empty(&sctp_sk(sk)->ep->asocs) && !sctp_sstate(sk, LISTENING))
 		goto out;
 
 	/* Handle signals.  */
@@ -3149,7 +4051,7 @@ static int sctp_wait_for_packet(struct s
 	sctp_lock_sock(sk);
 
 ready:
-	remove_wait_queue(sk->sleep, &wait);
+	remove_wait_queue(sk->sk_sleep, &wait);
 	__set_current_state(TASK_RUNNING);
 	return 0;
 
@@ -3157,7 +4059,7 @@ interrupted:
 	error = sock_intr_errno(*timeo_p);
 
 out:
-	remove_wait_queue(sk->sleep, &wait);
+	remove_wait_queue(sk->sk_sleep, &wait);
 	__set_current_state(TASK_RUNNING);
 	*err = error;
 	return error;
@@ -3174,7 +4076,7 @@ static struct sk_buff *sctp_skb_recv_dat
 	struct sk_buff *skb;
 	long timeo;
 
-	/* Caller is allowed not to check sk->err before calling.  */
+	/* Caller is allowed not to check sk->sk_err before calling.  */
 	error = sock_error(sk);
 	if (error)
 		goto no_packet;
@@ -3195,21 +4097,21 @@ static struct sk_buff *sctp_skb_recv_dat
 		if (flags & MSG_PEEK) {
 			unsigned long cpu_flags;
 
-			sctp_spin_lock_irqsave(&sk->receive_queue.lock,
+			sctp_spin_lock_irqsave(&sk->sk_receive_queue.lock,
 					       cpu_flags);
-			skb = skb_peek(&sk->receive_queue);
+			skb = skb_peek(&sk->sk_receive_queue);
 			if (skb)
 				atomic_inc(&skb->users);
-			sctp_spin_unlock_irqrestore(&sk->receive_queue.lock,
+			sctp_spin_unlock_irqrestore(&sk->sk_receive_queue.lock,
 						    cpu_flags);
 		} else {
-			skb = skb_dequeue(&sk->receive_queue);
+			skb = skb_dequeue(&sk->sk_receive_queue);
 		}
 
 		if (skb)
 			return skb;
 
-		if (sk->shutdown & RCV_SHUTDOWN)
+		if (sk->sk_shutdown & RCV_SHUTDOWN)
 			break;
 
 		/* User doesn't want to wait.  */
@@ -3237,7 +4139,7 @@ static inline int sctp_verify_addr(struc
 		return -EINVAL;
 
 	/* Is this a valid SCTP address?  */
-	if (!af->addr_valid(addr))
+	if (!af->addr_valid(addr, sctp_sk(sk)))
 		return -EINVAL;
 
 	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
@@ -3252,7 +4154,7 @@ static inline int sctp_wspace(struct sct
 	struct sock *sk = asoc->base.sk;
 	int amt = 0;
 
-	amt = sk->sndbuf - asoc->sndbuf_used;
+	amt = sk->sk_sndbuf - asoc->sndbuf_used;
 	if (amt < 0)
 		amt = 0;
 	return amt;
@@ -3267,7 +4169,7 @@ static inline int sctp_wspace(struct sct
  * destructor in the data chunk skb for the purpose of the sndbuf space
  * tracking.
  */
-static inline void sctp_set_owner_w(sctp_chunk_t *chunk)
+static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
 {
 	struct sctp_association *asoc = chunk->asoc;
 	struct sock *sk = asoc->base.sk;
@@ -3277,32 +4179,32 @@ static inline void sctp_set_owner_w(sctp
 
 	chunk->skb->destructor = sctp_wfree;
 	/* Save the chunk pointer in skb for sctp_wfree to use later.  */
-	*((sctp_chunk_t **)(chunk->skb->cb)) = chunk;
+	*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
 
 	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
-	sk->wmem_queued += SCTP_DATA_SNDSIZE(chunk);
+	sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk);
 }
 
 /* If sndbuf has changed, wake up per association sndbuf waiters.  */
 static void __sctp_write_space(struct sctp_association *asoc)
 {
 	struct sock *sk = asoc->base.sk;
-	struct socket *sock = sk->socket;
+	struct socket *sock = sk->sk_socket;
 
 	if ((sctp_wspace(asoc) > 0) && sock) {
 		if (waitqueue_active(&asoc->wait))
 			wake_up_interruptible(&asoc->wait);
 
 		if (sctp_writeable(sk)) {
-			if (sk->sleep && waitqueue_active(sk->sleep))
-				wake_up_interruptible(sk->sleep);
+			if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+				wake_up_interruptible(sk->sk_sleep);
 
 			/* Note that we try to include the Async I/O support
 			 * here by modeling from the current TCP/UDP code.
 			 * We have not tested with it yet.
 			 */
 			if (sock->fasync_list &&
-			    !(sk->shutdown & SEND_SHUTDOWN))
+			    !(sk->sk_shutdown & SEND_SHUTDOWN))
 				sock_wake_async(sock, 2, POLL_OUT);
 		}
 	}
@@ -3315,15 +4217,15 @@ static void __sctp_write_space(struct sc
 static void sctp_wfree(struct sk_buff *skb)
 {
 	struct sctp_association *asoc;
-	sctp_chunk_t *chunk;
+	struct sctp_chunk *chunk;
 	struct sock *sk;
 
 	/* Get the saved chunk pointer.  */
-	chunk = *((sctp_chunk_t **)(skb->cb));
+	chunk = *((struct sctp_chunk **)(skb->cb));
 	asoc = chunk->asoc;
 	sk = asoc->base.sk;
 	asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk);
-	sk->wmem_queued -= SCTP_DATA_SNDSIZE(chunk);
+	sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk);
 	__sctp_write_space(asoc);
 
 	sctp_association_put(asoc);
@@ -3331,26 +4233,28 @@ static void sctp_wfree(struct sk_buff *s
 
 /* Helper function to wait for space in the sndbuf.  */
 static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
-				int msg_len)
+				size_t msg_len)
 {
 	struct sock *sk = asoc->base.sk;
 	int err = 0;
 	long current_timeo = *timeo_p;
 	DECLARE_WAITQUEUE(wait, current);
 
-	SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%d\n",
+	SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%u\n",
 	                  asoc, (long)(*timeo_p), msg_len);
 
-	/* Wait on the association specific sndbuf space. */
-	add_wait_queue_exclusive(&asoc->wait, &wait);
-
 	/* Increment the association's refcnt.  */
 	sctp_association_hold(asoc);
+
+        /* Wait on the association specific sndbuf space. */
+        add_wait_queue_exclusive(&asoc->wait, &wait);
+
+	/* Wait on the association specific sndbuf space. */
 	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		if (!*timeo_p)
 			goto do_nonblock;
-		if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
+		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
 		    asoc->base.dead)
 			goto do_error;
 		if (signal_pending(current))
@@ -3370,11 +4274,11 @@ static int sctp_wait_for_sndbuf(struct s
 
 out:
 	remove_wait_queue(&asoc->wait, &wait);
+	__set_current_state(TASK_RUNNING);
 
 	/* Release the association's refcnt.  */
 	sctp_association_put(asoc);
 
-	__set_current_state(TASK_RUNNING);
 	return err;
 
 do_error:
@@ -3418,7 +4322,7 @@ static int sctp_writeable(struct sock *s
 {
 	int amt = 0;
 
-	amt = sk->sndbuf - sk->wmem_queued;
+	amt = sk->sk_sndbuf - sk->sk_wmem_queued;
 	if (amt < 0)
 		amt = 0;
 	return amt;
@@ -3437,24 +4341,23 @@ static int sctp_wait_for_connect(struct 
 	SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
 			  (long)(*timeo_p));
 
-	add_wait_queue_exclusive(&asoc->wait, &wait);
-
 	/* Increment the association's refcnt.  */
 	sctp_association_hold(asoc);
 
+	add_wait_queue_exclusive(&asoc->wait, &wait);
 	for (;;) {
 		__set_current_state(TASK_INTERRUPTIBLE);
 		if (!*timeo_p)
 			goto do_nonblock;
-		if (sk->shutdown & RCV_SHUTDOWN)
+		if (sk->sk_shutdown & RCV_SHUTDOWN)
 			break;
-		if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
+		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
 		    asoc->base.dead)
 			goto do_error;
 		if (signal_pending(current))
 			goto do_interrupted;
 
-		if (asoc->state == SCTP_STATE_ESTABLISHED)
+		if (sctp_state(asoc, ESTABLISHED))
 			break;
 
 		/* Let another process have a go.  Since we are going
@@ -3469,12 +4372,11 @@ static int sctp_wait_for_connect(struct 
 
 out:
 	remove_wait_queue(&asoc->wait, &wait);
+	__set_current_state(TASK_RUNNING);
 
 	/* Release the association's refcnt.  */
 	sctp_association_put(asoc);
 
-	__set_current_state(TASK_RUNNING);
-
 	return err;
 
 do_error:
@@ -3498,7 +4400,7 @@ static int sctp_wait_for_accept(struct s
 
 	ep = sctp_sk(sk)->ep;
 
-	add_wait_queue_exclusive(sk->sleep, &wait);
+	add_wait_queue_exclusive(sk->sk_sleep, &wait);
 
 	for (;;) {
 		__set_current_state(TASK_INTERRUPTIBLE);
@@ -3509,7 +4411,7 @@ static int sctp_wait_for_accept(struct s
 		}
 
 		err = -EINVAL;
-		if (sk->state != SCTP_SS_LISTENING)
+		if (!sctp_sstate(sk, LISTENING))
 			break;
 
 		err = 0;
@@ -3525,12 +4427,31 @@ static int sctp_wait_for_accept(struct s
 			break;
 	}
 
-	remove_wait_queue(sk->sleep, &wait);
-	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk->sk_sleep, &wait);
+	__set_current_state(TASK_RUNNING);	
 
 	return err;
 }
 
+void sctp_wait_for_close(struct sock *sk, long timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue_exclusive(sk->sk_sleep, &wait);
+
+	do {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		if (list_empty(&sctp_sk(sk)->ep->asocs))
+			break;
+		sctp_release_sock(sk);
+		timeout = schedule_timeout(timeout);
+		sctp_lock_sock(sk);
+	} while (!signal_pending(current) && timeout);
+
+	remove_wait_queue(sk->sk_sleep, &wait);
+	__set_current_state(TASK_RUNNING);	
+}
+
 /* Populate the fields of the newsk from the oldsk and migrate the assoc
  * and its messages to the newsk.
  */
@@ -3547,9 +4468,10 @@ static void sctp_sock_migrate(struct soc
 	/* Migrate socket buffer sizes and all the socket level options to the
 	 * new socket.
 	 */
-	newsk->sndbuf = oldsk->sndbuf;
-	newsk->rcvbuf = oldsk->rcvbuf;
-	*newsp = *oldsp;
+	newsk->sk_sndbuf = oldsk->sk_sndbuf;
+	newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
+	/* Brute force copy old sctp opt. */
+	memcpy(newsp, oldsp, sizeof(struct sctp_opt));
 
 	/* Restore the ep value that was overwritten with the above structure
 	 * copy.
@@ -3557,14 +4479,16 @@ static void sctp_sock_migrate(struct soc
 	newsp->ep = newep;
 	newsp->hmac = NULL;
 
+	newsk->num = oldsk->num;
+
 	/* Move any messages in the old socket's receive queue that are for the
 	 * peeled off association to the new socket's receive queue.
 	 */
-	sctp_skb_for_each(skb, &oldsk->receive_queue, tmp) {
+	sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
 		event = sctp_skb2event(skb);
-		if (event->event_asoc == assoc) {
+		if (event->sndrcvinfo.sinfo_assoc_id == assoc) {
 			__skb_unlink(skb, skb->list);
-			__skb_queue_tail(&newsk->receive_queue, skb);
+			__skb_queue_tail(&newsk->sk_receive_queue, skb);
 		}
 	}
 
@@ -3584,14 +4508,14 @@ static void sctp_sock_migrate(struct soc
 		if (assoc->ulpq.pd_mode) {
 			queue = &newsp->pd_lobby;
 		} else
-			queue = &newsk->receive_queue;
+			queue = &newsk->sk_receive_queue;
 
 		/* Walk through the pd_lobby, looking for skbs that
 		 * need moved to the new socket.
 		 */
 		sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
 			event = sctp_skb2event(skb);
-			if (event->event_asoc == assoc) {
+			if (event->sndrcvinfo.sinfo_assoc_id == assoc) {
 				__skb_unlink(skb, skb->list);
 				__skb_queue_tail(queue, skb);
 			}
@@ -3614,7 +4538,13 @@ static void sctp_sock_migrate(struct soc
 	/* Migrate the association to the new socket. */
 	sctp_assoc_migrate(assoc, newsk);
 
-	newsk->state = SCTP_SS_ESTABLISHED;
+	/* If the association on the newsk is already closed before accept()
+	 * is called, set RCV_SHUTDOWN flag.
+	 */
+	if (sctp_state(assoc, CLOSED) && sctp_style(newsk, TCP))
+		newsk->sk_shutdown |= RCV_SHUTDOWN;
+
+	newsk->sk_state = SCTP_SS_ESTABLISHED;
 }
 
 /* This proto struct describes the ULP interface for SCTP.  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ssnmap.c linux-2.4.26-pre6/net/sctp/ssnmap.c
--- linux-2.4.25/net/sctp/ssnmap.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/ssnmap.c	2004-03-25 00:21:25.000000000 +0000
@@ -40,6 +40,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
+#define MAX_KMALLOC_SIZE	131072
 
 /* Storage size needed for map includes 2 headers and then the
  * specific needs of in or out streams.
@@ -56,9 +57,14 @@ static inline size_t sctp_ssnmap_size(__
 struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp)
 {
 	struct sctp_ssnmap *retval;
+	int size;
 
-	retval = kmalloc(sctp_ssnmap_size(in, out), gfp);
-
+	size = sctp_ssnmap_size(in, out);
+	if (size <= MAX_KMALLOC_SIZE)
+		retval = kmalloc(size, gfp);
+	else
+		retval = (struct sctp_ssnmap *)
+			  __get_free_pages(gfp, get_order(size));
 	if (!retval)
 		goto fail;
 
@@ -71,7 +77,10 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u1
 	return retval;
 
 fail_map:
-	kfree(retval);
+	if (size <= MAX_KMALLOC_SIZE)
+		kfree(retval);
+	else
+		free_pages((unsigned long)retval, get_order(size));
 fail:
 	return NULL;
 }
@@ -107,7 +116,13 @@ void sctp_ssnmap_clear(struct sctp_ssnma
 void sctp_ssnmap_free(struct sctp_ssnmap *map)
 {
 	if (map && map->malloced) {
-		kfree(map);
+		int size;
+
+		size = sctp_ssnmap_size(map->in.len, map->out.len);
+		if (size <= MAX_KMALLOC_SIZE)
+			kfree(map);
+		else
+			free_pages((unsigned long)map, get_order(size));
 		SCTP_DBG_OBJCNT_DEC(ssnmap);
 	}
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sysctl.c linux-2.4.26-pre6/net/sctp/sysctl.c
--- linux-2.4.25/net/sctp/sysctl.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/sysctl.c	2004-03-25 00:17:55.000000000 +0000
@@ -1,39 +1,40 @@
-/* SCTP kernel reference Implementation 
+/* SCTP kernel reference Implementation
  * Copyright (c) 2002 International Business Machines Corp.
  * Copyright (c) 2002 Intel Corp.
- * 
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
- * Sysctl related interfaces for SCTP. 
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ *
+ * Sysctl related interfaces for SCTP.
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
  * the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
  *                 ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
+ * Written or modified by:
  *    Mingqin Liu           <liuming@us.ibm.com>
  *    Jon Grimm             <jgrimm@us.ibm.com>
  *    Ardelle Fan           <ardelle.fan@intel.com>
+ *    Ryan Layer            <rmlayer@us.ibm.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -42,49 +43,59 @@
 #include <net/sctp/structs.h>
 #include <linux/sysctl.h>
 
-extern struct sctp_protocol sctp_proto;
+static ctl_handler sctp_sysctl_jiffies_ms;
+static long rto_timer_min = 1;
+static long rto_timer_max = 86400000; /* One day */
 
 static ctl_table sctp_table[] = {
 	{
 		.ctl_name	= NET_SCTP_RTO_INITIAL,
 		.procname	= "rto_initial",
-		.data		= &sctp_proto.rto_initial,
-		.maxlen		= sizeof(int),
+		.data		= &sctp_rto_initial,
+		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+		.strategy	= &sctp_sysctl_jiffies_ms,
+		.extra1         = &rto_timer_min,
+		.extra2         = &rto_timer_max
 	},
 	{
 		.ctl_name	= NET_SCTP_RTO_MIN,
 		.procname	= "rto_min",
-		.data		= &sctp_proto.rto_min,
-		.maxlen		= sizeof(int),
+		.data		= &sctp_rto_min,
+		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+		.strategy	= &sctp_sysctl_jiffies_ms,
+		.extra1         = &rto_timer_min,
+		.extra2         = &rto_timer_max
 	},
 	{
 		.ctl_name	= NET_SCTP_RTO_MAX,
 		.procname	= "rto_max",
-		.data		= &sctp_proto.rto_max,
-		.maxlen		= sizeof(int),
+		.data		= &sctp_rto_max,
+		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+		.strategy	= &sctp_sysctl_jiffies_ms,
+		.extra1         = &rto_timer_min,
+		.extra2         = &rto_timer_max
 	},
 	{
 		.ctl_name	= NET_SCTP_VALID_COOKIE_LIFE,
 		.procname	= "valid_cookie_life",
-		.data		= &sctp_proto.valid_cookie_life,
-		.maxlen		= sizeof(int),
+		.data		= &sctp_valid_cookie_life,
+		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+		.strategy	= &sctp_sysctl_jiffies_ms,
+		.extra1         = &rto_timer_min,
+		.extra2         = &rto_timer_max
 	},
 	{
 		.ctl_name	= NET_SCTP_MAX_BURST,
 		.procname	= "max_burst",
-		.data		= &sctp_proto.max_burst,
+		.data		= &sctp_max_burst,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -92,7 +103,7 @@ static ctl_table sctp_table[] = {
 	{
 		.ctl_name	= NET_SCTP_ASSOCIATION_MAX_RETRANS,
 		.procname	= "association_max_retrans",
-		.data		= &sctp_proto.max_retrans_association,
+		.data		= &sctp_max_retrans_association,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -100,7 +111,7 @@ static ctl_table sctp_table[] = {
 	{
 		.ctl_name	= NET_SCTP_PATH_MAX_RETRANS,
 		.procname	= "path_max_retrans",
-		.data		= &sctp_proto.max_retrans_path,
+		.data		= &sctp_max_retrans_path,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -108,7 +119,7 @@ static ctl_table sctp_table[] = {
 	{
 		.ctl_name	= NET_SCTP_MAX_INIT_RETRANSMITS,
 		.procname	= "max_init_retransmits",
-		.data		= &sctp_proto.max_retrans_init,
+		.data		= &sctp_max_retrans_init,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -116,25 +127,29 @@ static ctl_table sctp_table[] = {
 	{
 		.ctl_name	= NET_SCTP_HB_INTERVAL,
 		.procname	= "hb_interval",
-		.data		= &sctp_proto.hb_interval,
-		.maxlen		= sizeof(int),
+		.data		= &sctp_hb_interval,
+		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+		.strategy	= &sctp_sysctl_jiffies_ms,
+		.extra1         = &rto_timer_min,
+		.extra2         = &rto_timer_max
 	},
 	{
 		.ctl_name	= NET_SCTP_PRESERVE_ENABLE,
 		.procname	= "cookie_preserve_enable",
-		.data		= &sctp_proto.cookie_preserve_enable,
-		.maxlen		= sizeof(int),
+		.data		= &sctp_cookie_preserve_enable,
+		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+		.strategy	= &sctp_sysctl_jiffies_ms,
+		.extra1         = &rto_timer_min,
+		.extra2         = &rto_timer_max
 	},
 	{
 		.ctl_name	= NET_SCTP_RTO_ALPHA,
 		.procname	= "rto_alpha_exp_divisor",
-		.data		= &sctp_proto.rto_alpha,
+		.data		= &sctp_rto_alpha,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -142,7 +157,15 @@ static ctl_table sctp_table[] = {
 	{
 		.ctl_name	= NET_SCTP_RTO_BETA,
 		.procname	= "rto_beta_exp_divisor",
-		.data		= &sctp_proto.rto_beta,
+		.data		= &sctp_rto_beta,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
+		.ctl_name	= NET_SCTP_ADDIP_ENABLE,
+		.procname	= "addip_enable",
+		.data		= &sctp_addip_enable,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -154,7 +177,6 @@ static ctl_table sctp_net_table[] = {
 	{
 		.ctl_name	= NET_SCTP,
 		.procname	= "sctp",
-		.maxlen		= 0,
 		.mode		= 0555,
 		.child		= sctp_table
 	},
@@ -165,7 +187,6 @@ static ctl_table sctp_root_table[] = {
 	{
 		.ctl_name	= CTL_NET,
 		.procname	= "net",
-		.maxlen		= 0,
 		.mode		= 0555,
 		.child		= sctp_net_table
 	},
@@ -185,3 +206,37 @@ void sctp_sysctl_unregister(void)
 {
 	unregister_sysctl_table(sctp_sysctl_header);
 }
+
+/* Strategy function to convert jiffies to milliseconds.  */
+static int sctp_sysctl_jiffies_ms(ctl_table *table, int *name, int nlen,
+				  void *oldval, size_t *oldlenp,
+				  void *newval, size_t newlen, void **context)
+{
+	if (oldval) {
+		size_t olen;
+
+		if (oldlenp) {
+			if (get_user(olen, oldlenp))
+				return -EFAULT;
+
+			if (olen != sizeof (int))
+				return -EINVAL;
+		}
+		if (put_user((*(int *)(table->data) * 1000) / HZ,
+			(int *)oldval) ||
+		    (oldlenp && put_user(sizeof (int), oldlenp)))
+			return -EFAULT;
+	}
+	if (newval && newlen) {
+		int new;
+
+		if (newlen != sizeof (int))
+			return -EINVAL;
+
+		if (get_user(new, (int *)newval))
+			return -EFAULT;
+
+		*(int *)(table->data) = (new * HZ) / 1000;
+	}
+	return 1;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/transport.c linux-2.4.26-pre6/net/sctp/transport.c
--- linux-2.4.25/net/sctp/transport.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/transport.c	2004-03-25 00:19:57.000000000 +0000
@@ -83,8 +83,6 @@ struct sctp_transport *sctp_transport_in
 					   const union sctp_addr *addr,
 					   int gfp)
 {
-	struct sctp_protocol *proto = sctp_get_protocol();
-
 	/* Copy in the address.  */
 	peer->ipaddr = *addr;
 	peer->af_specific = sctp_get_af_specific(addr->sa.sa_family);
@@ -100,7 +98,7 @@ struct sctp_transport *sctp_transport_in
 	 * parameter 'RTO.Initial'.
 	 */
 	peer->rtt = 0;
-	peer->rto = proto->rto_initial;
+	peer->rto = sctp_rto_initial;
 	peer->rttvar = 0;
 	peer->srtt = 0;
 	peer->rto_pending = 0;
@@ -109,19 +107,18 @@ struct sctp_transport *sctp_transport_in
 	peer->last_time_used = jiffies;
 	peer->last_time_ecne_reduced = jiffies;
 
-	peer->active = 1;
+	peer->active = SCTP_ACTIVE;
 	peer->hb_allowed = 0;
 
 	/* Initialize the default path max_retrans.  */
-	peer->max_retrans = proto->max_retrans_path;
+	peer->max_retrans = sctp_max_retrans_path;
 	peer->error_threshold = 0;
 	peer->error_count = 0;
 
-	peer->debug_name = "unnamedtransport";
-
 	INIT_LIST_HEAD(&peer->transmitted);
 	INIT_LIST_HEAD(&peer->send_ready);
 	INIT_LIST_HEAD(&peer->transports);
+	sctp_packet_init(&peer->packet, peer, 0, 0);
 
 	/* Set up the retransmission timer.  */
 	init_timer(&peer->T3_rtx_timer);
@@ -138,6 +135,13 @@ struct sctp_transport *sctp_transport_in
 	peer->dead = 0;
 
 	peer->malloced = 0;
+
+	/* Initialize the state information for SFR-CACC */
+	peer->cacc.changeover_active = 0;
+	peer->cacc.cycling_changeover = 0;
+	peer->cacc.next_tsn_at_change = 0;
+	peer->cacc.cacc_saw_newack = 0;
+
 	return peer;
 }
 
@@ -241,7 +245,7 @@ void sctp_transport_route(struct sctp_tr
 	if (dst) {
 		transport->pmtu = dst_pmtu(dst);
 
-		/* Initialize sk->rcv_saddr, if the transport is the
+		/* Initialize sk->sk_rcv_saddr, if the transport is the
 		 * association's active path for getsockname().
 		 */ 
 		if (asoc && (transport == asoc->peer.active_path))
@@ -268,8 +272,6 @@ void sctp_transport_put(struct sctp_tran
 /* Update transport's RTO based on the newly calculated RTT. */
 void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
 {
-	struct sctp_protocol *proto = sctp_get_protocol();
-
 	/* Check for valid transport.  */
 	SCTP_ASSERT(tp, "NULL transport", return);
 
@@ -288,10 +290,10 @@ void sctp_transport_update_rto(struct sc
 		 * For example, assuming the default value of RTO.Alpha of
 		 * 1/8, rto_alpha would be expressed as 3.
 		 */
-		tp->rttvar = tp->rttvar - (tp->rttvar >> proto->rto_beta)
-			+ ((abs(tp->srtt - rtt)) >> proto->rto_beta);
-		tp->srtt = tp->srtt - (tp->srtt >> proto->rto_alpha)
-			+ (rtt >> proto->rto_alpha);
+		tp->rttvar = tp->rttvar - (tp->rttvar >> sctp_rto_beta)
+			+ ((abs(tp->srtt - rtt)) >> sctp_rto_beta);
+		tp->srtt = tp->srtt - (tp->srtt >> sctp_rto_alpha)
+			+ (rtt >> sctp_rto_alpha);
 	} else {
 		/* 6.3.1 C2) When the first RTT measurement R is made, set
 		 * SRTT <- R, RTTVAR <- R/2.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/tsnmap.c linux-2.4.26-pre6/net/sctp/tsnmap.c
--- linux-2.4.25/net/sctp/tsnmap.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/tsnmap.c	2004-03-25 00:17:23.000000000 +0000
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001 International Business Machines, Corp.
+ * Copyright (c) 2001-2003 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
@@ -46,7 +46,6 @@
 #include <net/sctp/sm.h>
 
 static void sctp_tsnmap_update(struct sctp_tsnmap *map);
-static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map);
 static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
 				     __u16 len, __u16 base,
 				     int *started, __u16 *start,
@@ -92,7 +91,6 @@ struct sctp_tsnmap *sctp_tsnmap_init(str
 	map->cumulative_tsn_ack_point = initial_tsn - 1;
 	map->max_tsn_seen = map->cumulative_tsn_ack_point;
 	map->malloced = 0;
-	map->pending_data = 0;
 	map->num_dup_tsns = 0;
 
 	return map;
@@ -135,14 +133,6 @@ out:
 	return dup;
 }
 
-/* Is there a gap in the TSN map?  */
-int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
-{
-	int has_gap;
-
-	has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen);
-	return has_gap;
-}
 
 /* Mark this TSN as seen.  */
 void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
@@ -176,21 +166,6 @@ void sctp_tsnmap_mark(struct sctp_tsnmap
 	sctp_tsnmap_update(map);
 }
 
-void sctp_tsnmap_report_dup(struct sctp_tsnmap *map, __u32 tsn)
-{
-}
-
-/* Retrieve the Cumulative TSN Ack Point. */
-__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map)
-{
-	return map->cumulative_tsn_ack_point;
-}
-
-/* Retrieve the highest TSN we've seen.  */
-__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map)
-{
-	return map->max_tsn_seen;
-}
 
 /* Dispose of a tsnmap.  */
 void sctp_tsnmap_free(struct sctp_tsnmap *map)
@@ -219,6 +194,10 @@ int sctp_tsnmap_next_gap_ack(const struc
 	/* We haven't found a gap yet.  */
 	started = ended = 0;
 
+	/* If there are no more gap acks possible, get out fast.  */
+	if (TSN_lte(map->max_tsn_seen, iter->start))
+		return 0;
+
 	/* Search the first mapping array.  */
 	if (iter->start - map->base_tsn < map->len) {
 
@@ -304,10 +283,11 @@ static void sctp_tsnmap_update(struct sc
 	} while (map->tsn_map[ctsn - map->base_tsn]);
 
 	map->cumulative_tsn_ack_point = ctsn - 1; /* Back up one. */
-	sctp_tsnmap_update_pending_data(map);
 }
 
-static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map)
+/* How many data chunks  are we missing from our peer?
+ */
+__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
 {
 	__u32 cum_tsn = map->cumulative_tsn_ack_point;
 	__u32 max_tsn = map->max_tsn_seen;
@@ -339,7 +319,7 @@ static void sctp_tsnmap_update_pending_d
 	}
 
 out:
-	map->pending_data = pending_data;
+	return pending_data;
 }
 
 /* This is a private helper for finding Gap Ack Blocks.  It searches a
@@ -359,6 +339,8 @@ static void sctp_tsnmap_find_gap_ack(__u
 	 * early if we have found the end of the Gap Ack Block.
 	 */
 
+	/* Also, stop looking past the maximum TSN seen. */
+
 	/* Look for the start. */
 	if (!(*started)) {
 		for (; i < len; i++) {
@@ -404,3 +386,26 @@ void sctp_tsnmap_renege(struct sctp_tsnm
 	else
 		map->overflow_map[gap - map->len] = 0;
 }
+
+/* How many gap ack blocks do we have recorded? */
+__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map)
+{
+	struct sctp_tsnmap_iter iter;
+	int gabs = 0;
+
+	/* Refresh the gap ack information. */
+	if (sctp_tsnmap_has_gap(map)) {
+		sctp_tsnmap_iter_init(map, &iter);
+		while (sctp_tsnmap_next_gap_ack(map, &iter,
+						&map->gabs[gabs].start,
+						&map->gabs[gabs].end)) {
+
+			map->gabs[gabs].start = htons(map->gabs[gabs].start);
+			map->gabs[gabs].end = htons(map->gabs[gabs].end);
+			gabs++;
+			if (gabs >= SCTP_MAX_GABS)
+				break;
+		}
+	}
+	return gabs;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ulpevent.c linux-2.4.26-pre6/net/sctp/ulpevent.c
--- linux-2.4.25/net/sctp/ulpevent.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/ulpevent.c	2004-03-25 00:20:53.000000000 +0000
@@ -35,6 +35,8 @@
  * Written or modified by:
  *    Jon Grimm             <jgrimm@us.ibm.com>
  *    La Monte H.P. Yarroll <piggy@acm.org>
+ *    Ardelle Fan	    <ardelle.fan@intel.com>
+ *    Sridhar Samudrala     <sri@us.ibm.com>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -46,10 +48,12 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
-static void sctp_ulpevent_set_owner_r(struct sk_buff *skb,
-				      struct sctp_association *asoc);
-static void sctp_ulpevent_set_owner(struct sk_buff *skb,
-				    const struct sctp_association *asoc);
+static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
+					   const struct sctp_association *asoc);
+static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event);
+static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
+				       struct sctp_association *asoc);
+static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);
 
 /* Create a new sctp_ulpevent.  */
 struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
@@ -62,30 +66,19 @@ struct sctp_ulpevent *sctp_ulpevent_new(
 		goto fail;
 
 	event = sctp_skb2event(skb);
-	event = sctp_ulpevent_init(event, msg_flags);
-	if (!event)
-		goto fail_init;
+	sctp_ulpevent_init(event, msg_flags);
+
 	return event;
 
-fail_init:
-	kfree_skb(skb);
 fail:
 	return NULL;
 }
 
 /* Initialize an ULP event from an given skb.  */
-struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *event,
-					 int msg_flags)
+void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
 {
 	memset(event, sizeof(struct sctp_ulpevent), 0x00);
 	event->msg_flags = msg_flags;
-	return event;
-}
-
-/* Dispose of an event.  */
-void sctp_ulpevent_free(struct sctp_ulpevent *event)
-{
-	kfree_skb(sctp_event2skb(event));
 }
 
 /* Is this a MSG_NOTIFICATION?  */
@@ -189,7 +182,7 @@ struct sctp_ulpevent  *sctp_ulpevent_mak
 	 * All notifications for a given association have the same association
 	 * identifier.  For TCP style socket, this field is ignored.
 	 */
-	sctp_ulpevent_set_owner(skb, asoc);
+	sctp_ulpevent_set_owner(event, asoc);
 	sac->sac_assoc_id = sctp_assoc2id(asoc);
 
 	return event;
@@ -281,7 +274,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 * All notifications for a given association have the same association
 	 * identifier.  For TCP style socket, this field is ignored.
 	 */
-	sctp_ulpevent_set_owner(skb, asoc);
+	sctp_ulpevent_set_owner(event, asoc);
 	spc->spc_assoc_id = sctp_assoc2id(asoc);
 
 	/* Sockets API Extensions for SCTP
@@ -294,6 +287,11 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 */
 	memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage));
 
+	/* Map ipv4 address into v4-mapped-on-v6 address.  */
+	sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map(
+					sctp_sk(asoc->base.sk),
+					(union sctp_addr *)&spc->spc_aaddr);
+
 	return event;
 
 fail:
@@ -316,7 +314,7 @@ fail:
  * error formats.
  */
 struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
-	const struct sctp_association *asoc, sctp_chunk_t *chunk,
+	const struct sctp_association *asoc, struct sctp_chunk *chunk,
 	__u16 flags, int gfp)
 {
 	struct sctp_ulpevent *event;
@@ -328,7 +326,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 
 	ch = (sctp_errhdr_t *)(chunk->skb->data);
 	cause = ch->cause;
-	elen = ntohs(ch->length) - sizeof(sctp_errhdr_t);
+	elen = WORD_ROUND(ntohs(ch->length)) - sizeof(sctp_errhdr_t);
 
 	/* Pull off the ERROR header.  */
 	skb_pull(chunk->skb, sizeof(sctp_errhdr_t));
@@ -336,10 +334,8 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	/* Copy the skb to a new skb with room for us to prepend
 	 * notification with.
 	 */
-	skb = skb_copy_expand(chunk->skb,
-			      sizeof(struct sctp_remote_error), /* headroom */
-			      0,                                /* tailroom */
-			      gfp);
+	skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_remote_error),
+			      0, gfp);
 
 	/* Pull off the rest of the cause TLV from the chunk.  */
 	skb_pull(chunk->skb, elen);
@@ -348,10 +344,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
-	event = sctp_ulpevent_init(event, MSG_NOTIFICATION);
-
-	if (!event)
-		goto fail;
+	sctp_ulpevent_init(event, MSG_NOTIFICATION);
 
 	sre = (struct sctp_remote_error *)
 		skb_push(skb, sizeof(struct sctp_remote_error));
@@ -404,8 +397,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 * All notifications for a given association have the same association
 	 * identifier.  For TCP style socket, this field is ignored.
 	 */
-	skb = sctp_event2skb(event);
-	sctp_ulpevent_set_owner(skb, asoc);
+	sctp_ulpevent_set_owner(event, asoc);
 	sre->sre_assoc_id = sctp_assoc2id(asoc);
 
 	return event;
@@ -420,13 +412,16 @@ fail:
  * 5.3.1.4 SCTP_SEND_FAILED
  */
 struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
-	const struct sctp_association *asoc, sctp_chunk_t *chunk,
+	const struct sctp_association *asoc, struct sctp_chunk *chunk,
 	__u16 flags, __u32 error, int gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_send_failed *ssf;
 	struct sk_buff *skb;
 
+	/* Pull off any padding. */
+	int len = ntohs(chunk->chunk_hdr->length);
+
 	/* Make skb with more room so we can prepend notification.  */
 	skb = skb_copy_expand(chunk->skb,
 			      sizeof(struct sctp_send_failed), /* headroom */
@@ -436,13 +431,12 @@ struct sctp_ulpevent *sctp_ulpevent_make
 		goto fail;
 
 	/* Pull off the common chunk header and DATA header.  */
-	skb_pull(skb, sizeof(sctp_data_chunk_t));
+	skb_pull(skb, sizeof(struct sctp_data_chunk));
+	len -= sizeof(struct sctp_data_chunk);
 
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
-	event = sctp_ulpevent_init(event, MSG_NOTIFICATION);
-	if (!event)
-		goto fail;
+	sctp_ulpevent_init(event, MSG_NOTIFICATION);
 
 	ssf = (struct sctp_send_failed *)
 		skb_push(skb, sizeof(struct sctp_send_failed));
@@ -477,7 +471,8 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 * This field is the total length of the notification data, including
 	 * the notification header.
 	 */
-	ssf->ssf_length = skb->len;
+	ssf->ssf_length = sizeof(struct sctp_send_failed) + len;
+	skb_trim(skb, ssf->ssf_length);
 
 	/* Socket Extensions for SCTP
 	 * 5.3.1.4 SCTP_SEND_FAILED
@@ -498,6 +493,11 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 */
 	memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo));
 
+	/* Per TSVWG discussion with Randy. Allow the application to
+	 * ressemble a fragmented message.
+	 */
+	ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags;
+
 	/* Socket Extensions for SCTP
 	 * 5.3.1.4 SCTP_SEND_FAILED
 	 *
@@ -507,8 +507,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 * same association identifier.  For TCP style socket, this field is
 	 * ignored.
 	 */
-	skb = sctp_event2skb(event);
-	sctp_ulpevent_set_owner(skb, asoc);
+	sctp_ulpevent_set_owner(event, asoc);
 	ssf->ssf_assoc_id = sctp_assoc2id(asoc);
 	return event;
 
@@ -571,7 +570,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 * All notifications for a given association have the same association
 	 * identifier.  For TCP style socket, this field is ignored.
 	 */
-	sctp_ulpevent_set_owner(skb, asoc);
+	sctp_ulpevent_set_owner(event, asoc);
 	sse->sse_assoc_id = sctp_assoc2id(asoc);
 
 	return event;
@@ -588,11 +587,12 @@ fail:
  * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
  */
 struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
-		   sctp_chunk_t *chunk, int gfp)
+						struct sctp_chunk *chunk,
+						int gfp)
 {
 	struct sctp_ulpevent *event;
 	struct sctp_sndrcvinfo *info;
-	struct sk_buff *skb, *list;
+	struct sk_buff *skb;
 	size_t padding, len;
 
 	/* Clone the original skb, sharing the data.  */
@@ -618,24 +618,15 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	/* Fixup cloned skb with just this chunks data.  */
 	skb_trim(skb, chunk->chunk_end - padding - skb->data);
 
-	/* Set up a destructor to do rwnd accounting.  */
-	sctp_ulpevent_set_owner_r(skb, asoc);
-
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
 
 	/* Initialize event with flags 0.  */
-	event = sctp_ulpevent_init(event, 0);
-	if (!event)
-		goto fail_init;
+	sctp_ulpevent_init(event, 0);
 
 	event->iif = sctp_chunk_iif(chunk);
-	/* Note:  Not clearing the entire event struct as
-	 * this is just a fragment of the real event.  However,
-	 * we still need to do rwnd accounting.
-	 */
-	for (list = skb_shinfo(skb)->frag_list; list; list = list->next)
-		sctp_ulpevent_set_owner_r(list, asoc);
+
+	sctp_ulpevent_receive_data(event, asoc);
 
 	info = (struct sctp_sndrcvinfo *) &event->sndrcvinfo;
 
@@ -726,9 +717,6 @@ struct sctp_ulpevent *sctp_ulpevent_make
 
 	return event;
 
-fail_init:
-	kfree_skb(skb);
-
 fail:
 	return NULL;
 }
@@ -745,7 +733,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	const struct sctp_association *asoc, __u32 indication, int gfp)
 {
 	struct sctp_ulpevent *event;
-	struct sctp_rcv_pdapi_event *pd;
+	struct sctp_pdapi_event *pd;
 	struct sk_buff *skb;
 
 	event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
@@ -754,8 +742,8 @@ struct sctp_ulpevent *sctp_ulpevent_make
 		goto fail;
 
 	skb = sctp_event2skb(event);
-	pd = (struct sctp_rcv_pdapi_event *)
-		skb_put(skb, sizeof(struct sctp_rcv_pdapi_event));
+	pd = (struct sctp_pdapi_event *)
+		skb_put(skb, sizeof(struct sctp_pdapi_event));
 
 	/* pdapi_type
 	 *   It should be SCTP_PARTIAL_DELIVERY_EVENT
@@ -770,9 +758,9 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 *
 	 * This field is the total length of the notification data, including
 	 * the notification header.  It will generally be sizeof (struct
-	 * sctp_rcv_pdapi_event).
+	 * sctp_pdapi_event).
 	 */
-	pd->pdapi_length = sizeof(struct sctp_rcv_pdapi_event);
+	pd->pdapi_length = sizeof(struct sctp_pdapi_event);
 
         /*  pdapi_indication: 32 bits (unsigned integer)
 	 *
@@ -784,6 +772,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	 *
 	 * The association id field, holds the identifier for the association.
 	 */
+	sctp_ulpevent_set_owner(event, asoc);
 	pd->pdapi_assoc_id = sctp_assoc2id(asoc);
 
 	return event;
@@ -801,7 +790,7 @@ __u16 sctp_ulpevent_get_notification_typ
 
 	skb = sctp_event2skb((struct sctp_ulpevent *)event);
 	notification = (union sctp_notification *) skb->data;
-	return notification->h.sn_type;
+	return notification->sn_header.sn_type;
 }
 
 /* Copy out the sndrcvinfo into a msghdr.  */
@@ -815,69 +804,115 @@ void sctp_ulpevent_read_sndrcvinfo(const
 	}
 }
 
-/* Do accounting for bytes just read by user.  */
-static void sctp_rcvmsg_rfree(struct sk_buff *skb)
+/* Stub skb destructor.  */
+static void sctp_stub_rfree(struct sk_buff *skb)
 {
-	struct sctp_association *asoc;
-	struct sctp_ulpevent *event;
-
-	/* Current stack structures assume that the rcv buffer is
-	 * per socket.   For UDP style sockets this is not true as
-	 * multiple associations may be on a single UDP-style socket.
-	 * Use the local private area of the skb to track the owning
-	 * association.
-	 */
-	event = sctp_skb2event(skb);
-	asoc = event->event_asoc;
-	sctp_assoc_rwnd_increase(asoc, skb_headlen(skb));
-	sctp_association_put(asoc);
+/* WARNING:  This function is just a warning not to use the
+ * skb destructor.  If the skb is shared, we may get the destructor
+ * callback on some processor that does not own the sock_lock.  This
+ * was occuring with PACKET socket applications that were monitoring
+ * our skbs.   We can't take the sock_lock, because we can't risk
+ * recursing if we do really own the sock lock.  Instead, do all
+ * of our rwnd manipulation while we own the sock_lock outright.
+ */
 }
 
-/* Charge receive window for bytes received.  */
-static void sctp_ulpevent_set_owner_r(struct sk_buff *skb,
-				      struct sctp_association *asoc)
+/* Hold the association in case the msg_name needs read out of
+ * the association.
+ */
+static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
+					   const struct sctp_association *asoc)
 {
-	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
 
-	/* The current stack structures assume that the rcv buffer is
-	 * per socket.  For UDP-style sockets this is not true as
-	 * multiple associations may be on a single UDP-style socket.
-	 * We use the local private area of the skb to track the owning
-	 * association.
+	/* Cast away the const, as we are just wanting to
+	 * bump the reference count.
 	 */
-	sctp_association_hold(asoc);
+	sctp_association_hold((struct sctp_association *)asoc);
+	skb = sctp_event2skb(event);
 	skb->sk = asoc->base.sk;
-	event = sctp_skb2event(skb);
-	event->event_asoc = asoc;
+	event->sndrcvinfo.sinfo_assoc_id = sctp_assoc2id(asoc);
+	skb->destructor = sctp_stub_rfree;
+}
+
+/* A simple destructor to give up the reference to the association. */
+static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
+{
+	sctp_association_put(event->sndrcvinfo.sinfo_assoc_id);
+}
 
-	skb->destructor = sctp_rcvmsg_rfree;
+/* Do accounting for bytes received and hold a reference to the association
+ * for each skb.
+ */
+static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
+				       struct sctp_association *asoc)
+{
+	struct sk_buff *skb, *frag;
 
+	skb = sctp_event2skb(event);
+	/* Set the owner and charge rwnd for bytes received.  */
+	sctp_ulpevent_set_owner(event, asoc);
 	sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
+
+	/* Note:  Not clearing the entire event struct as this is just a
+	 * fragment of the real event.  However, we still need to do rwnd
+	 * accounting.
+	 * In general, the skb passed from IP can have only 1 level of
+	 * fragments. But we allow multiple levels of fragments. 
+	 */
+	for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+		sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc);
+	}
 }
 
-/* A simple destructor to give up the reference to the association. */
-static void sctp_ulpevent_rfree(struct sk_buff *skb)
+/* Do accounting for bytes just read by user and release the references to
+ * the association.
+ */ 
+static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
-	struct sctp_ulpevent *event;
+	struct sk_buff *skb, *frag;
 
-	event = sctp_skb2event(skb);
-	sctp_association_put(event->event_asoc);
+	/* Current stack structures assume that the rcv buffer is
+	 * per socket.   For UDP style sockets this is not true as
+	 * multiple associations may be on a single UDP-style socket.
+	 * Use the local private area of the skb to track the owning
+	 * association.
+	 */
+
+	skb = sctp_event2skb(event);
+	sctp_assoc_rwnd_increase(event->sndrcvinfo.sinfo_assoc_id,
+				 skb_headlen(skb));
+
+	/* Don't forget the fragments. */
+	for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+		/* NOTE:  skb_shinfos are recursive. Although IP returns
+		 * skb's with only 1 level of fragments, SCTP reassembly can
+		 * increase the levels.
+		 */
+		sctp_ulpevent_release_data(sctp_skb2event(frag));
+	}
+	sctp_ulpevent_release_owner(event);
 }
 
-/* Hold the association in case the msg_name needs read out of
- * the association.
+/* Free a ulpevent that has an owner.  It includes releasing the reference
+ * to the owner, updating the rwnd in case of a DATA event and freeing the
+ * skb.
+ * See comments in sctp_stub_rfree().
  */
-static void sctp_ulpevent_set_owner(struct sk_buff *skb,
-				    const struct sctp_association *asoc)
+void sctp_ulpevent_free(struct sctp_ulpevent *event)
 {
-	struct sctp_ulpevent *event;
+	if (sctp_ulpevent_is_notification(event))
+		sctp_ulpevent_release_owner(event);
+	else
+		sctp_ulpevent_release_data(event);
 
-	/* Cast away the const, as we are just wanting to
-	 * bump the reference count.
-	 */
-	sctp_association_hold((struct sctp_association *)asoc);
-	skb->sk = asoc->base.sk;
-	event = sctp_skb2event(skb);
-	event->event_asoc = (struct sctp_association *)asoc;
-	skb->destructor = sctp_ulpevent_rfree;
+	kfree_skb(sctp_event2skb(event));
+}
+
+/* Purge the skb lists holding ulpevents. */
+void sctp_queue_purge_ulpevents(struct sk_buff_head *list)
+{
+	struct sk_buff *skb;
+	while ((skb = skb_dequeue(list)) != NULL)
+		sctp_ulpevent_free(sctp_skb2event(skb));
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ulpqueue.c linux-2.4.26-pre6/net/sctp/ulpqueue.c
--- linux-2.4.25/net/sctp/ulpqueue.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.26-pre6/net/sctp/ulpqueue.c	2004-03-25 00:16:47.000000000 +0000
@@ -118,7 +118,7 @@ void sctp_ulpq_free(struct sctp_ulpq *ul
 }
 
 /* Process an incoming DATA chunk.  */
-int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, sctp_chunk_t *chunk,
+int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
 			int gfp)
 {
 	struct sk_buff_head temp;
@@ -163,7 +163,7 @@ int sctp_clear_pd(struct sock *sk)
 	sp->pd_mode = 0;
 	if (!skb_queue_empty(&sp->pd_lobby)) {
 		struct list_head *list;
-		sctp_skb_list_tail(&sp->pd_lobby, &sk->receive_queue);
+		sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue);
 		list = (struct list_head *)&sctp_sk(sk)->pd_lobby;
 		INIT_LIST_HEAD(list);
 		return 1;
@@ -189,7 +189,7 @@ int sctp_ulpq_tail_event(struct sctp_ulp
 	/* If the socket is just going to throw this away, do not
 	 * even try to deliver it.
 	 */
-	if ((sk->dead) || (sk->shutdown & RCV_SHUTDOWN))
+	if (sk->dead || (sk->sk_shutdown & RCV_SHUTDOWN))
 		goto out_free;
 
 	/* Check if the user wishes to receive this event.  */
@@ -202,13 +202,13 @@ int sctp_ulpq_tail_event(struct sctp_ulp
 	 */
 
 	if (!sctp_sk(sk)->pd_mode) {
-		queue = &sk->receive_queue;
+		queue = &sk->sk_receive_queue;
 	} else if (ulpq->pd_mode) {
 		if (event->msg_flags & MSG_NOTIFICATION)
 		       	queue = &sctp_sk(sk)->pd_lobby;
 		else {
 			clear_pd = event->msg_flags & MSG_EOR;
-			queue = &sk->receive_queue;
+			queue = &sk->sk_receive_queue;
 		}
 	} else
 		queue = &sctp_sk(sk)->pd_lobby;
@@ -229,15 +229,15 @@ int sctp_ulpq_tail_event(struct sctp_ulp
 	if (clear_pd)
 		sctp_ulpq_clear_pd(ulpq);
 
-	if (queue == &sk->receive_queue)
-		sk->data_ready(sk, 0);
+	if (queue == &sk->sk_receive_queue)
+		sk->sk_data_ready(sk, 0);
 	return 1;
 
 out_free:
 	if (sctp_event2skb(event)->list)
-		skb_queue_purge(sctp_event2skb(event)->list);
+		sctp_queue_purge_ulpevents(sctp_event2skb(event)->list);
 	else
-		kfree_skb(sctp_event2skb(event));
+		sctp_ulpevent_free(event);
 	return 0;
 }
 
@@ -289,7 +289,7 @@ static inline void sctp_ulpq_store_reasm
  * payload was fragmented on the way and ip had to reassemble them.
  * We add the rest of skb's to the first skb's fraglist.
  */
-static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag)
+static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag)
 {
 	struct sk_buff *pos;
 	struct sctp_ulpevent *event;
@@ -325,11 +325,10 @@ static inline struct sctp_ulpevent *sctp
 
 		/* Remove the fragment from the reassembly queue.  */
 		__skb_unlink(pos, pos->list);
-
+	
 		/* Break if we have reached the last fragment.  */
 		if (pos == l_frag)
 			break;
-
 		pos->next = pnext;
 		pos = pnext;
 	};
@@ -570,7 +569,7 @@ static inline void sctp_ulpq_retrieve_or
 
 	/* We are holding the chunks by stream, by SSN.  */
 	sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
-		cevent = sctp_skb2event(pos);
+		cevent = (struct sctp_ulpevent *) pos->cb;
 		csid = cevent->sndrcvinfo.sinfo_stream;
 		cssn = cevent->sndrcvinfo.sinfo_ssn;
 
@@ -613,7 +612,7 @@ static inline void sctp_ulpq_store_order
 	sid = event->sndrcvinfo.sinfo_stream;
 	ssn = event->sndrcvinfo.sinfo_ssn;
 	
-	cevent = sctp_skb2event(pos);
+	cevent = (struct sctp_ulpevent *) pos->cb;
 	csid = cevent->sndrcvinfo.sinfo_stream;
 	cssn = cevent->sndrcvinfo.sinfo_ssn;
 	if (sid > csid) {
@@ -630,7 +629,7 @@ static inline void sctp_ulpq_store_order
 	 * stream ID and then by SSN.
 	 */
 	skb_queue_walk(&ulpq->lobby, pos) {
-		cevent = sctp_skb2event(pos);
+		cevent = (struct sctp_ulpevent *) pos->cb;
 		csid = cevent->sndrcvinfo.sinfo_stream;
 		cssn = cevent->sndrcvinfo.sinfo_ssn;
 
@@ -773,7 +772,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *
 
 	freed = 0;
 
-	if (skb_queue_empty(&asoc->base.sk->receive_queue)) {
+	if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) {
 		freed = sctp_ulpq_renege_order(ulpq, needed);
 		if (freed < needed) {
 			freed += sctp_ulpq_renege_frags(ulpq, needed - freed);
@@ -812,9 +811,9 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq
 					      SCTP_PARTIAL_DELIVERY_ABORTED,
 					      gfp);
 	if (ev)
-		__skb_queue_tail(&sk->receive_queue, sctp_event2skb(ev));
+		__skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
 
 	/* If there is data waiting, send it up the socket now. */
 	if (sctp_ulpq_clear_pd(ulpq) || ev)
-		sk->data_ready(sk, 0);
+		sk->sk_data_ready(sk, 0);
 }
