diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/CREDITS linux-2.4.26-rc3/CREDITS
--- linux-2.4.25/CREDITS	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/CREDITS	2004-04-12 19:03:48.782821112 +0000
@@ -3386,9 +3386,9 @@ E: yoshfuji@linux-ipv6.org
 W: http://www.yoshifuji.org/~hideaki/
 P: 1024D/E0620EEA 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
 D: IPv6 and other networking related stuff
-D: USAGI/WIDE Project, The University of Tokyo
-S: Green House #102, 1-15-5, Nishikata, 
-S: Bunkyo, Tokyo 113-0024
+D: USAGI/WIDE Project, Keio University
+S: Jeunet Palace Kawasaki #1-201, 10-2, Furukawa-cho, Saiwai-ku
+S: Kawasaki, Kanagawa 212-0025
 S: Japan
 
 N: Eric Youngdale
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/Configure.help linux-2.4.26-rc3/Documentation/Configure.help
--- linux-2.4.25/Documentation/Configure.help	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/Documentation/Configure.help	2004-04-12 19:04:43.095564320 +0000
@@ -1159,6 +1159,14 @@ CONFIG_AMD74XX_OVERRIDE
   This effect can be also invoked by calling "idex=ata66"
   If unsure, say N.
 
+ATI IXP chipset IDE support
+CONFIG_BLK_DEV_ATIIXP
+  This driver adds explicit support for ATI IXP chipset.
+  This allows the kernel to change PIO, DMA and UDMA speeds
+  and to configure the chip to optimum performance.
+
+  Say Y here if you have an ATI IXP chipset IDE controller.
+
 CMD64X/CMD680 chipset support
 CONFIG_BLK_DEV_CMD64X
   Say Y here if you have an IDE controller which uses any of these
@@ -2085,6 +2093,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 +6248,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 +6265,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
@@ -7001,8 +7055,11 @@ CONFIG_PACKET
 
 Packet socket: mmapped IO
 CONFIG_PACKET_MMAP
-  If you say Y here, the Packet protocol driver will use an IO
-  mechanism that results in faster communication.
+  If you say Y here, the Packet protocol driver can use a faster and 
+  more efficient capture method. This feature also allows bigger 
+  receive buffers. To take advantage of this method who have to use 
+  a libpcap library that supports it. For more info see
+  <file:Documentation/networking/packet_mmap.txt>.
 
   If unsure, say N.
 
@@ -10237,6 +10294,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
@@ -10770,6 +10840,14 @@ CONFIG_NET_SCH_TBF
   whenever you want). If you want to compile it as a module, say M
   here and read <file:Documentation/modules.txt>.
 
+Network delay simualtor  
+CONFIG_NET_SCH_DELAY
+  Say Y if you want to delay packets by a fixed amount of
+  time. This is often useful to simulate network delay when
+  testing applications or protocols.
+  
+  This code is also available as a module called sch_delay.o
+
 Ingress Qdisc
 CONFIG_NET_SCH_INGRESS
   If you say Y here, you will be able to police incoming bandwidth
@@ -12358,6 +12436,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 +20007,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 +23621,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 +28781,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-rc3/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-rc3/Documentation/crypto/api-intro.txt	2004-04-12 19:05:09.275584352 +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-rc3/Documentation/kernel-parameters.txt
--- linux-2.4.25/Documentation/kernel-parameters.txt	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/Documentation/kernel-parameters.txt	2004-04-12 19:05:16.150539200 +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-rc3/Documentation/networking/bonding.txt
--- linux-2.4.25/Documentation/networking/bonding.txt	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/Documentation/networking/bonding.txt	2004-04-12 19:01:35.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-rc3/Documentation/networking/ifenslave.c
--- linux-2.4.25/Documentation/networking/ifenslave.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/Documentation/networking/ifenslave.c	2004-04-12 19:01:10.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-rc3/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-rc3/Documentation/networking/ip-sysctl.txt	2004-04-12 19:02:31.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/Documentation/networking/packet_mmap.txt linux-2.4.26-rc3/Documentation/networking/packet_mmap.txt
--- linux-2.4.25/Documentation/networking/packet_mmap.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/Documentation/networking/packet_mmap.txt	2004-04-12 19:05:16.122543456 +0000
@@ -0,0 +1,412 @@
+
+DaveM:
+
+If you agree with it I will send two small patches to modify
+kernel's configure help. 
+
+	Ulisses
+
+--------------------------------------------------------------------------------
++ ABSTRACT
+--------------------------------------------------------------------------------
+
+This file documents the CONFIG_PACKET_MMAP option available with the PACKET
+socket interface on 2.4 and 2.6 kernels. This type of sockets is used for 
+capture network traffic with utilities like tcpdump or any other that uses 
+the libpcap library. 
+
+You can find the latest version of this document at
+
+    http://pusa.uv.es/~ulisses/packet_mmap/
+
+Please send me your comments to
+
+    Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
+
+-------------------------------------------------------------------------------
++ Why use PACKET_MMAP
+--------------------------------------------------------------------------------
+
+In Linux 2.4/2.6 if PACKET_MMAP is not enabled, the capture process is very
+inefficient. It uses very limited buffers and requires one system call
+to capture each packet, it requires two if you want to get packet's 
+timestamp (like libpcap always does).
+
+In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size 
+configurable circular buffer mapped in user space. This way reading packets just 
+needs to wait for them, most of the time there is no need to issue a single 
+system call. By using a shared buffer between the kernel and the user 
+also has the benefit of minimizing packet copies.
+
+It's fine to use PACKET_MMAP to improve the performance of the capture process, 
+but it isn't everything. At least, if you are capturing at high speeds (this 
+is relative to the cpu speed), you should check if the device driver of your 
+network interface card supports some sort of interrupt load mitigation or 
+(even better) if it supports NAPI, also make sure it is enabled.
+
+--------------------------------------------------------------------------------
++ How to use CONFIG_PACKET_MMAP
+--------------------------------------------------------------------------------
+
+From the user standpoint, you should use the higher level libpcap library, wich
+is a de facto standard, portable across nearly all operating systems
+including Win32. 
+
+Said that, at time of this writing, official libpcap 0.8.1 is out and doesn't include
+support for PACKET_MMAP, and also probably the libpcap included in your distribution. 
+
+I'm aware of two implementations of PACKET_MMAP in libpcap:
+
+    http://pusa.uv.es/~ulisses/packet_mmap/  (by Simon Patarin, based on libpcap 0.6.2)
+    http://public.lanl.gov/cpw/              (by Phil Wood, based on lastest libpcap)
+
+The rest of this document is intended for people who want to understand
+the low level details or want to improve libpcap by including PACKET_MMAP
+support.
+
+--------------------------------------------------------------------------------
++ How to use CONFIG_PACKET_MMAP directly
+--------------------------------------------------------------------------------
+
+From the system calls stand point, the use of PACKET_MMAP involves
+the following process:
+
+
+[setup]     socket() -------> creation of the capture socket
+            setsockopt() ---> allocation of the circular buffer (ring)
+            mmap() ---------> maping of the allocated buffer to the
+                              user process
+
+[capture]   poll() ---------> to wait for incoming packets
+
+[shutdown]  close() --------> destruction of the capture socket and
+                              deallocation of all associated 
+                              resources.
+
+
+socket creation and destruction is straight forward, and is done 
+the same way with or without PACKET_MMAP:
+
+int fd;
+
+fd= socket(PF_PACKET, mode, htons(ETH_P_ALL))
+
+where mode is SOCK_RAW for the raw interface were link level
+information can be captured or SOCK_DGRAM for the cooked
+interface where link level information capture is not 
+supported and a link level pseudo-header is provided 
+by the kernel.
+
+The destruction of the socket and all associated resources
+is done by a simple call to close(fd).
+
+Next I will describe PACKET_MMAP settings and it's constraints,
+also the maping of the circular buffer in the user process and 
+the use of this buffer.
+
+--------------------------------------------------------------------------------
++ PACKET_MMAP settings
+--------------------------------------------------------------------------------
+
+
+To setup PACKET_MMAP from user level code is done with a call like
+
+     setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req))
+
+The most significant argument in the previous call is the req parameter, 
+this parameter must to have the following structure:
+
+    struct tpacket_req
+    {
+        unsigned int    tp_block_size;  /* Minimal size of contiguous block */
+        unsigned int    tp_block_nr;    /* Number of blocks */
+        unsigned int    tp_frame_size;  /* Size of frame */
+        unsigned int    tp_frame_nr;    /* Total number of frames */
+    };
+
+This structure is defined in /usr/include/linux/if_packet.h and establishes a 
+circular buffer (ring) of unswappable memory mapped in the capture process. 
+Being mapped in the capture process allows reading the captured frames and 
+related meta-information like timestamps without requiring a system call.
+
+Captured frames are grouped in blocks. Each block is a physically contiguous 
+region of memory and holds tp_block_size/tp_frame_size frames. The total number 
+of blocks is tp_block_nr. Note that tp_frame_nr is a redundant parameter because
+
+    frames_per_block = tp_block_size/tp_frame_size
+
+indeed, packet_set_ring checks that the following condition is true
+
+    frames_per_block * tp_block_nr == tp_frame_nr
+
+
+Lets see an example, with the following values:
+
+     tp_block_size= 4096
+     tp_frame_size= 2048
+     tp_block_nr  = 4
+     tp_frame_nr  = 8
+
+we will get the following buffer structure:
+
+        block #1                 block #2         
++---------+---------+    +---------+---------+    
+| frame 1 | frame 2 |    | frame 3 | frame 4 |    
++---------+---------+    +---------+---------+    
+
+        block #3                 block #4
++---------+---------+    +---------+---------+
+| frame 5 | frame 6 |    | frame 7 | frame 8 |
++---------+---------+    +---------+---------+
+
+A frame can be of any size with the only condition it can fit in a block. A block
+can only hold an integer number of frames, or in other words, a frame cannot 
+be spawn accross two blocks so there are some datails you have to take into 
+account when choosing the frame_size. See "Maping and use of the circular 
+buffer (ring)".
+
+
+--------------------------------------------------------------------------------
++ PACKET_MMAP setting constraints
+--------------------------------------------------------------------------------
+
+In kernel versions prior to 2.4.26 (for the 2.4 branch) and 2.6.5 (2.6 branch),
+the PACKET_MMAP buffer could hold only 32768 frames in a 32 bit architecture or
+16384 in a 64 bit architecture. For information on these kernel versions
+see http://pusa.uv.es/~ulisses/packet_mmap/packet_mmap.pre-2.4.26_2.6.5.txt
+
+ Block size limit
+------------------
+
+As stated earlier, each block is a contiguous physical region of memory. These 
+memory regions are allocated with calls to the __get_free_pages() function. As 
+the name indicates, this function allocates pages of memory, and the second
+argument is "order" or a power of two number of pages, that is 
+(for PAGE_SIZE == 4096) order=0 ==> 4096 bytes, order=1 ==> 8192 bytes, 
+order=2 ==> 16384 bytes, etc. The maximum size of a 
+region allocated by __get_free_pages is determined by the MAX_ORDER macro. More 
+precisely the limit can be calculated as:
+
+   PAGE_SIZE << MAX_ORDER
+
+   In a i386 architecture PAGE_SIZE is 4096 bytes 
+   In a 2.4/i386 kernel MAX_ORDER is 10
+   In a 2.6/i386 kernel MAX_ORDER is 11
+
+So get_free_pages can allocate as much as 4MB or 8MB in a 2.4/2.6 kernel 
+respectively, with an i386 architecture.
+
+User space programs can include /usr/include/sys/user.h and 
+/usr/include/linux/mmzone.h to get PAGE_SIZE MAX_ORDER declarations.
+
+The pagesize can also be determined dynamically with the getpagesize (2) 
+system call. 
+
+
+ Block number limit
+--------------------
+
+To understand the constraints of PACKET_MMAP, we have to see the structure 
+used to hold the pointers to each block.
+
+Currently, this structure is a dynamically allocated vector with kmalloc 
+called pg_vec, its size limits the number of blocks that can be allocated.
+
+    +---+---+---+---+
+    | x | x | x | x |
+    +---+---+---+---+
+      |   |   |   |
+      |   |   |   v
+      |   |   v  block #4
+      |   v  block #3
+      v  block #2
+     block #1
+
+
+kmalloc allocates any number of bytes of phisically contiguous memory from 
+a pool of pre-determined sizes. This pool of memory is mantained by the slab 
+allocator wich is at the end the responsible for doing the allocation and 
+hence wich imposes the maximum memory that kmalloc can allocate. 
+
+In a 2.4/2.6 kernel and the i386 architecture, the limit is 131072 bytes. The 
+predetermined sizes that kmalloc uses can be checked in the "size-<bytes>" 
+entries of /proc/slabinfo
+
+In a 32 bit architecture, pointers are 4 bytes long, so the total number of 
+pointers to blocks is
+
+     131072/4 = 32768 blocks
+
+
+ PACKET_MMAP buffer size calculator
+------------------------------------
+
+Definitions:
+
+<size-max>    : is the maximum size of allocable with kmalloc (see /proc/slabinfo)
+<pointer size>: depends on the architecture -- sizeof(void *)
+<page size>   : depends on the architecture -- PAGE_SIZE or getpagesize (2)
+<max-order>   : is the value defined with MAX_ORDER
+<frame size>  : it's an upper bound of frame's capture size (more on this later)
+
+from these definitions we will derive 
+
+	<block number> = <size-max>/<pointer size>
+	<block size> = <pagesize> << <max-order>
+
+so, the max buffer size is
+
+	<block number> * <block size>
+
+and, the number of frames be
+
+	<block number> * <block size> / <frame size>
+
+Suposse the following parameters, wich apply for 2.6 kernel and an
+i386 architecture:
+
+	<size-max> = 131072 bytes
+	<pointer size> = 4 bytes
+	<pagesize> = 4096 bytes
+	<max-order> = 11
+
+and a value for <frame size> of 2048 byteas. These parameters will yield
+
+	<block number> = 131072/4 = 32768 blocks
+	<block size> = 4096 << 11 = 8 MiB.
+
+and hence the buffer will have a 262144 MiB size. So it can hold 
+262144 MiB / 2048 bytes = 134217728 frames
+
+
+Actually, this buffer size is not possible with an i386 architecture. 
+Remember that the memory is allocated in kernel space, in the case of 
+an i386 kernel's memory size is limited to 1GiB.
+
+All memory allocations are not freed until the socket is closed. The memory 
+allocations are done with GFP_KERNEL priority, this basically means that 
+the allocation can wait and swap other process' memory in order to allocate 
+the nececessary memory, so normally limits can be reached.
+
+ Other constraints
+-------------------
+
+If you check the source code you will see that what I draw here as a frame
+is not only the link level frame. At the begining of each frame there is a 
+header called struct tpacket_hdr used in PACKET_MMAP to hold link level's frame
+meta information like timestamp. So what we draw here a frame it's really 
+the following (from include/linux/if_packet.h):
+
+/*
+   Frame structure:
+
+   - Start. Frame must be aligned to TPACKET_ALIGNMENT=16
+   - struct tpacket_hdr
+   - pad to TPACKET_ALIGNMENT=16
+   - struct sockaddr_ll
+   - Gap, chosen so that packet data (Start+tp_net) alignes to 
+     TPACKET_ALIGNMENT=16
+   - Start+tp_mac: [ Optional MAC header ]
+   - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
+   - Pad to align to TPACKET_ALIGNMENT=16
+ */
+           
+ 
+ The following are conditions that are checked in packet_set_ring
+
+   tp_block_size must be a multiple of PAGE_SIZE (1)
+   tp_frame_size must be greater than TPACKET_HDRLEN (obvious)
+   tp_frame_size must be a multiple of TPACKET_ALIGNMENT
+   tp_frame_nr   must be exactly frames_per_block*tp_block_nr
+
+Note that tp_block_size should be choosed to be a power of two or there will
+be a waste of memory.
+
+--------------------------------------------------------------------------------
++ Maping and use of the circular buffer (ring)
+--------------------------------------------------------------------------------
+
+The maping of the buffer in the user process is done with the conventional 
+mmap function. Even the circular buffer is compound of several physically
+discontiguous blocks of memory, they are contiguous to the user space, hence
+just one call to mmap is needed:
+
+    mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+If tp_frame_size is a divisor of tp_block_size frames will be 
+contiguosly spaced by tp_frame_size bytes. If not, each 
+tp_block_size/tp_frame_size frames there will be a gap between 
+the frames. This is because a frame cannot be spawn across two
+blocks. 
+
+At the beginning of each frame there is an status field (see 
+struct tpacket_hdr). If this field is 0 means that the frame is ready
+to be used for the kernel, If not, there is a frame the user can read 
+and the following flags apply:
+
+     from include/linux/if_packet.h
+
+     #define TP_STATUS_COPY          2 
+     #define TP_STATUS_LOSING        4 
+     #define TP_STATUS_CSUMNOTREADY  8 
+
+
+TP_STATUS_COPY        : This flag indicates that the frame (and associated
+                        meta information) has been truncated because it's 
+                        larger than tp_frame_size. This packet can be 
+                        read entirely with recvfrom().
+                        
+                        In order to make this work it must to be
+                        enabled previously with setsockopt() and 
+                        the PACKET_COPY_THRESH option. 
+
+                        The number of frames than can be buffered to 
+                        be read with recvfrom is limited like a normal socket.
+                        See the SO_RCVBUF option in the socket (7) man page.
+
+TP_STATUS_LOSING      : indicates there were packet drops from last time 
+                        statistics where checked with getsockopt() and
+                        the PACKET_STATISTICS option.
+
+TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets wich 
+                        it's checksum will be done in hardware. So while 
+                        reading the packet we should not try to check the 
+                        checksum. 
+
+for convenience there are also the following defines:
+
+     #define TP_STATUS_KERNEL        0
+     #define TP_STATUS_USER          1
+
+The kernel initializes all frames to TP_STATUS_KERNEL, when the kernel
+receives a packet it puts in the buffer and updates the status with
+at least the TP_STATUS_USER flag. Then the user can read the packet,
+once the packet is read the user must zero the status field, so the kernel 
+can use again that frame buffer.
+
+The user can use poll (any other variant should apply too) to check if new
+packets are in the ring:
+
+    struct pollfd pfd;
+
+    pfd.fd = fd;
+    pfd.revents = 0;
+    pfd.events = POLLIN|POLLRDNORM|POLLERR;
+
+    if (status == TP_STATUS_KERNEL)
+        retval = poll(&pfd, 1, timeout);
+
+It doesn't incur in a race condition to first check the status value and 
+then poll for frames.
+
+--------------------------------------------------------------------------------
++ THANKS
+--------------------------------------------------------------------------------
+   
+   Jesse Brandeburg, for fixing my grammathical/spelling errors
+
+>>> EOF
+-
+To unsubscribe from this list: send the line "unsubscribe linux-net" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at  http://vger.kernel.org/majordomo-info.html
\ No newline at end of file
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/MAINTAINERS linux-2.4.26-rc3/MAINTAINERS
--- linux-2.4.25/MAINTAINERS	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/MAINTAINERS	2004-04-12 19:03:21.098029840 +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-rc3/Makefile
--- linux-2.4.25/Makefile	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.26-rc3/Makefile	2004-04-12 19:03:35.874783432 +0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 25
-EXTRAVERSION =
+SUBLEVEL = 26
+EXTRAVERSION = -rc3
 
 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/alpha/lib/ev6-stxncpy.S linux-2.4.26-rc3/arch/alpha/lib/ev6-stxncpy.S
--- linux-2.4.25/arch/alpha/lib/ev6-stxncpy.S	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.26-rc3/arch/alpha/lib/ev6-stxncpy.S	2004-04-12 19:04:08.113882344 +0000
@@ -365,7 +365,7 @@ $unaligned:
 	andnot	t2, t6, t12	# E : dest mask for a single word copy
 	or	t8, t10, t5	# E : test for end-of-count too
 
-	cmpbge	zero, t2, t3	# E :
+	cmpbge	zero, t12, t3	# E :
 	cmoveq	a2, t5, t8	# E : Latency=2, extra map slot
 	nop			# E : keep with cmoveq
 	andnot	t8, t3, t8	# E : (stall)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/alpha/lib/stxncpy.S linux-2.4.26-rc3/arch/alpha/lib/stxncpy.S
--- linux-2.4.25/arch/alpha/lib/stxncpy.S	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.26-rc3/arch/alpha/lib/stxncpy.S	2004-04-12 19:04:59.231111344 +0000
@@ -317,7 +317,7 @@ $unaligned:
 	cmpbge	zero, t1, t8	# .. e1 : is there a zero?
 	andnot	t2, t6, t12	# e0    : dest mask for a single word copy
 	or	t8, t10, t5	# .. e1 : test for end-of-count too
-	cmpbge	zero, t2, t3	# e0    :
+	cmpbge	zero, t12, t3	# e0    :
 	cmoveq	a2, t5, t8	# .. e1 :
 	andnot	t8, t3, t8	# e0    :
 	beq	t8, $u_head	# .. e1 (zdb)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/defconfig linux-2.4.26-rc3/arch/i386/defconfig
--- linux-2.4.25/arch/i386/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/i386/defconfig	2004-04-12 19:00:51.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-rc3/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-rc3/arch/i386/kernel/acpi.c	2004-04-12 19:04:20.413012592 +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,59 @@ acpi_parse_ioapic (
 	return 0;
 }
 
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+{
+	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_config_acpi_legacy_irqs() already setup IRQs < 16
+	 * If GSI is < 16, this will update its flags,
+	 * else it will create a new mp_irqs[] entry.
+	 */
+	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+
+	/*
+	 * stash over-ride to indicate we've been here
+	 * and for later update of acpi_fadt
+	 */
+	acpi_sci_override_gsi = gsi;
+	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 +282,12 @@ acpi_parse_int_src_ovr (
 
 	acpi_table_print_madt_entry(header);
 
+	if (intsrc->bus_irq == acpi_fadt.sci_int) {
+		acpi_sci_ioapic_setup(intsrc->global_irq,
+			intsrc->flags.polarity, intsrc->flags.trigger);
+		return 0;
+	}
+
 	mp_override_legacy_irq (
 		intsrc->bus_irq,
 		intsrc->flags.polarity,
@@ -307,7 +368,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 +395,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 +505,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 +515,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_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
+
 	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 +543,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,56 +559,41 @@ 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 */
 
 
 
+#ifndef __HAVE_ARCH_CMPXCHG
+#warning ACPI uses CMPXCHG, i486 and later hardware
+#endif
+
 /* --------------------------------------------------------------------------
                               Low-Level Sleep Support
    -------------------------------------------------------------------------- */
@@ -656,7 +710,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-rc3/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-rc3/arch/i386/kernel/dmi_scan.c	2004-04-12 19:02:12.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-rc3/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-rc3/arch/i386/kernel/i386_ksyms.c	2004-04-12 19:05:05.716125472 +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/io_apic.c linux-2.4.26-rc3/arch/i386/kernel/io_apic.c
--- linux-2.4.25/arch/i386/kernel/io_apic.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/i386/kernel/io_apic.c	2004-04-12 19:02:00.000000000 +0000
@@ -1864,7 +1864,11 @@ int io_apic_set_pci_routing (int ioapic,
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
 
-	add_pin_to_irq(irq, ioapic, pin);
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= 16)
+		add_pin_to_irq(irq, ioapic, pin);
 
 	entry.vector = assign_irq_vector(irq);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/microcode.c linux-2.4.26-rc3/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-rc3/arch/i386/kernel/microcode.c	2004-04-12 19:01:27.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-rc3/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-rc3/arch/i386/kernel/mpparse.c	2004-04-12 19:01:53.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-rc3/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-rc3/arch/i386/kernel/pci-irq.c	2004-04-12 19:05:07.283887136 +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-rc3/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-rc3/arch/i386/kernel/setup.c	2004-04-12 19:02: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-rc3/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-rc3/arch/i386/kernel/smpboot.c	2004-04-12 19:02:46.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-rc3/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-rc3/arch/i386/mm/init.c	2004-04-12 19:03:58.807297160 +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-rc3/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-rc3/arch/ia64/ia32/ia32_signal.c	2004-04-12 19:00:19.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-rc3/arch/ia64/kernel/Makefile
--- linux-2.4.25/arch/ia64/kernel/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/ia64/kernel/Makefile	2004-04-12 19:05:05.671132312 +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-rc3/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-rc3/arch/ia64/kernel/acpi.c	2004-04-12 19:02:49.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-rc3/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-rc3/arch/ia64/kernel/ia64_ksyms.c	2004-04-12 19:02:42.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-rc3/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-rc3/arch/ia64/kernel/mca.c	2004-04-12 19:02:45.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-rc3/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-rc3/arch/ia64/kernel/pci.c	2004-04-12 19:02:38.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-rc3/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-rc3/arch/ia64/kernel/ptrace.c	2004-04-12 19:05:00.213961928 +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-rc3/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-rc3/arch/ia64/kernel/salinfo.c	2004-04-12 19:02:38.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-rc3/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-rc3/arch/ia64/kernel/signal.c	2004-04-12 19:03:15.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-rc3/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-rc3/arch/ia64/kernel/smpboot.c	2004-04-12 19:01:31.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-rc3/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-rc3/arch/ia64/kernel/unwind.c	2004-04-12 19:05:16.183534184 +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-rc3/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-rc3/arch/ia64/kernel/unwind_i.h	2004-04-12 19:02:31.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-rc3/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-rc3/arch/ia64/sn/kernel/mca.c	2004-04-12 19:01:41.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-rc3/arch/ia64/tools/Makefile
--- linux-2.4.25/arch/ia64/tools/Makefile	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ia64/tools/Makefile	2004-04-12 19:03:00.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-rc3/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-rc3/arch/m68k/mac/baboon.c	2004-04-12 19:03:46.924103680 +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-rc3/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-rc3/arch/m68k/mac/config.c	2004-04-12 19:02:30.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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/arch/ppc/Makefile
--- linux-2.4.25/arch/ppc/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/Makefile	2004-04-12 19:00:33.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/common/misc-simple.c linux-2.4.26-rc3/arch/ppc/boot/common/misc-simple.c
--- linux-2.4.25/arch/ppc/boot/common/misc-simple.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/boot/common/misc-simple.c	2004-04-12 19:04:11.968296384 +0000
@@ -75,7 +75,7 @@ extern void serial_close(unsigned long c
 extern void gunzip(void *, int, unsigned char *, int *);
 extern void serial_fixups(void);
 
-static struct bi_record *
+struct bi_record *
 decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		void *ignored)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/boot/simple/embed_config.c linux-2.4.26-rc3/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-rc3/arch/ppc/boot/simple/embed_config.c	2004-04-12 19:04:13.778021264 +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-rc3/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-rc3/arch/ppc/boot/simple/m8260_tty.c	2004-04-12 19:03:54.865896344 +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-rc3/arch/ppc/config.in
--- linux-2.4.25/arch/ppc/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/config.in	2004-04-12 19:03:07.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-rc3/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-rc3/arch/ppc/configs/ads8272_defconfig	2004-04-12 19:02:53.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-rc3/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-rc3/arch/ppc/configs/ep405_defconfig	2004-04-12 19:03:35.204885272 +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-rc3/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-rc3/arch/ppc/configs/est8260_defconfig	2004-04-12 19:03:02.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-rc3/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-rc3/arch/ppc/configs/redwood5_defconfig	2004-04-12 19:02:20.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-rc3/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-rc3/arch/ppc/configs/redwood6_defconfig	2004-04-12 19:05:09.254587544 +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-rc3/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-rc3/arch/ppc/configs/rpx8260_defconfig	2004-04-12 19:02:56.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-rc3/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-rc3/arch/ppc/cpm2_io/Config.in	2004-04-12 19:00:22.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-rc3/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-rc3/arch/ppc/cpm2_io/Makefile	2004-04-12 19:03:47.686987704 +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-rc3/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-rc3/arch/ppc/cpm2_io/commproc.c	2004-04-12 19:00:02.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-rc3/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-rc3/arch/ppc/cpm2_io/enet.c	2004-04-12 19:00:05.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-rc3/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-rc3/arch/ppc/cpm2_io/fcc_enet.c	2004-04-12 19:02:42.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-rc3/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-rc3/arch/ppc/cpm2_io/uart.c	2004-04-12 19:00:38.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-rc3/arch/ppc/kernel/Makefile
--- linux-2.4.25/arch/ppc/kernel/Makefile	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/Makefile	2004-04-12 19:04:35.869662824 +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,14 +54,17 @@ 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_40x)		+= ppc4xx_setup.o
-obj-$(CONFIG_4xx)		+= ocp.o ppc4xx_pic.o todc_time.o
+obj-$(CONFIG_PPC_OCP)		+= ocp.o
+obj-$(CONFIG_40x)		+= ppc4xx_setup.o ppc4xx_pic.o
+obj-$(CONFIG_4xx)		+= 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
 endif
-obj-$(CONFIG_44x)		+= ibm44x_common.o
+obj-$(CONFIG_44x)		+= ppc4xx_pic.o ibm44x_common.o
 obj-$(CONFIG_440GP)		+= ibm440gp_common.o
+obj-$(CONFIG_440GX)		+= ibm440gx_common.o
 obj-$(CONFIG_PPC4xx_DMA)	+= ppc4xx_dma.o
 obj-$(CONFIG_PPC4xx_EDMA)	+= ppc4xx_sgdma.o
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
@@ -85,7 +89,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-rc3/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-rc3/arch/ppc/kernel/cpm2_pic.c	2004-04-12 19:03:07.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-rc3/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-rc3/arch/ppc/kernel/cpm2_pic.h	2004-04-12 19:04:48.064808880 +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/cputable.c linux-2.4.26-rc3/arch/ppc/kernel/cputable.c
--- linux-2.4.25/arch/ppc/kernel/cputable.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/cputable.c	2004-04-12 19:03:02.000000000 +0000
@@ -417,6 +417,20 @@ struct cpu_spec	cpu_specs[] = {
         32, 32,
         0, /*__setup_cpu_440 */
     },
+    { /* 440GX Rev. B */
+        0xf0000fff, 0x50000851, "440GX Rev. B",
+        CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+        PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+        32, 32,
+        0, /*__setup_cpu_440 */
+    },
+    { /* 440GX Rev. B1 (2.1) */
+        0xf0000fff, 0x50000852, "440GX Rev. B1 (2.1)",
+        CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+        PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+        32, 32,
+        0, /*__setup_cpu_440 */
+    },
 #endif /* CONFIG_44x */
 #if !CLASSIC_PPC
     {	/* default match */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/entry.S linux-2.4.26-rc3/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-rc3/arch/ppc/kernel/entry.S	2004-04-12 19:04:33.332048600 +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-rc3/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-rc3/arch/ppc/kernel/head.S	2004-04-12 19:00:10.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/head_44x.S linux-2.4.26-rc3/arch/ppc/kernel/head_44x.S
--- linux-2.4.25/arch/ppc/kernel/head_44x.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/head_44x.S	2004-04-12 19:00:10.000000000 +0000
@@ -30,6 +30,16 @@
 #define STND_EXC        0
 #define CRIT_EXC        1
 
+#ifdef CONFIG_440A
+#define MCHK_EXC	2
+#define __SPRN_MCSRR0	SPRN_MCSRR0
+#define __SPRN_MCSRR1	SPRN_MCSRR1
+#else
+#define MCHK_EXC	CRIT_EXC
+#define __SPRN_MCSRR0	SPRN_CSRR0
+#define __SPRN_MCSRR1	SPRN_CSRR1
+#endif
+
 /*
  * Macros
  */
@@ -396,7 +406,25 @@ interrupt_base:
 
 	/* Machine Check Interrupt */
 	/* TODO: provide bus error register status */
-	CRIT_EXCEPTION(0x200, MachineCheck,MachineCheckException);
+	START_EXCEPTION(MachineCheck)
+	COMMON_PROLOG;
+	mfspr   r22,__SPRN_MCSRR0       /* Faulting instruction address    */
+	lis     r20,MSR_WE@h
+	mfspr   r23,__SPRN_MCSRR1       /* MSR at the time of fault        */
+	andc    r23,r23,r20             /* disable processor wait state    */
+	COMMON_EPILOG;
+#ifdef CONFIG_440A
+	lis	r20,MCSR_MCS@h
+	mfspr	r4,SPRN_MCSR		/* We may want to access original
+					   MCSR as arg2 in the future. --ebs */
+	mtspr	SPRN_MCSR,r20		/* Clear Machine Check Summary field */
+#endif	
+	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it */
+	stw	r5,_ESR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r7,MCHK_EXC
+	li	r20,MSR_KERNEL
+	FINISH_EXCEPTION(0x200, MachineCheckException)
 
 	/* Data Storage Interrupt */
 	START_EXCEPTION(DataStorage)
@@ -415,7 +443,7 @@ interrupt_base:
 	 * offending address and handle it.
 	 */
 	mfspr	r20, SPRN_ESR
-	andis.	r20, r20, ESR_ST@h
+	andis.	r20, r20, ESR_DST@h
 	beq	2f
 
 	mfspr	r20, SPRN_DEAR		/* Get faulting address */
@@ -994,7 +1022,7 @@ _GLOBAL(transfer_to_handler)
 	lwz	r24,0(r23)		/* Virtual address of the handler */
 	lwz	r23,4(r23)		/* Handler return pointer */
 	cmpwi	cr0,r7,STND_EXC		/* What type of exception is this? */
-	bne	3f			/* It is a critical exception... */
+	bne	3f			/* It is a critical/machine check exception... */
 
 	/* Standard exception jump path
 	*/
@@ -1010,19 +1038,23 @@ _GLOBAL(transfer_to_handler)
 	mtspr	SPRN_SRR1,r20		/* Set up the machine state register */
 	mtlr	r23			/* Set up the return pointer */
 	SYNC
-	/* We shouldn't need a 405 erratum #77 workaround here, because we're not
-	 * actually returning to the interrupted instruction yet. */
 	rfi
 
-	/* Critical exception jump path
+	/* Critical/Machine check exception jump path
 	*/
-
-3:	mtspr	SPRN_CSRR0,r24		/* Set up the instruction pointer */
-	mtspr	SPRN_CSRR1,r20		/* Set up the machine state register */
+3:	cmpwi	r7,CRIT_EXC		/* Critical or machine check ? */
 	mtlr	r23			/* Set up the return pointer */
+	bne	4f
+	mtspr	SPRN_CSRR0,r24		/* Set up the instruction pointer */
+	mtspr	SPRN_CSRR1,r20		/* Set up the machine state register */
 	SYNC
 	rfci
 
+4:	mtspr	SPRN_MCSRR0,r24		/* Set up the instruction pointer */
+	mtspr	SPRN_MCSRR1,r20		/* Set up the machine state register */
+	SYNC	
+	RFMCI
+
 /* On kernel stack overlow, load up an initial stack pointer and call
  * StackOverflow(regs), which should NOT return.
  */ 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ibm440gp_common.c linux-2.4.26-rc3/arch/ppc/kernel/ibm440gp_common.c
--- linux-2.4.25/arch/ppc/kernel/ibm440gp_common.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/ibm440gp_common.c	2004-04-12 19:02:32.000000000 +0000
@@ -25,7 +25,7 @@
 /*
  * Calculate 440GP clocks
  */
-void __init ibm440gp_get_clocks(struct ibm440gp_clocks* p, unsigned int sys_clk, 
+void __init ibm440gp_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, 
 	unsigned int ser_clk)
 {
 	u32 cpc0_sys0 = mfdcr(DCRN_CPC0_SYS0);
@@ -68,11 +68,11 @@ void __init ibm440gp_get_clocks(struct i
     
 	if (cpc0_cr0 & 0x00400000){
 		/* External UART clock */
-		p->uart = ser_clk;
+		p->uart0 = p->uart1 = ser_clk;
 	}
 	else {
 		/* Internal UART clock */    
     		u32 uart_div = ((cpc0_cr0 >> 16) & 0x1f) + 1;
-		p->uart = p->plb / uart_div;
+		p->uart0 = p->uart1 = p->plb / uart_div;
 	}
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ibm440gp_common.h linux-2.4.26-rc3/arch/ppc/kernel/ibm440gp_common.h
--- linux-2.4.25/arch/ppc/kernel/ibm440gp_common.h	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/ibm440gp_common.h	2004-04-12 19:01:29.000000000 +0000
@@ -20,24 +20,14 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-
-/*
- * All clocks are in Hz
- */
-struct ibm440gp_clocks {
-	unsigned int cpu;	/* CPUCoreClk */
-	unsigned int plb;	/* PLBClk */
-	unsigned int opb;	/* OPBClk */
-	unsigned int ebc;	/* PerClk */
-	unsigned int uart;	
-};
+#include <kernel/ibm44x_common.h>
 
 /*
  * Please, refer to the Figure 13.1 in 440GP user manual
  * 
  * if internal UART clock is used, ser_clk is ignored
  */
-void ibm440gp_get_clocks(struct ibm440gp_clocks*, unsigned int sys_clk, 
+void ibm440gp_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk, 
 	unsigned int ser_clk) __init;
  
 #endif /* __ASSEMBLY__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ibm440gx_common.c linux-2.4.26-rc3/arch/ppc/kernel/ibm440gx_common.c
--- linux-2.4.25/arch/ppc/kernel/ibm440gx_common.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/ibm440gx_common.c	2004-04-12 19:02:56.000000000 +0000
@@ -0,0 +1,191 @@
+/*
+ * arch/ppc/kernel/ibm440gx_common.c
+ *
+ * PPC440GX system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <asm/ibm44x.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <kernel/ibm440gx_common.h>
+
+/*
+ * Calculate 440GX clocks
+ */
+static inline u32 __fix_zero(u32 v, u32 def){
+	return v ? v : def;
+}
+ 
+void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, 
+	unsigned int ser_clk)
+{
+	u32 pllc  = CPR_READ(DCRN_CPR_PLLC);
+	u32 plld  = CPR_READ(DCRN_CPR_PLLD);
+	u32 uart0 = SDR_READ(DCRN_SDR_UART0);
+	u32 uart1 = SDR_READ(DCRN_SDR_UART1);
+	
+	/* Dividers */
+	u32 fbdv   = __fix_zero((plld >> 24) & 0x1f, 32);
+	u32 fwdva  = __fix_zero((plld >> 16) & 0xf, 16);
+	u32 fwdvb  = __fix_zero((plld >> 8) & 7, 8);
+	u32 lfbdv  = __fix_zero(plld & 0x3f, 64);
+	u32 pradv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMAD) >> 24) & 7, 8);
+	u32 prbdv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMBD) >> 24) & 7, 8);
+	u32 opbdv0 = __fix_zero((CPR_READ(DCRN_CPR_OPBD) >> 24) & 3, 4);
+	u32 perdv0 = __fix_zero((CPR_READ(DCRN_CPR_PERD) >> 24) & 3, 4);
+
+	/* Input clocks for primary dividers */	
+	u32 clk_a, clk_b;
+
+	if (pllc & 0x40000000){
+		u32 m;
+	    
+		/* Feedback path */
+		switch ((pllc >> 24) & 7){
+		case 0:
+			/* PLLOUTx */
+			m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
+			break;
+		case 1:
+			/* CPU */
+			m = fwdva * pradv0;
+			break;
+		case 5:
+			/* PERClk */
+			m = fwdvb * prbdv0 * opbdv0 * perdv0;
+			break;
+		default:
+			printk(KERN_EMERG "invalid PLL feedback source\n");
+			goto bypass;
+		}
+		m *= fbdv;
+		p->vco = sys_clk * m;
+		clk_a = p->vco / fwdva;
+		clk_b = p->vco / fwdvb;
+	}
+	else {
+bypass:	
+		/* Bypass system PLL */
+		p->vco = 0;
+		clk_a = clk_b = sys_clk;
+	}
+	
+	p->cpu = clk_a / pradv0;
+	p->plb = clk_b / prbdv0;
+	p->opb = p->plb / opbdv0;
+	p->ebc = p->opb / perdv0;
+	
+	/* UARTs clock */
+	if (uart0 & 0x00800000)
+		p->uart0 = ser_clk;
+	else
+		p->uart0 = p->plb / __fix_zero(uart0 & 0xff, 256);
+
+	if (uart1 & 0x00800000)
+		p->uart1 = ser_clk;
+	else
+		p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256);
+}
+
+/* Enable L2 cache (call with IRQs disabled) */
+void __init ibm440gx_l2c_enable(void){
+	u32 r;
+	
+	asm volatile ("sync" ::: "memory");
+
+	/* Disable SRAM */
+	mtdcr(DCRN_SRAM0_DPC,   mfdcr(DCRN_SRAM0_DPC)   & ~SRAM_DPC_ENABLE);
+	mtdcr(DCRN_SRAM0_SB0CR, mfdcr(DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
+	mtdcr(DCRN_SRAM0_SB1CR, mfdcr(DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
+	mtdcr(DCRN_SRAM0_SB2CR, mfdcr(DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
+	mtdcr(DCRN_SRAM0_SB3CR, mfdcr(DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
+	
+	/* Enable L2_MODE without ICU/DCU */
+	r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
+	r |= L2C_CFG_L2M | L2C_CFG_SS_256;
+	mtdcr(DCRN_L2C0_CFG, r);
+	
+	mtdcr(DCRN_L2C0_ADDR, 0);
+	
+	/* Hardware Clear Command */
+	mtdcr(DCRN_L2C0_CMD, L2C_CMD_HCC);
+	while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;
+	
+	/* Clear Cache Parity and Tag Errors */
+	mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
+	
+	/* Enable 64G snoop region starting at 0 */
+	r = mfdcr(DCRN_L2C0_SNP0) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
+	r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
+	mtdcr(DCRN_L2C0_SNP0, r);
+
+	r = mfdcr(DCRN_L2C0_SNP1) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
+	r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
+	mtdcr(DCRN_L2C0_SNP1, r);
+	
+	asm volatile ("sync" ::: "memory");
+	
+	/* Enable ICU/DCU ports */
+	r = mfdcr(DCRN_L2C0_CFG);
+	r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM 
+		| L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI | L2C_CFG_CPEI
+		| L2C_CFG_NAM | L2C_CFG_NBRM);
+	r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN 
+		| L2C_CFG_SMCM;
+	mtdcr(DCRN_L2C0_CFG, r);
+	
+	asm volatile ("sync; isync" ::: "memory");
+}
+
+/* Disable L2 cache (call with IRQs disabled) */
+void __init ibm440gx_l2c_disable(void){
+	u32 r;
+	
+	asm volatile ("sync" ::: "memory");
+
+	/* Disable L2C mode */
+	r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_L2M | L2C_CFG_ICU | L2C_CFG_DCU);
+	mtdcr(DCRN_L2C0_CFG, r);
+
+	/* Enable SRAM */
+	mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) | SRAM_DPC_ENABLE);
+	mtdcr(DCRN_SRAM0_SB0CR,
+	      SRAM_SBCR_BAS0 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	mtdcr(DCRN_SRAM0_SB1CR,
+	      SRAM_SBCR_BAS1 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	mtdcr(DCRN_SRAM0_SB2CR,
+	      SRAM_SBCR_BAS2 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	mtdcr(DCRN_SRAM0_SB3CR,
+	      SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	
+	asm volatile ("sync; isync" ::: "memory");
+}
+
+int ibm440gx_show_cpuinfo(struct seq_file *m){
+
+	u32 l2c_cfg = mfdcr(DCRN_L2C0_CFG);
+	const char* s;
+	if (l2c_cfg & L2C_CFG_L2M){
+	    switch (l2c_cfg & (L2C_CFG_ICU | L2C_CFG_DCU)){
+		case L2C_CFG_ICU: s = "I-Cache only";    break;
+		case L2C_CFG_DCU: s = "D-Cache only";    break;
+		default:	  s = "I-Cache/D-Cache"; break;	
+	    }
+	}
+	else
+	    s = "disabled";
+
+	seq_printf(m, "L2-Cache\t: %s (0x%08x 0x%08x)\n", s, 
+	    l2c_cfg, mfdcr(DCRN_L2C0_SR));
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ibm440gx_common.h linux-2.4.26-rc3/arch/ppc/kernel/ibm440gx_common.h
--- linux-2.4.25/arch/ppc/kernel/ibm440gx_common.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/ibm440gx_common.h	2004-04-12 19:03:23.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ * arch/ppc/kernel/ibm440gx_common.h
+ *
+ * PPC440GX system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM440GX_COMMON_H
+#define __PPC_SYSLIB_IBM440GX_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <kernel/ibm44x_common.h>
+
+/*
+ * Please, refer to the Figure 14.1 in 440GX user manual
+ * 
+ * if internal UART clock is used, ser_clk is ignored
+ */
+void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk, 
+	unsigned int ser_clk) __init;
+
+/* Enable L2 cache */
+void ibm440gx_l2c_enable(void) __init;
+
+/* Add L2C info to /proc/cpuinfo */
+int ibm440gx_show_cpuinfo(struct seq_file*);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM440GX_COMMON_H */
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/ibm44x_common.h linux-2.4.26-rc3/arch/ppc/kernel/ibm44x_common.h
--- linux-2.4.25/arch/ppc/kernel/ibm44x_common.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/ibm44x_common.h	2004-04-12 19:05:16.954416992 +0000
@@ -0,0 +1,36 @@
+/*
+ * arch/ppc/kernel/ibm44x_common.h
+ *
+ * PPC44x system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM44x_COMMON_H
+#define __PPC_SYSLIB_IBM44x_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * All clocks are in Hz
+ */
+struct ibm44x_clocks {
+	unsigned int vco;	/* VCO, 0 if system PLL is bypassed */
+	unsigned int cpu;	/* CPUCoreClk */
+	unsigned int plb;	/* PLBClk */
+	unsigned int opb;	/* OPBClk */
+	unsigned int ebc;	/* PerClk */
+	unsigned int uart0;
+	unsigned int uart1;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM44x_COMMON_H */
+#endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/kernel/m8260_setup.c linux-2.4.26-rc3/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-rc3/arch/ppc/kernel/m8260_setup.c	2004-04-12 19:02:55.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-rc3/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-rc3/arch/ppc/kernel/misc.S	2004-04-12 19:04:40.066024880 +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-rc3/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-rc3/arch/ppc/kernel/ocp.c	2004-04-12 19:03:03.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-rc3/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-rc3/arch/ppc/kernel/ppc4xx_stbdma.c	2004-04-12 19:05:15.203683144 +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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/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-rc3/arch/ppc/kernel/setup.c	2004-04-12 19:04:46.469051472 +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/kernel/traps.c linux-2.4.26-rc3/arch/ppc/kernel/traps.c
--- linux-2.4.25/arch/ppc/kernel/traps.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/kernel/traps.c	2004-04-12 19:01:20.000000000 +0000
@@ -212,15 +212,44 @@ MachineCheckException(struct pt_regs *re
 	if (check_io_access(regs))
 		return;
 
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
 	if (reason & ESR_IMCP) {
 		printk("Instruction");
 		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
 	} else
 		printk("Data");
 	printk(" machine check in kernel mode.\n");
-
-#else /* !CONFIG_4xx */
+#elif defined(CONFIG_440A)
+	printk("Machine check in kernel mode.\n");
+	if (reason & ESR_IMCP){
+		printk("Instruction Synchronous Machine Check exception\n");
+		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
+	}
+	else {
+		u32 mcsr = mfspr(SPRN_MCSR);
+		if (mcsr & MCSR_IB)
+			printk("Instruction Read PLB Error\n");
+		if (mcsr & MCSR_DRB)
+			printk("Data Read PLB Error\n");
+		if (mcsr & MCSR_DWB)
+			printk("Data Write PLB Error\n");
+		if (mcsr & MCSR_TLBP)
+			printk("TLB Parity Error\n");
+		if (mcsr & MCSR_ICP){
+			flush_instruction_cache();
+			printk("I-Cache Parity Error\n");
+		}	
+		if (mcsr & MCSR_DCSP)
+			printk("D-Cache Search Parity Error\n");
+		if (mcsr & MCSR_DCFP)
+			printk("D-Cache Flush Parity Error\n");
+		if (mcsr & MCSR_IMPE)
+			printk("Machine Check exception is imprecise\n");
+		
+		/* Clear MCSR */
+		mtspr(SPRN_MCSR, mcsr);
+	}
+#else /* !CONFIG_4xx && !CONFIG_E500 */
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from SRR1=%lx): ", reason);
 	switch (reason & 0x601F0000) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/lib/string.S linux-2.4.26-rc3/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-rc3/arch/ppc/lib/string.S	2004-04-12 19:03:21.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-rc3/arch/ppc/platforms/Makefile
--- linux-2.4.25/arch/ppc/platforms/Makefile	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/platforms/Makefile	2004-04-12 19:05:16.965415320 +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/ebony.c linux-2.4.26-rc3/arch/ppc/platforms/ebony.c
--- linux-2.4.25/arch/ppc/platforms/ebony.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/platforms/ebony.c	2004-04-12 19:01:09.000000000 +0000
@@ -234,7 +234,7 @@ ebony_setup_pcix(void)
 	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
-	PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+	PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
 
 	eieio();
 }
@@ -335,7 +335,7 @@ static void __init
 ebony_setup_arch(void)
 {
 	unsigned char * vpd_base;
-	struct ibm440gp_clocks clocks;
+	struct ibm44x_clocks clocks;
 	bd_t *bip = (bd_t *) __res;
 
 #if !defined(CONFIG_BDI_SWITCH)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ep405.c linux-2.4.26-rc3/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-rc3/arch/ppc/platforms/ep405.c	2004-04-12 19:01:17.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-rc3/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-rc3/arch/ppc/platforms/ep405.h	2004-04-12 19:03:44.406486416 +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-rc3/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-rc3/arch/ppc/platforms/est8260.h	2004-04-12 19:03:57.073560728 +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-rc3/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-rc3/arch/ppc/platforms/ibmstb4.c	2004-04-12 19:02:36.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-rc3/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-rc3/arch/ppc/platforms/ibmstb4.h	2004-04-12 19:03:00.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-rc3/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-rc3/arch/ppc/platforms/ibmstbx25.c	2004-04-12 19:05:13.304971792 +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-rc3/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-rc3/arch/ppc/platforms/ibmstbx25.h	2004-04-12 19:00:05.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/ocotea.c linux-2.4.26-rc3/arch/ppc/platforms/ocotea.c
--- linux-2.4.25/arch/ppc/platforms/ocotea.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/platforms/ocotea.c	2004-04-12 19:01:27.000000000 +0000
@@ -44,6 +44,8 @@
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
 
+#include <kernel/ibm440gx_common.h>
+
 extern void abort(void);
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
@@ -79,11 +81,13 @@ ocotea_calibrate_decr(void)
 static int
 ocotea_show_cpuinfo(struct seq_file *m)
 {
+	ibm440gx_show_cpuinfo(m);
 	seq_printf(m, "vendor\t\t: IBM\n");
 	seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n");
 
 	return 0;
 }
+
 static inline int
 ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
@@ -147,7 +151,7 @@ ocotea_setup_pcix(void)
 	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
-	PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+	PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
 
 	eieio();
 }
@@ -205,14 +209,14 @@ ocotea_setup_hose(void)
 TODC_ALLOC();
 
 static void __init
-ocotea_early_serial_map(void)
+ocotea_early_serial_map(const struct ibm44x_clocks* clks)
 {
 	struct serial_struct serial_req;
 
 	/* Setup ioremapped serial port access */
 	memset(&serial_req, 0, sizeof(serial_req));
 	serial_req.line = 0;
-	serial_req.baud_base = BASE_BAUD;
+	serial_req.baud_base = clks->uart0 / 16;
 	serial_req.port = 0;
 	serial_req.irq = 0;
 	serial_req.flags = ASYNC_BOOT_AUTOCONF;
@@ -231,6 +235,7 @@ ocotea_early_serial_map(void)
 
 	/* Assume early_serial_setup() doesn't modify serial_req */
 	serial_req.line = 1;
+	serial_req.baud_base = clks->uart1 / 16;
 	serial_req.port = 1;
 	serial_req.irq = 1; 
 	serial_req.iomem_base = ioremap64(PPC440GX_UART1_ADDR, 8);
@@ -251,6 +256,7 @@ ocotea_setup_arch(void)
 	unsigned char *addr;
 	unsigned long long mac64;
 	bd_t *bip = (bd_t *) __res;
+	struct ibm44x_clocks clocks;
 
 	/* Retrieve MAC addresses from flash */
 	addr = ioremap64(OCOTEA_MAC_BASE, OCOTEA_MAC_SIZE);
@@ -271,7 +277,18 @@ ocotea_setup_arch(void)
 	 */
         mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
 #endif
-
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+	bip->bi_opb_busfreq = clocks.opb;
+	
+	/* Use IIC in standard (100 kHz) mode */
+	bip->bi_iic_fast[0] = bip->bi_iic_fast[1] = 0;
+	
 	/* Setup TODC access */
 	TODC_INIT(TODC_TYPE_DS1743,
 			0,
@@ -300,7 +317,7 @@ ocotea_setup_arch(void)
 	conswitchp = &dummy_con;
 #endif
 
-	ocotea_early_serial_map();
+	ocotea_early_serial_map(&clocks);
 
 	/* Identify the system */
 	printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
@@ -405,6 +422,9 @@ void __init platform_init(unsigned long 
 {
 	parse_bootinfo(find_bootinfo());
 
+	/* Disable L2-Cache due to hardware issues */
+	ibm440gx_l2c_disable();
+
 	ppc_md.setup_arch = ocotea_setup_arch;
 	ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
 	ppc_md.init_IRQ = ocotea_init_irq;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/ocotea.h linux-2.4.26-rc3/arch/ppc/platforms/ocotea.h
--- linux-2.4.25/arch/ppc/platforms/ocotea.h	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc/platforms/ocotea.h	2004-04-12 19:01:01.000000000 +0000
@@ -25,7 +25,7 @@
 #define PPC44x_EMAC0_MR0	0xE0000800
 
 /* Location of MAC addresses in firmware */
-#define OCOTEA_MAC_BASE		(OCOTEA_SMALL_FLASH_HIGH+0xc0500)
+#define OCOTEA_MAC_BASE		(OCOTEA_SMALL_FLASH_HIGH+0xb0500)
 #define OCOTEA_MAC_SIZE		0x200
 #define OCOTEA_MAC1_OFFSET	0x100
 
@@ -55,6 +55,9 @@
 #define UART0_IO_BASE	(u8 *) 0xE0000200
 #define UART1_IO_BASE	(u8 *) 0xE0000300
 
+/* This value is used only to fill something in STD_UART_OP definition,
+   actual value is determined in ocotea_early_serial_map.   --ebs
+*/
 #define BASE_BAUD	11059200/16
 #define STD_UART_OP(num)					\
 	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ppc/platforms/pq2ads.h linux-2.4.26-rc3/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-rc3/arch/ppc/platforms/pq2ads.h	2004-04-12 19:00:46.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-rc3/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-rc3/arch/ppc/platforms/redwood5.c	2004-04-12 19:01:16.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-rc3/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-rc3/arch/ppc/platforms/redwood5.h	2004-04-12 19:00:25.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-rc3/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-rc3/arch/ppc/platforms/redwood6.c	2004-04-12 19:00:41.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-rc3/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-rc3/arch/ppc/platforms/redwood6.h	2004-04-12 19:00:41.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-rc3/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-rc3/arch/ppc/platforms/rpx8260.h	2004-04-12 19:00:06.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/ppc64/kernel/lparcfg.c linux-2.4.26-rc3/arch/ppc64/kernel/lparcfg.c
--- linux-2.4.25/arch/ppc64/kernel/lparcfg.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.26-rc3/arch/ppc64/kernel/lparcfg.c	2004-04-12 19:01:17.000000000 +0000
@@ -326,7 +326,7 @@ static int lparcfg_data(unsigned char *b
 		system_potential_processors =  get_splpar_potential_characteristics();
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_active_processors=%d\n",
-			      (h_resource >> 2*8) && 0xffff);
+			      (h_resource >> 2*8) & 0xffff);
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_potential_processors=%d\n",
 			      system_potential_processors);
@@ -366,16 +366,16 @@ static int lparcfg_data(unsigned char *b
 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "pool=%d\n", (h_aggregation >> 0*8)&&0xffff);
+			      "pool=%d\n", (h_aggregation >> 0*8)&0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "pool_capacity=%d\n", (h_resource >> 3*8) &&0xffff);
+			      "pool_capacity=%d\n", (h_resource >> 3*8) &0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "group=%d\n", (h_aggregation >> 2*8)&&0xffff);
+			      "group=%d\n", (h_aggregation >> 2*8)&0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "capped=%d\n", (h_resource >> 6*8)&&0x40);
+			      "capped=%d\n", (h_resource >> 6*8)&0x40);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/sparc/defconfig linux-2.4.26-rc3/arch/sparc/defconfig
--- linux-2.4.25/arch/sparc/defconfig	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/arch/sparc/defconfig	2004-04-12 19:03:57.110555104 +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-rc3/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-rc3/arch/sparc/kernel/sys_sunos.c	2004-04-12 19:02:22.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-rc3/arch/sparc64/defconfig
--- linux-2.4.25/arch/sparc64/defconfig	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/arch/sparc64/defconfig	2004-04-12 19:02:03.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
@@ -312,11 +314,12 @@ CONFIG_IP6_NF_TARGET_MARK=m
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-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 +354,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 +458,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 +623,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 +745,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
@@ -749,7 +756,7 @@ CONFIG_EFS_FS=m
 # CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 CONFIG_RAMFS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
@@ -763,8 +770,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 +981,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 +1040,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 +1097,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 +1118,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-rc3/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-rc3/arch/sparc64/kernel/sys_sparc32.c	2004-04-12 19:03:29.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-rc3/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-rc3/arch/sparc64/kernel/sys_sunos32.c	2004-04-12 19:03:23.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-rc3/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-rc3/arch/sparc64/mm/modutil.c	2004-04-12 19:02:06.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-rc3/arch/x86_64/Makefile
--- linux-2.4.25/arch/x86_64/Makefile	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/x86_64/Makefile	2004-04-12 19:04:28.658759048 +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=nocona,)
+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-rc3/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-rc3/arch/x86_64/boot/setup.S	2004-04-12 19:03:46.211212056 +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-rc3/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-rc3/arch/x86_64/config.in	2004-04-12 19:03:47.654992568 +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-rc3/arch/x86_64/defconfig
--- linux-2.4.25/arch/x86_64/defconfig	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/arch/x86_64/defconfig	2004-04-12 19:02:45.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-rc3/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-rc3/arch/x86_64/ia32/ia32_ioctl.c	2004-04-12 19:04:26.655063656 +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-rc3/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-rc3/arch/x86_64/ia32/ptrace32.c	2004-04-12 19:04:42.020727720 +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-rc3/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-rc3/arch/x86_64/ia32/sys_ia32.c	2004-04-12 19:04:30.954410056 +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-rc3/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-rc3/arch/x86_64/kernel/Makefile	2004-04-12 19:01:10.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-rc3/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-rc3/arch/x86_64/kernel/acpi.c	2004-04-12 19:04:52.251172456 +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,59 @@ acpi_parse_ioapic (
 	return 0;
 }
 
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+{
+	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_config_acpi_legacy_irqs() already setup IRQs < 16
+	 * If GSI is < 16, this will update its flags,
+	 * else it will create a new mp_irqs[] entry.
+	 */
+	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+
+	/*
+	 * stash over-ride to indicate we've been here
+	 * and for later update of acpi_fadt
+	 */
+	acpi_sci_override_gsi = gsi;
+	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 +295,12 @@ acpi_parse_int_src_ovr (
 
 	acpi_table_print_madt_entry(header);
 
+	if (intsrc->bus_irq == acpi_fadt.sci_int) {
+		acpi_sci_ioapic_setup(intsrc->global_irq,
+			intsrc->flags.polarity, intsrc->flags.trigger);
+		return 0;
+	}
+
 	mp_override_legacy_irq (
 		intsrc->bus_irq,
 		intsrc->flags.polarity,
@@ -292,13 +354,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 +367,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 +453,7 @@ acpi_boot_init (void)
 	 */
 	result = acpi_table_init();
 	if (result) {
-		acpi_disabled = 1;
+		disable_acpi();
 		return result;
 	}
 
@@ -535,6 +576,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 +586,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_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
+
 	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 +618,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-rc3/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-rc3/arch/x86_64/kernel/aperture.c	2004-04-12 19:04:47.174944160 +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-rc3/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-rc3/arch/x86_64/kernel/e820.c	2004-04-12 19:02:06.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-rc3/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-rc3/arch/x86_64/kernel/head.S	2004-04-12 19:03:23.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/io_apic.c linux-2.4.26-rc3/arch/x86_64/kernel/io_apic.c
--- linux-2.4.25/arch/x86_64/kernel/io_apic.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/arch/x86_64/kernel/io_apic.c	2004-04-12 19:04:33.322050120 +0000
@@ -1850,7 +1850,11 @@ int io_apic_set_pci_routing (int ioapic,
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
 
-	add_pin_to_irq(irq, ioapic, pin);
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= 16)
+		add_pin_to_irq(irq, ioapic, pin);
 
 	entry.vector = assign_irq_vector(irq);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/kernel/mpparse.c linux-2.4.26-rc3/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-rc3/arch/x86_64/kernel/mpparse.c	2004-04-12 19:01:53.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-rc3/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-rc3/arch/x86_64/kernel/mtrr.c	2004-04-12 19:00:40.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-rc3/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-rc3/arch/x86_64/kernel/nmi.c	2004-04-12 19:01:40.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-rc3/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-rc3/arch/x86_64/kernel/pci-gart.c	2004-04-12 19:00:33.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-rc3/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-rc3/arch/x86_64/kernel/pci-pc.c	2004-04-12 19:03:35.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-rc3/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-rc3/arch/x86_64/kernel/process.c	2004-04-12 19:02:16.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-rc3/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-rc3/arch/x86_64/kernel/setup.c	2004-04-12 19:01:19.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-rc3/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-rc3/arch/x86_64/kernel/setup64.c	2004-04-12 19:04:47.180943248 +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-rc3/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-rc3/arch/x86_64/kernel/smpboot.c	2004-04-12 19:04:13.765023240 +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-rc3/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-rc3/arch/x86_64/kernel/swiotlb.c	2004-04-12 19:02:35.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-rc3/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-rc3/arch/x86_64/kernel/traps.c	2004-04-12 19:03:48.809817008 +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-rc3/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-rc3/arch/x86_64/kernel/x8664_ksyms.c	2004-04-12 19:03:26.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-rc3/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-rc3/arch/x86_64/lib/copy_page.S	2004-04-12 19:00:02.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-rc3/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-rc3/arch/x86_64/lib/copy_user.S	2004-04-12 19:02:20.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-rc3/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-rc3/arch/x86_64/lib/csum-copy.S	2004-04-12 19:03:58.107403560 +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-rc3/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-rc3/arch/x86_64/lib/csum-partial.c	2004-04-12 19:04:38.795218072 +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-rc3/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-rc3/arch/x86_64/lib/usercopy.c	2004-04-12 19:03:14.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-rc3/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-rc3/arch/x86_64/mm/fault.c	2004-04-12 19:05:03.264498176 +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/k8topology.c linux-2.4.26-rc3/arch/x86_64/mm/k8topology.c
--- linux-2.4.25/arch/x86_64/mm/k8topology.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/arch/x86_64/mm/k8topology.c	2004-04-12 19:04:01.685859552 +0000
@@ -197,7 +197,7 @@ int __init k8_scan_nodes(unsigned long s
 			continue;		
 		if ((nodes_present >> rr) == 0) 
 			rr = 0; 
-		rr = ffz(~nodes_present >> rr); 
+		rr += ffz(~nodes_present >> rr); 
 		PLAT_NODE_DATA(i) = PLAT_NODE_DATA(rr); 
 		rr++; 
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/x86_64/mm/pageattr.c linux-2.4.26-rc3/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-rc3/arch/x86_64/mm/pageattr.c	2004-04-12 19:01:17.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-rc3/crypto/Config.in
--- linux-2.4.25/crypto/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/crypto/Config.in	2004-04-12 19:04:35.880661152 +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-rc3/crypto/Makefile
--- linux-2.4.25/crypto/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/crypto/Makefile	2004-04-12 19:01:33.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-rc3/crypto/arc4.c
--- linux-2.4.25/crypto/arc4.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/crypto/arc4.c	2004-04-12 19:02:55.000000000 +0000
@@ -0,0 +1,103 @@
+/* 
+ * 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;
+	}
+
+	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-rc3/crypto/cipher.c
--- linux-2.4.25/crypto/cipher.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/crypto/cipher.c	2004-04-12 19:03:36.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-rc3/crypto/internal.h
--- linux-2.4.25/crypto/internal.h	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.26-rc3/crypto/internal.h	2004-04-12 19:02:55.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-rc3/crypto/scatterwalk.c
--- linux-2.4.25/crypto/scatterwalk.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/crypto/scatterwalk.c	2004-04-12 19:00:06.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-rc3/crypto/scatterwalk.h
--- linux-2.4.25/crypto/scatterwalk.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/crypto/scatterwalk.h	2004-04-12 19:02:45.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-rc3/crypto/tcrypt.c
--- linux-2.4.25/crypto/tcrypt.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/crypto/tcrypt.c	2004-04-12 19:03:30.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-rc3/crypto/tcrypt.h
--- linux-2.4.25/crypto/tcrypt.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/crypto/tcrypt.h	2004-04-12 19:04:56.613509280 +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-rc3/drivers/acpi/Config.in
--- linux-2.4.25/drivers/acpi/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/Config.in	2004-04-12 19:04:30.987405040 +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-rc3/drivers/acpi/bus.c
--- linux-2.4.25/drivers/acpi/bus.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/bus.c	2004-04-12 19:03:12.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,23 @@ 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;
+
+		/* compatible (0) means level (3) */
+		if (acpi_sci_flags.trigger == 0)
+			acpi_sci_flags.trigger = 3;
+
+		/* 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 +2058,7 @@ acpi_init (void)
 
 	result = acpi_bus_init();
 	if (result) {
-		acpi_disabled = 1;
+		disable_acpi();
 		return_VALUE(result);
 	}
 
@@ -2074,19 +2084,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-rc3/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-rc3/drivers/acpi/dispatcher/dsmethod.c	2004-04-12 19:02:49.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-rc3/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-rc3/drivers/acpi/dispatcher/dsmthdat.c	2004-04-12 19:02:11.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-rc3/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-rc3/drivers/acpi/dispatcher/dsobject.c	2004-04-12 19:00:19.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-rc3/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-rc3/drivers/acpi/dispatcher/dsopcode.c	2004-04-12 19:04:22.704664208 +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-rc3/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-rc3/drivers/acpi/dispatcher/dsutils.c	2004-04-12 19:02:45.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-rc3/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-rc3/drivers/acpi/dispatcher/dswstate.c	2004-04-12 19:04:30.976406712 +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/ec.c linux-2.4.26-rc3/drivers/acpi/ec.c
--- linux-2.4.25/drivers/acpi/ec.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/ec.c	2004-04-12 19:01:32.000000000 +0000
@@ -715,7 +715,7 @@ acpi_ec_start (
 	 * Install GPE handler
 	 */
 	status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
-		ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
+		ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
 	if (ACPI_FAILURE(status)) {
 		return_VALUE(-ENODEV);
 	}
@@ -799,7 +799,7 @@ acpi_ec_ecdt_probe (void)
 	 * Install GPE handler
 	 */
 	status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
-		ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
+		ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
 		ec_ecdt);
 	if (ACPI_FAILURE(status)) {
 		goto error;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/events/evgpe.c linux-2.4.26-rc3/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-rc3/drivers/acpi/events/evgpe.c	2004-04-12 19:03:46.000000000 +0000
@@ -99,9 +99,8 @@ acpi_ev_get_gpe_event_info (
 		return (NULL);
 	}
 
-	/*
-	 * A Non-null gpe_device means this is a GPE Block Device.
-	 */
+	/* A Non-NULL gpe_device means this is a GPE Block Device */
+
 	obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
 	if (!obj_desc ||
 		!obj_desc->device.gpe_block) {
@@ -149,6 +148,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 */
 
@@ -292,7 +296,7 @@ acpi_ev_asynch_execute_gpe_method (
 		}
 	}
 
-	if (local_gpe_event_info.flags & ACPI_EVENT_LEVEL_TRIGGERED) {
+	if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
 		/*
 		 * GPE is level-triggered, we clear the GPE status bit after handling
 		 * the event.
@@ -341,7 +345,7 @@ acpi_ev_gpe_dispatch (
 	 * If edge-triggered, clear the GPE status bit now.  Note that
 	 * level-triggered events are cleared after the GPE is serviced.
 	 */
-	if (gpe_event_info->flags & ACPI_EVENT_EDGE_TRIGGERED) {
+	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) {
 		status = acpi_hw_clear_gpe (gpe_event_info);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
@@ -364,7 +368,7 @@ acpi_ev_gpe_dispatch (
 
 		/* It is now safe to clear level-triggered events. */
 
-		if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) {
+		if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
 			status = acpi_hw_clear_gpe (gpe_event_info);
 			if (ACPI_FAILURE (status)) {
 				ACPI_REPORT_ERROR ((
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/events/evgpeblk.c linux-2.4.26-rc3/drivers/acpi/events/evgpeblk.c
--- linux-2.4.25/drivers/acpi/events/evgpeblk.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/events/evgpeblk.c	2004-04-12 19:01:09.000000000 +0000
@@ -168,11 +168,11 @@ unlock_and_exit:
  *              information for quick lookup during GPE dispatch
  *
  *              The name of each GPE control method is of the form:
- *                  "_Lnn" or "_Enn"
- *                  Where:
- *                      L      - means that the GPE is level triggered
- *                      E      - means that the GPE is edge triggered
- *                      nn     - is the GPE number [in HEX]
+ *              "_Lxx" or "_Exx"
+ *              Where:
+ *                  L      - means that the GPE is level triggered
+ *                  E      - means that the GPE is edge triggered
+ *                  xx     - is the GPE number [in HEX]
  *
  ******************************************************************************/
 
@@ -188,36 +188,41 @@ acpi_ev_save_method_info (
 	u32                             gpe_number;
 	char                            name[ACPI_NAME_SIZE + 1];
 	u8                              type;
-	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("ev_save_method_info");
 
 
-	/* Extract the name from the object and convert to a string */
-
+	/*
+	 * _Lxx and _Exx GPE method support
+	 *
+	 * 1) Extract the name from the object and convert to a string
+	 */
 	ACPI_MOVE_32_TO_32 (name,
 			   &((struct acpi_namespace_node *) obj_handle)->name.integer);
 	name[ACPI_NAME_SIZE] = 0;
 
 	/*
-	 * Edge/Level determination is based on the 2nd character
-	 * of the method name
+	 * 2) Edge/Level determination is based on the 2nd character
+	 *    of the method name
+	 *
+	 * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE if a
+	 * _PRW object is found that points to this GPE.
 	 */
 	switch (name[1]) {
 	case 'L':
-		type = ACPI_EVENT_LEVEL_TRIGGERED;
+		type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
 		break;
 
 	case 'E':
-		type = ACPI_EVENT_EDGE_TRIGGERED;
+		type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
 		break;
 
 	default:
 		/* Unknown method type, just ignore it! */
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
+			"Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
 			name));
 		return_ACPI_STATUS (AE_OK);
 	}
@@ -229,7 +234,7 @@ acpi_ev_save_method_info (
 		/* Conversion failed; invalid method, just ignore it */
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Could not extract GPE number from name: %s (name is not of form _Lnn or _Enn)\n",
+			"Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
 			name));
 		return_ACPI_STATUS (AE_OK);
 	}
@@ -255,13 +260,6 @@ acpi_ev_save_method_info (
 	gpe_event_info->flags    = type;
 	gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
 
-	/* Enable the GPE (SCIs should be disabled at this point) */
-
-	status = acpi_hw_enable_gpe (gpe_event_info);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
-
 	ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
 		"Registered GPE method %s as GPE number 0x%.2X\n",
 		name, gpe_number));
@@ -271,6 +269,122 @@ acpi_ev_save_method_info (
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ev_get_gpe_type
+ *
+ * PARAMETERS:  Callback from walk_namespace
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
+ *              Device.  Run the _PRW method.  If present, extract the GPE
+ *              number and mark the GPE as a WAKE GPE.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ev_get_gpe_type (
+	acpi_handle                     obj_handle,
+	u32                             level,
+	void                            *info,
+	void                            **return_value)
+{
+	struct acpi_gpe_walk_info       *gpe_info = (void *) info;
+	struct acpi_namespace_node      *gpe_device;
+	struct acpi_gpe_block_info      *gpe_block;
+	struct acpi_namespace_node      *target_gpe_device;
+	struct acpi_gpe_event_info      *gpe_event_info;
+	union acpi_operand_object       *pkg_desc;
+	union acpi_operand_object       *obj_desc;
+	u32                             gpe_number;
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_get_gpe_type");
+
+
+	/* Check for a _PRW method under this device */
+
+	status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
+			 ACPI_BTYPE_PACKAGE, &pkg_desc);
+	if (status == AE_NOT_FOUND) {
+		return_ACPI_STATUS (AE_OK);
+	}
+	else if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/* The returned _PRW package must have at least two elements */
+
+	if (pkg_desc->package.count < 2) {
+		goto cleanup;
+	}
+
+	/* Extract pointers from the input context */
+
+	gpe_device = gpe_info->gpe_device;
+	gpe_block = gpe_info->gpe_block;
+
+	/*
+	 * The _PRW object must return a package, we are only interested
+	 * in the first element
+	 */
+	obj_desc = pkg_desc->package.elements[0];
+
+	if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+		/* Use FADT-defined GPE device (from definition of _PRW) */
+
+		target_gpe_device = acpi_gbl_fadt_gpe_device;
+
+		/* Integer is the GPE number in the FADT described GPE blocks */
+
+		gpe_number = (u32) obj_desc->integer.value;
+	}
+	else if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
+		/* Package contains a GPE reference and GPE number within a GPE block */
+
+		if ((obj_desc->package.count < 2) ||
+			(ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) ||
+			(ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+			goto cleanup;
+		}
+
+		/* Get GPE block reference and decode */
+
+		target_gpe_device = obj_desc->package.elements[0]->reference.node;
+		gpe_number = (u32) obj_desc->package.elements[1]->integer.value;
+	}
+	else {
+		/* Unknown type, just ignore it */
+
+		goto cleanup;
+	}
+
+	/*
+	 * Is this GPE within this block?
+	 *
+	 * TRUE iff these conditions are true:
+	 *     1) The GPE devices match.
+	 *     2) The GPE index(number) is within the range of the Gpe Block
+	 *          associated with the GPE device.
+	 */
+	if ((gpe_device == target_gpe_device) &&
+		(gpe_number >= gpe_block->block_base_number) &&
+		(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
+		/* Mark GPE for WAKE but DISABLED (even for wake) */
+
+		gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
+		gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE;
+	}
+
+cleanup:
+	acpi_ut_remove_reference (pkg_desc);
+
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ev_get_gpe_xrupt_block
  *
  * PARAMETERS:  interrupt_level     - Interrupt for a GPE block
@@ -695,8 +809,13 @@ acpi_ev_create_gpe_block (
 	struct acpi_gpe_block_info      **return_gpe_block)
 {
 	struct acpi_gpe_block_info      *gpe_block;
+	struct acpi_gpe_event_info      *gpe_event_info;
+	acpi_native_uint                i;
+	acpi_native_uint                j;
+	u32                             wake_gpe_count;
+	u32                             gpe_enabled_count;
 	acpi_status                     status;
-
+	struct acpi_gpe_walk_info       gpe_info;
 
 	ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
 
@@ -737,7 +856,8 @@ acpi_ev_create_gpe_block (
 
 	/* Dump info about this GPE block */
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+		"GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
 		gpe_block->block_base_number,
 		(u32) (gpe_block->block_base_number +
 				((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
@@ -752,6 +872,58 @@ acpi_ev_create_gpe_block (
 			  ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
 			  gpe_block, NULL);
 
+	/*
+	 * Runtime option: Should Wake GPEs be enabled at runtime?  The default is
+	 * No,they should only be enabled just as the machine goes to sleep.
+	 */
+	if (acpi_gbl_leave_wake_gpes_disabled) {
+		/*
+		 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. (Each
+		 * GPE that has one or more _PRWs that reference it is by definition a
+		 * WAKE GPE and will not be enabled while the machine is running.)
+		 */
+		gpe_info.gpe_block = gpe_block;
+		gpe_info.gpe_device = gpe_device;
+
+		status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				  ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type,
+				  &gpe_info, NULL);
+	}
+
+	/*
+	 * Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have
+	 * a corresponding _Lxx or _Exx method.  All other GPEs must be enabled via
+	 * the acpi_enable_gpe() external interface.
+	 */
+	wake_gpe_count = 0;
+	gpe_enabled_count = 0;
+
+	for (i = 0; i < gpe_block->register_count; i++) {
+		for (j = 0; j < 8; j++) {
+			/* Get the info block for this particular GPE */
+
+			gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+			if ((gpe_event_info->method_node) &&
+			   ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) {
+				/* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */
+
+				status = acpi_hw_enable_gpe (gpe_event_info);
+				if (ACPI_FAILURE (status)) {
+					return_ACPI_STATUS (status);
+				}
+				gpe_enabled_count++;
+			}
+
+			if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) {
+				wake_gpe_count++;
+			}
+		}
+	}
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+			"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
+			wake_gpe_count, gpe_enabled_count));
+
 	/* Return the new block */
 
 	if (return_gpe_block) {
@@ -775,27 +947,25 @@ acpi_ev_create_gpe_block (
  ******************************************************************************/
 
 acpi_status
-acpi_ev_gpe_initialize (void)
+acpi_ev_gpe_initialize (
+	void)
 {
 	u32                             register_count0 = 0;
 	u32                             register_count1 = 0;
 	u32                             gpe_number_max = 0;
-	acpi_handle                     gpe_device;
 	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
 
 
-	/* Get a handle to the predefined _GPE object */
-
-	status = acpi_get_handle (NULL, "\\_GPE", &gpe_device);
+	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
 	/*
-	 * Initialize the GPE Blocks defined in the FADT
+	 * Initialize the GPE Block(s) defined in the FADT
 	 *
 	 * Why the GPE register block lengths are divided by 2:  From the ACPI Spec,
 	 * section "General-Purpose Event Registers", we have:
@@ -829,8 +999,9 @@ acpi_ev_gpe_initialize (void)
 
 		/* Install GPE Block 0 */
 
-		status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe0_blk,
+		status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe0_blk,
 				 register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
+
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR ((
 				"Could not create GPE Block 0, %s\n",
@@ -861,9 +1032,10 @@ acpi_ev_gpe_initialize (void)
 		else {
 			/* Install GPE Block 1 */
 
-			status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe1_blk,
+			status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe1_blk,
 					 register_count1, acpi_gbl_FADT->gpe1_base,
 					 acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
+
 			if (ACPI_FAILURE (status)) {
 				ACPI_REPORT_ERROR ((
 					"Could not create GPE Block 1, %s\n",
@@ -885,7 +1057,8 @@ acpi_ev_gpe_initialize (void)
 		/* GPEs are not required by ACPI, this is OK */
 
 		ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
-		return_ACPI_STATUS (AE_OK);
+		status = AE_OK;
+		goto cleanup;
 	}
 
 	/* Check for Max GPE number out-of-range */
@@ -893,9 +1066,12 @@ acpi_ev_gpe_initialize (void)
 	if (gpe_number_max > ACPI_GPE_MAX) {
 		ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
 			gpe_number_max));
-		return_ACPI_STATUS (AE_BAD_VALUE);
+		status = AE_BAD_VALUE;
+		goto cleanup;
 	}
 
+cleanup:
+	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 	return_ACPI_STATUS (AE_OK);
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/events/evmisc.c linux-2.4.26-rc3/drivers/acpi/events/evmisc.c
--- linux-2.4.25/drivers/acpi/events/evmisc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/events/evmisc.c	2004-04-12 19:03:17.000000000 +0000
@@ -97,6 +97,20 @@ acpi_ev_is_notify_object (
  *
  ******************************************************************************/
 
+#ifdef ACPI_DEBUG_OUTPUT
+static const char                *acpi_notify_value_names[] =
+{
+	"Bus Check",
+	"Device Check",
+	"Device Wake",
+	"Eject request",
+	"Device Check Light",
+	"Frequency Mismatch",
+	"Bus Mode Mismatch",
+	"Power Fault"
+};
+#endif
+
 acpi_status
 acpi_ev_queue_notify_request (
 	struct acpi_namespace_node      *node,
@@ -112,7 +126,7 @@ acpi_ev_queue_notify_request (
 
 
 	/*
-	 * For value 1 (Ejection Request), some device method may need to be run.
+	 * For value 3 (Ejection Request), some device method may need to be run.
 	 * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
 	 * For value 0x80 (Status Change) on the power button or sleep button,
 	 * initiate soft-off or sleep operation?
@@ -120,26 +134,13 @@ acpi_ev_queue_notify_request (
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 		"Dispatching Notify(%X) on node %p\n", notify_value, node));
 
-	switch (notify_value) {
-	case 0:
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Re-enumerate Devices\n"));
-		break;
-
-	case 1:
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Ejection Request\n"));
-		break;
-
-	case 2:
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Device Wake\n"));
-		break;
-
-	case 0x80:
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Status Change\n"));
-		break;
-
-	default:
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unknown Notify Value: %X \n", notify_value));
-		break;
+	if (notify_value <= 7) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
+				acpi_notify_value_names[notify_value]));
+	}
+	else {
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "notify value: 0x2.2_x **Device Specific**\n",
+				notify_value));
 	}
 
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/events/evxfevnt.c linux-2.4.26-rc3/drivers/acpi/events/evxfevnt.c
--- linux-2.4.25/drivers/acpi/events/evxfevnt.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/events/evxfevnt.c	2004-04-12 19:01:41.000000000 +0000
@@ -247,16 +247,29 @@ acpi_enable_gpe (
 		goto unlock_and_exit;
 	}
 
-	/* Enable the requested GPE number */
-
-	status = acpi_hw_enable_gpe (gpe_event_info);
-	if (ACPI_FAILURE (status)) {
-		goto unlock_and_exit;
-	}
+	/* Check for Wake vs Runtime GPE */
 
 	if (flags & ACPI_EVENT_WAKE_ENABLE) {
+		/* Ensure the requested wake GPE is disabled */
+
+		status = acpi_hw_disable_gpe (gpe_event_info);
+		if (ACPI_FAILURE (status)) {
+			goto unlock_and_exit;
+		}
+
+		/* Defer Enable of Wake GPE until sleep time */
+
 		acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
 	}
+	else {
+		/* Enable the requested runtime GPE  */
+
+		status = acpi_hw_enable_gpe (gpe_event_info);
+		if (ACPI_FAILURE (status)) {
+			goto unlock_and_exit;
+		}
+	}
+
 
 unlock_and_exit:
 	if (flags & ACPI_NOT_ISR) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exconvrt.c linux-2.4.26-rc3/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-rc3/drivers/acpi/executer/exconvrt.c	2004-04-12 19:00:26.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-rc3/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-rc3/drivers/acpi/executer/excreate.c	2004-04-12 19:04:45.063265184 +0000
@@ -84,14 +84,15 @@ acpi_ex_create_alias (
 	alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
 	target_node = (struct acpi_namespace_node *) walk_state->operands[1];
 
-	if (target_node->type == ACPI_TYPE_LOCAL_ALIAS) {
+	if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
+		(target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
 		/*
 		 * Dereference an existing alias so that we don't create a chain
 		 * of aliases.  With this code, we guarantee that an alias is
 		 * always exactly one level of indirection away from the
 		 * actual aliased name.
 		 */
-		target_node = (struct acpi_namespace_node *) target_node->object;
+		target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
 	}
 
 	/*
@@ -117,6 +118,17 @@ acpi_ex_create_alias (
 		alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
 		break;
 
+	case ACPI_TYPE_METHOD:
+
+		/*
+		 * The new alias has the type ALIAS and points to the original
+		 * NS node, not the object itself.  This is because for these
+		 * types, the object can change dynamically via a Store.
+		 */
+		alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
+		alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
+		break;
+
 	default:
 
 		/* Attach the original source object to the new Alias Node */
@@ -587,27 +599,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/exdump.c linux-2.4.26-rc3/drivers/acpi/executer/exdump.c
--- linux-2.4.25/drivers/acpi/executer/exdump.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/executer/exdump.c	2004-04-12 19:00:43.000000000 +0000
@@ -774,6 +774,7 @@ acpi_ex_dump_object_descriptor (
 
 
 	case ACPI_TYPE_LOCAL_ALIAS:
+	case ACPI_TYPE_LOCAL_METHOD_ALIAS:
 	case ACPI_TYPE_LOCAL_EXTRA:
 	case ACPI_TYPE_LOCAL_DATA:
 	default:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exfldio.c linux-2.4.26-rc3/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-rc3/drivers/acpi/executer/exfldio.c	2004-04-12 19:01:55.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-rc3/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-rc3/drivers/acpi/executer/exmisc.c	2004-04-12 19:04:23.635522696 +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-rc3/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-rc3/drivers/acpi/executer/exmutex.c	2004-04-12 19:04:09.883613304 +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-rc3/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-rc3/drivers/acpi/executer/exoparg2.c	2004-04-12 19:02:56.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-rc3/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-rc3/drivers/acpi/executer/exprep.c	2004-04-12 19:01:15.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/exresnte.c linux-2.4.26-rc3/drivers/acpi/executer/exresnte.c
--- linux-2.4.25/drivers/acpi/executer/exresnte.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/executer/exresnte.c	2004-04-12 19:01:27.000000000 +0000
@@ -108,10 +108,11 @@ acpi_ex_resolve_node_to_value (
 	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
 		 node, source_desc, acpi_ut_get_type_name (entry_type)));
 
-	if (entry_type == ACPI_TYPE_LOCAL_ALIAS) {
+	if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
+		(entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
 		/* There is always exactly one level of indirection */
 
-		node       = (struct acpi_namespace_node *) node->object;
+		node       = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
 		source_desc = acpi_ns_get_attached_object (node);
 		entry_type = acpi_ns_get_type ((acpi_handle) node);
 		*object_ptr = node;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exresolv.c linux-2.4.26-rc3/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-rc3/drivers/acpi/executer/exresolv.c	2004-04-12 19:02:16.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-rc3/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-rc3/drivers/acpi/executer/exresop.c	2004-04-12 19:04:33.952954208 +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-rc3/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-rc3/drivers/acpi/executer/exstore.c	2004-04-12 19:02:31.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-rc3/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-rc3/drivers/acpi/executer/exstoren.c	2004-04-12 19:00:49.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
 		 */
@@ -132,11 +138,12 @@ acpi_ex_resolve_object (
 
 
 	case ACPI_TYPE_LOCAL_ALIAS:
+	case ACPI_TYPE_LOCAL_METHOD_ALIAS:
 
 		/*
 		 * 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-rc3/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-rc3/drivers/acpi/hardware/hwgpe.c	2004-04-12 19:00:19.000000000 +0000
@@ -53,9 +53,9 @@
  *
  * FUNCTION:    acpi_hw_enable_gpe
  *
- * PARAMETERS:  gpe_number      - The GPE
+ * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
  *
- * RETURN:      None
+ * RETURN:      Status
  *
  * DESCRIPTION: Enable a single GPE.
  *
@@ -95,7 +95,7 @@ acpi_hw_enable_gpe (
  *
  * FUNCTION:    acpi_hw_enable_gpe_for_wakeup
  *
- * PARAMETERS:  gpe_number      - The GPE
+ * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
  *
  * RETURN:      None
  *
@@ -122,9 +122,11 @@ acpi_hw_enable_gpe_for_wakeup (
 	}
 
 	/*
-	 * Set the bit so we will not disable this when sleeping
+	 * Set the bit so we will not enable this GPE when sleeping (and disable
+	 * it upon wake)
 	 */
 	gpe_register_info->wake_enable |= gpe_event_info->bit_mask;
+	gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED);
 }
 
 
@@ -132,9 +134,9 @@ acpi_hw_enable_gpe_for_wakeup (
  *
  * FUNCTION:    acpi_hw_disable_gpe
  *
- * PARAMETERS:  gpe_number      - The GPE
+ * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
  *
- * RETURN:      None
+ * RETURN:      Status
  *
  * DESCRIPTION: Disable a single GPE.
  *
@@ -177,6 +179,8 @@ acpi_hw_disable_gpe (
 		return (status);
 	}
 
+	/* Make sure this GPE is disabled for wake, also */
+
 	acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
 	return (AE_OK);
 }
@@ -186,7 +190,7 @@ acpi_hw_disable_gpe (
  *
  * FUNCTION:    acpi_hw_disable_gpe_for_wakeup
  *
- * PARAMETERS:  gpe_number      - The GPE
+ * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
  *
  * RETURN:      None
  *
@@ -212,9 +216,8 @@ acpi_hw_disable_gpe_for_wakeup (
 		return;
 	}
 
-	/*
-	 * Clear the bit so we will disable this when sleeping
-	 */
+	/* Clear the bit so we will disable this when sleeping */
+
 	gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask);
 }
 
@@ -223,11 +226,11 @@ acpi_hw_disable_gpe_for_wakeup (
  *
  * FUNCTION:    acpi_hw_clear_gpe
  *
- * PARAMETERS:  gpe_number      - The GPE
+ * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
  *
- * RETURN:      None
+ * RETURN:      status_status
  *
- * DESCRIPTION: Clear a single GPE.
+ * DESCRIPTION: Clear the status bit for a single GPE.
  *
  ******************************************************************************/
 
@@ -256,9 +259,10 @@ acpi_hw_clear_gpe (
  *
  * FUNCTION:    acpi_hw_get_gpe_status
  *
- * PARAMETERS:  gpe_number      - The GPE
+ * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
+ *              event_status        - Where the GPE status is returned
  *
- * RETURN:      None
+ * RETURN:      Status
  *
  * DESCRIPTION: Return the status of a single GPE.
  *
@@ -376,7 +380,7 @@ acpi_hw_disable_gpe_block (
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Clear all GPEs within a GPE block
+ * DESCRIPTION: Clear status bits for all GPEs within a GPE block
  *
  ******************************************************************************/
 
@@ -392,7 +396,7 @@ acpi_hw_clear_gpe_block (
 	/* Examine each GPE Register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
-		/* Clear all GPEs in this register */
+		/* Clear status on all GPEs in this register */
 
 		status = acpi_hw_low_level_write (8, 0xFF,
 				 &gpe_block->register_info[i].status_address);
@@ -407,19 +411,20 @@ acpi_hw_clear_gpe_block (
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_disable_non_wakeup_gpe_block
+ * FUNCTION:    acpi_hw_prepare_gpe_block_for_sleep
  *
  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all GPEs except wakeup GPEs in a GPE block
+ * DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within
+ *              a single GPE block
  *
  ******************************************************************************/
 
 static acpi_status
-acpi_hw_disable_non_wakeup_gpe_block (
+acpi_hw_prepare_gpe_block_for_sleep (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
 	struct acpi_gpe_block_info      *gpe_block)
 {
@@ -437,8 +442,11 @@ acpi_hw_disable_non_wakeup_gpe_block (
 
 	for (i = 0; i < gpe_block->register_count; i++) {
 		/*
-		 * Read the enabled status of all GPEs. We
+		 * Read the enabled/disabled status of all GPEs. We
 		 * will be using it to restore all the GPEs later.
+		 *
+		 * NOTE:  Wake GPEs are are ALL disabled at this time, so when we wake
+		 * and restore this register, they will be automatically disabled.
 		 */
 		status = acpi_hw_low_level_read (8, &in_value,
 				 &gpe_register_info->enable_address);
@@ -449,7 +457,8 @@ acpi_hw_disable_non_wakeup_gpe_block (
 		gpe_register_info->enable = (u8) in_value;
 
 		/*
-		 * Disable all GPEs except wakeup GPEs.
+		 * 1) Disable all runtime GPEs
+		 * 2) Enable all wakeup GPEs
 		 */
 		status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
 				&gpe_register_info->enable_address);
@@ -457,6 +466,8 @@ acpi_hw_disable_non_wakeup_gpe_block (
 			return (status);
 		}
 
+		/* Point to next GPE register */
+
 		gpe_register_info++;
 	}
 
@@ -466,22 +477,22 @@ acpi_hw_disable_non_wakeup_gpe_block (
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_disable_non_wakeup_gpes
+ * FUNCTION:    acpi_hw_prepare_gpes_for_sleep
  *
  * PARAMETERS:  None
  *
- * RETURN:      None
+ * RETURN:      Status
  *
- * DESCRIPTION: Disable all non-wakeup GPEs
+ * DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs.
  *              Called with interrupts disabled. The interrupt handler also
  *              modifies gpe_register_info->Enable, so it should not be
- *              given the chance to run until after non-wake GPEs are
+ *              given the chance to run until after the runtime GPEs are
  *              re-enabled.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_disable_non_wakeup_gpes (
+acpi_hw_prepare_gpes_for_sleep (
 	void)
 {
 	acpi_status                     status;
@@ -490,27 +501,27 @@ acpi_hw_disable_non_wakeup_gpes (
 	ACPI_FUNCTION_ENTRY ();
 
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_disable_non_wakeup_gpe_block);
-
+	status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep);
 	return (status);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_enable_non_wakeup_gpe_block
+ * FUNCTION:    acpi_hw_restore_gpe_block_on_wake
  *
  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable a single GPE.
+ * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one
+ *              GPE block
  *
  ******************************************************************************/
 
 static acpi_status
-acpi_hw_enable_non_wakeup_gpe_block (
+acpi_hw_restore_gpe_block_on_wake (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
 	struct acpi_gpe_block_info      *gpe_block)
 {
@@ -528,9 +539,21 @@ 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.
+		 * Restore the GPE Enable register, which will do the following:
+		 *
+		 * 1) Disable all wakeup GPEs
+		 * 2) Enable all runtime GPEs
+		 *
+		 *  (On sleep, we saved the enabled status of all GPEs)
 		 */
 		status = acpi_hw_low_level_write (8, gpe_register_info->enable,
 				 &gpe_register_info->enable_address);
@@ -538,28 +561,30 @@ acpi_hw_enable_non_wakeup_gpe_block (
 			return (status);
 		}
 
+		/* Point to next GPE register */
+
 		gpe_register_info++;
 	}
 
-
 	return (AE_OK);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_enable_non_wakeup_gpes
+ * FUNCTION:    acpi_hw_restore_gpes_on_wake
  *
  * PARAMETERS:  None
  *
- * RETURN:      None
+ * RETURN:      Status
  *
- * DESCRIPTION: Enable all non-wakeup GPEs we previously enabled.
+ * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all
+ *              GPE blocks
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_enable_non_wakeup_gpes (
+acpi_hw_restore_gpes_on_wake (
 	void)
 {
 	acpi_status                     status;
@@ -568,7 +593,6 @@ acpi_hw_enable_non_wakeup_gpes (
 	ACPI_FUNCTION_ENTRY ();
 
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_enable_non_wakeup_gpe_block);
-
+	status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake);
 	return (status);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/hardware/hwregs.c linux-2.4.26-rc3/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-rc3/drivers/acpi/hardware/hwregs.c	2004-04-12 19:04:24.498391520 +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-rc3/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-rc3/drivers/acpi/hardware/hwsleep.c	2004-04-12 19:00:41.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)));
 	}
@@ -251,7 +286,11 @@ acpi_enter_sleep_state (
 		}
 	}
 
-	status = acpi_hw_disable_non_wakeup_gpes ();
+	/*
+	 * 1) Disable all runtime GPEs
+	 * 2) Enable all wakeup GPEs
+	 */
+	status = acpi_hw_prepare_gpes_for_sleep ();
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -380,7 +419,11 @@ acpi_enter_sleep_state_s4bios (
 		return_ACPI_STATUS (status);
 	}
 
-	status = acpi_hw_disable_non_wakeup_gpes ();
+	/*
+	 * 1) Disable all runtime GPEs
+	 * 2) Enable all wakeup GPEs
+	 */
+	status = acpi_hw_prepare_gpes_for_sleep ();
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -477,32 +520,53 @@ 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)));
 	}
+	/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
 
-	/* _WAK returns stuff - do we want to look at it? */
-
-	status = acpi_hw_enable_non_wakeup_gpes ();
+	/*
+	 * Restore the GPEs:
+	 * 1) Disable all wakeup GPEs
+	 * 2) Enable all runtime GPEs
+	 */
+	status = acpi_hw_restore_gpes_on_wake ();
 	if (ACPI_FAILURE (status)) {
 		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-rc3/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-rc3/drivers/acpi/namespace/nsaccess.c	2004-04-12 19:04:52.232175344 +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);
@@ -233,6 +247,14 @@ acpi_ns_root_initialize (void)
 
 unlock_and_exit:
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+
+	/* Save a handle to "_GPE", it is always present */
+
+	if (ACPI_SUCCESS (status)) {
+		status = acpi_ns_get_node_by_path ("\\_GPE", NULL, ACPI_NS_NO_UPSEARCH,
+				  &acpi_gbl_fadt_gpe_device);
+	}
+
 	return_ACPI_STATUS (status);
 }
 
@@ -314,7 +336,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);
 		}
@@ -563,6 +585,7 @@ acpi_ns_lookup (
 		if ((num_segments       == 0)                               &&
 			(type_to_check_for  != ACPI_TYPE_ANY)                   &&
 			(type_to_check_for  != ACPI_TYPE_LOCAL_ALIAS)           &&
+			(type_to_check_for  != ACPI_TYPE_LOCAL_METHOD_ALIAS)    &&
 			(type_to_check_for  != ACPI_TYPE_LOCAL_SCOPE)           &&
 			(this_node->type    != ACPI_TYPE_ANY)                   &&
 			(this_node->type    != type_to_check_for)) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsalloc.c linux-2.4.26-rc3/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-rc3/drivers/acpi/namespace/nsalloc.c	2004-04-12 19:02:57.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/nsdump.c linux-2.4.26-rc3/drivers/acpi/namespace/nsdump.c
--- linux-2.4.25/drivers/acpi/namespace/nsdump.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/namespace/nsdump.c	2004-04-12 19:04:38.777220808 +0000
@@ -351,6 +351,7 @@ acpi_ns_dump_one_object (
 
 
 		case ACPI_TYPE_LOCAL_ALIAS:
+		case ACPI_TYPE_LOCAL_METHOD_ALIAS:
 
 			acpi_os_printf ("Target %4.4s (%p)\n", acpi_ut_get_node_name (obj_desc), obj_desc);
 			break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nseval.c linux-2.4.26-rc3/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-rc3/drivers/acpi/namespace/nseval.c	2004-04-12 19:02: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 */
@@ -304,6 +311,15 @@ acpi_ns_evaluate_by_handle (
 	}
 
 	/*
+	 * For a method alias, we must grab the actual method node
+	 * so that proper scoping context will be established
+	 * before execution.
+	 */
+	if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+		node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
+	}
+
+	/*
 	 * Two major cases here:
 	 * 1) The object is an actual control method -- execute it.
 	 * 2) The object is not a method -- just return it's current
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nssearch.c linux-2.4.26-rc3/drivers/acpi/namespace/nssearch.c
--- linux-2.4.25/drivers/acpi/namespace/nssearch.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/namespace/nssearch.c	2004-04-12 19:04:52.239174280 +0000
@@ -113,6 +113,12 @@ acpi_ns_search_node (
 		/* Check for match against the name */
 
 		if (next_node->name.integer == target_name) {
+			/* Resolve a control method alias if any */
+
+			if (acpi_ns_get_type (next_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+				next_node = ACPI_CAST_PTR (struct acpi_namespace_node, next_node->object);
+			}
+
 			/*
 			 * Found matching entry.
 			 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsutils.c linux-2.4.26-rc3/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-rc3/drivers/acpi/namespace/nsutils.c	2004-04-12 19:02:53.000000000 +0000
@@ -256,7 +256,7 @@ acpi_ns_get_type (
 
 
 	if (!node) {
-		ACPI_REPORT_WARNING (("ns_get_type: Null Node ptr"));
+		ACPI_REPORT_WARNING (("ns_get_type: Null Node input pointer\n"));
 		return_VALUE (ACPI_TYPE_ANY);
 	}
 
@@ -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/nsxfeval.c linux-2.4.26-rc3/drivers/acpi/namespace/nsxfeval.c
--- linux-2.4.25/drivers/acpi/namespace/nsxfeval.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/namespace/nsxfeval.c	2004-04-12 19:02:00.000000000 +0000
@@ -45,6 +45,7 @@
 
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
+#include <acpi/acinterp.h>
 
 
 #define _COMPONENT          ACPI_NAMESPACE
@@ -149,11 +150,11 @@ acpi_evaluate_object_typed (
  * FUNCTION:    acpi_evaluate_object
  *
  * PARAMETERS:  Handle              - Object handle (optional)
- *              *Pathname           - Object pathname (optional)
- *              **external_params   - List of parameters to pass to method,
+ *              Pathname            - Object pathname (optional)
+ *              external_params     - List of parameters to pass to method,
  *                                    terminated by NULL.  May be NULL
  *                                    if no parameters are being passed.
- *              *return_buffer      - Where to put method's return value (if
+ *              return_buffer       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *
  * RETURN:      Status
@@ -172,6 +173,7 @@ acpi_evaluate_object (
 	struct acpi_buffer              *return_buffer)
 {
 	acpi_status                     status;
+	acpi_status                     status2;
 	union acpi_operand_object       **internal_params = NULL;
 	union acpi_operand_object       *internal_return_obj = NULL;
 	acpi_size                       buffer_space_needed;
@@ -203,7 +205,7 @@ acpi_evaluate_object (
 		 */
 		for (i = 0; i < external_params->count; i++) {
 			status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
-					 &internal_params[i]);
+					  &internal_params[i]);
 			if (ACPI_FAILURE (status)) {
 				acpi_ut_delete_internal_object_list (internal_params);
 				return_ACPI_STATUS (status);
@@ -321,14 +323,20 @@ acpi_evaluate_object (
 		}
 	}
 
-	/* Delete the return and parameter objects */
-
 	if (internal_return_obj) {
 		/*
-		 * Delete the internal return object. (Or at least
-		 * decrement the reference count by one)
+		 * Delete the internal return object.  NOTE: Interpreter
+		 * must be locked to avoid race condition.
 		 */
-		acpi_ut_remove_reference (internal_return_obj);
+		status2 = acpi_ex_enter_interpreter ();
+		if (ACPI_SUCCESS (status2)) {
+			/*
+			 * Delete the internal return object. (Or at least
+			 * decrement the reference count by one)
+			 */
+			acpi_ut_remove_reference (internal_return_obj);
+			acpi_ex_exit_interpreter ();
+		}
 	}
 
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsxfname.c linux-2.4.26-rc3/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-rc3/drivers/acpi/namespace/nsxfname.c	2004-04-12 19:01:27.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-rc3/drivers/acpi/osl.c
--- linux-2.4.25/drivers/acpi/osl.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/osl.c	2004-04-12 19:00:10.000000000 +0000
@@ -1021,3 +1021,60 @@ 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);
+
+/*
+ * Wake and Run-Time GPES are expected to be separate.
+ * We disable wake-GPEs at run-time to prevent spurious
+ * interrupts.
+ *
+ * However, if a system exists that shares Wake and
+ * Run-time events on the same GPE this flag is available
+ * to tell Linux to keep the wake-time GPEs enabled at run-time.
+ */
+int __init
+acpi_wake_gpes_always_on_setup(char *str)
+{
+	printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
+
+	acpi_gbl_leave_wake_gpes_disabled = FALSE;
+
+	return 1;
+}
+
+__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/parser/psargs.c linux-2.4.26-rc3/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-rc3/drivers/acpi/parser/psargs.c	2004-04-12 19:01:47.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-rc3/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-rc3/drivers/acpi/parser/psparse.c	2004-04-12 19:01:06.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-rc3/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-rc3/drivers/acpi/parser/psscope.c	2004-04-12 19:00:32.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-rc3/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-rc3/drivers/acpi/pci_irq.c	2004-04-12 19:05:01.090828624 +0000
@@ -277,7 +277,6 @@ acpi_pci_irq_lookup (
 	return_VALUE(entry->irq);
 }
 
-
 static int
 acpi_pci_irq_derive (
 	struct pci_dev		*dev,
@@ -285,6 +284,7 @@ acpi_pci_irq_derive (
 {
 	struct pci_dev		*bridge = dev;
 	int			irq = 0;
+	u8			bridge_pin = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
 
@@ -293,12 +293,28 @@ acpi_pci_irq_derive (
 
 	/* 
 	 * Attempt to derive an IRQ for this device from a parent bridge's
-	 * PCI interrupt routing entry (a.k.a. the "bridge swizzle").
+	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge)
 	 */
 	while (!irq && bridge->bus->self) {
 		pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
 		bridge = bridge->bus->self;
-		irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin);
+
+		if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
+			/* PC card has the same IRQ as its cardbridge */
+			pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin);
+			if (!bridge_pin) {
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"No interrupt pin configured for device %s\n",
+					pci_name(bridge)));
+				return_VALUE(0);
+			}
+			/* Pin is from 0 to 3 */
+			bridge_pin --;
+			pin = bridge_pin;
+		}
+
+		irq = acpi_pci_irq_lookup(0, bridge->bus->number,
+				PCI_SLOT(bridge->devfn), pin);
 	}
 
 	if (!irq) {
@@ -306,7 +322,8 @@ acpi_pci_irq_derive (
 		return_VALUE(0);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived IRQ %d\n", irq));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
+		irq, pci_name(dev), pci_name(bridge)));
 
 	return_VALUE(irq);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/pci_link.c linux-2.4.26-rc3/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-rc3/drivers/acpi/pci_link.c	2004-04-12 19:05:16.137541176 +0000
@@ -68,6 +68,7 @@ struct acpi_pci_link_irq {
 	u8			edge_level;		/* All IRQs */
 	u8			active_high_low;	/* All IRQs */
 	u8			setonboot;
+	u8			resource_type;
 	u8			possible_count;
 	u8			possible[ACPI_PCI_LINK_MAX_POSSIBLE];
 };
@@ -119,6 +120,7 @@ acpi_pci_link_check_possible (
 		}
 		link->irq.edge_level = p->edge_level;
 		link->irq.active_high_low = p->active_high_low;
+		link->irq.resource_type = ACPI_RSTYPE_IRQ;
 		break;
 	}
 	case ACPI_RSTYPE_EXT_IRQ:
@@ -139,6 +141,7 @@ acpi_pci_link_check_possible (
 		}
 		link->irq.edge_level = p->edge_level;
 		link->irq.active_high_low = p->active_high_low;
+		link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
 		break;
 	}
 	default:
@@ -338,13 +341,18 @@ acpi_pci_link_set (
 		}
 	}
 
+	resource_type = link->irq.resource_type;
+
+	if (resource_type != ACPI_RSTYPE_IRQ &&
+			resource_type != ACPI_RSTYPE_EXT_IRQ){
 	/* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
 	 * an extended one */
-	if (irq <= 15) {
-		resource_type = ACPI_RSTYPE_IRQ;
-	} else {
-		resource_type = ACPI_RSTYPE_EXT_IRQ;
-	}
+		if (irq <= 15) {
+			resource_type = ACPI_RSTYPE_IRQ;
+		} else {
+			resource_type = ACPI_RSTYPE_EXT_IRQ;
+		}
+	} 
 
 retry_programming:
    
@@ -767,7 +775,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 +782,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-rc3/drivers/acpi/processor.c
--- linux-2.4.25/drivers/acpi/processor.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/processor.c	2004-04-12 19:02:55.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/rsaddr.c linux-2.4.26-rc3/drivers/acpi/resources/rsaddr.c
--- linux-2.4.25/drivers/acpi/resources/rsaddr.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/resources/rsaddr.c	2004-04-12 19:00:04.000000000 +0000
@@ -88,6 +88,7 @@ acpi_rs_address16_resource (
 
 	ACPI_FUNCTION_TRACE ("rs_address16_resource");
 
+
 	/*
 	 * Point past the Descriptor to get the number of bytes consumed
 	 */
@@ -149,7 +150,7 @@ acpi_rs_address16_resource (
 		output_struct->data.address16.attribute.memory.read_write_attribute =
 				(u16) (temp8 & 0x01);
 		output_struct->data.address16.attribute.memory.cache_attribute =
-				(u16) ((temp8 >> 1) & 0x0F);
+				(u16) ((temp8 >> 1) & 0x03);
 	}
 	else {
 		if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) {
@@ -347,7 +348,7 @@ acpi_rs_address16_stream (
 
 		temp8 |=
 			(linked_list->data.address16.attribute.memory.cache_attribute &
-			 0x0F) << 1;
+			 0x03) << 1;
 	}
 	else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
 		temp8 = (u8)
@@ -539,7 +540,7 @@ acpi_rs_address32_resource (
 				(u16) (temp8 & 0x01);
 
 		output_struct->data.address32.attribute.memory.cache_attribute =
-				(u16) ((temp8 >> 1) & 0x0F);
+				(u16) ((temp8 >> 1) & 0x03);
 	}
 	else {
 		if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
@@ -735,7 +736,7 @@ acpi_rs_address32_stream (
 
 		temp8 |=
 			(linked_list->data.address32.attribute.memory.cache_attribute &
-			 0x0F) << 1;
+			 0x03) << 1;
 	}
 	else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
 		temp8 = (u8)
@@ -926,7 +927,7 @@ acpi_rs_address64_resource (
 				(u16) (temp8 & 0x01);
 
 		output_struct->data.address64.attribute.memory.cache_attribute =
-				(u16) ((temp8 >> 1) & 0x0F);
+				(u16) ((temp8 >> 1) & 0x03);
 	}
 	else {
 		if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
@@ -1124,7 +1125,7 @@ acpi_rs_address64_stream (
 
 		temp8 |=
 			(linked_list->data.address64.attribute.memory.cache_attribute &
-			 0x0F) << 1;
+			 0x03) << 1;
 	}
 	else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
 		temp8 = (u8)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/resources/rsxface.c linux-2.4.26-rc3/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-rc3/drivers/acpi/resources/rsxface.c	2004-04-12 19:00:56.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-rc3/drivers/acpi/system.c
--- linux-2.4.25/drivers/acpi/system.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/system.c	2004-04-12 19:02:20.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-rc3/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-rc3/drivers/acpi/toshiba_acpi.c	2004-04-12 19:00:48.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-rc3/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-rc3/drivers/acpi/utilities/uteval.c	2004-04-12 19:00:39.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-rc3/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-rc3/drivers/acpi/utilities/utglobal.c	2004-04-12 19:00:49.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              */
@@ -244,14 +253,15 @@ const u8                                
 	ACPI_NS_NORMAL,                     /* 19 index_field      */
 	ACPI_NS_NORMAL,                     /* 20 Reference        */
 	ACPI_NS_NORMAL,                     /* 21 Alias            */
-	ACPI_NS_NORMAL,                     /* 22 Notify           */
-	ACPI_NS_NORMAL,                     /* 23 Address Handler  */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 24 Resource Desc    */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 25 Resource Field   */
-	ACPI_NS_NEWSCOPE,                   /* 26 Scope            */
-	ACPI_NS_NORMAL,                     /* 27 Extra            */
-	ACPI_NS_NORMAL,                     /* 28 Data             */
-	ACPI_NS_NORMAL                      /* 29 Invalid          */
+	ACPI_NS_NORMAL,                     /* 22 method_alias     */
+	ACPI_NS_NORMAL,                     /* 23 Notify           */
+	ACPI_NS_NORMAL,                     /* 24 Address Handler  */
+	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 25 Resource Desc    */
+	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 26 Resource Field   */
+	ACPI_NS_NEWSCOPE,                   /* 27 Scope            */
+	ACPI_NS_NORMAL,                     /* 28 Extra            */
+	ACPI_NS_NORMAL,                     /* 29 Data             */
+	ACPI_NS_NORMAL                      /* 30 Invalid          */
 };
 
 
@@ -298,10 +308,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 +473,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 */
 
@@ -495,14 +502,15 @@ static const char                   *acp
 	/* 19 */ "index_field",
 	/* 20 */ "Reference",
 	/* 21 */ "Alias",
-	/* 22 */ "Notify",
-	/* 23 */ "addr_handler",
-	/* 24 */ "resource_desc",
-	/* 25 */ "resource_fld",
-	/* 26 */ "Scope",
-	/* 27 */ "Extra",
-	/* 28 */ "Data",
-	/* 39 */ "Invalid"
+	/* 22 */ "method_alias",
+	/* 23 */ "Notify",
+	/* 24 */ "addr_handler",
+	/* 25 */ "resource_desc",
+	/* 26 */ "resource_fld",
+	/* 27 */ "Scope",
+	/* 28 */ "Extra",
+	/* 29 */ "Data",
+	/* 30 */ "Invalid"
 };
 
 
@@ -550,7 +558,7 @@ char *
 acpi_ut_get_node_name (
 	void                            *object)
 {
-	struct acpi_namespace_node      *node;
+	struct acpi_namespace_node      *node = (struct acpi_namespace_node *) object;
 
 
 	if (!object)
@@ -558,7 +566,10 @@ acpi_ut_get_node_name (
 		return ("NULL NODE");
 	}
 
-	node = (struct acpi_namespace_node *) object;
+	if (object == ACPI_ROOT_OBJECT)
+	{
+		node = acpi_gbl_root_node;
+	}
 
 	if (node->descriptor != ACPI_DESC_TYPE_NAMED)
 	{
@@ -772,6 +783,12 @@ acpi_ut_init_globals (
 
 	ACPI_FUNCTION_TRACE ("ut_init_globals");
 
+	/* Runtime configuration */
+
+	acpi_gbl_create_osi_method = TRUE;
+	acpi_gbl_all_methods_serialized = FALSE;
+	acpi_gbl_leave_wake_gpes_disabled = TRUE;
+
 	/* 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/acpi/utilities/utmisc.c linux-2.4.26-rc3/drivers/acpi/utilities/utmisc.c
--- linux-2.4.25/drivers/acpi/utilities/utmisc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/acpi/utilities/utmisc.c	2004-04-12 19:00:40.000000000 +0000
@@ -529,6 +529,7 @@ acpi_ut_strupr (
 	return (src_string);
 }
 
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_mutex_initialize
@@ -562,10 +563,8 @@ acpi_ut_mutex_initialize (
 		}
 	}
 
-
 	status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
-
-	return_ACPI_STATUS (AE_OK);
+	return_ACPI_STATUS (status);
 }
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/atm/nicstar.c linux-2.4.26-rc3/drivers/atm/nicstar.c
--- linux-2.4.25/drivers/atm/nicstar.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/atm/nicstar.c	2004-04-12 19:01:23.000000000 +0000
@@ -112,9 +112,6 @@
 
 /* Macros *********************************************************************/
 
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
 #define CMD_BUSY(card) (readl((card)->membase + STAT) & NS_STAT_CMDBZ)
 
 #define NS_DELAY mdelay(1)
@@ -2472,7 +2469,7 @@ static void dequeue_rx(ns_dev *card, ns_
             for (j = 1; j < NS_SKB(iovb)->iovcnt; j++)
             {
                lb = (struct sk_buff *) iov->iov_base;
-               tocopy = MIN(remaining, iov->iov_len);
+               tocopy = min_t(int, remaining, iov->iov_len);
                memcpy(hb->tail, lb->data, tocopy);
                skb_put(hb, tocopy);
                iov++;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/block/cciss.c linux-2.4.26-rc3/drivers/block/cciss.c
--- linux-2.4.25/drivers/block/cciss.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/block/cciss.c	2004-04-12 19:04:58.211266384 +0000
@@ -508,12 +508,8 @@ static int cciss_ioctl(struct inode *ino
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
 			driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders;
-		} else {
-			driver_geo.heads = 0xff;
-			driver_geo.sectors = 0x3f;
-			driver_geo.cylinders = 
-				hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);
-		}
+		} else 
+			return -ENXIO;
 		driver_geo.start=
 			hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect;
 		if (copy_to_user((void *) arg, &driver_geo,
@@ -528,12 +524,8 @@ static int cciss_ioctl(struct inode *ino
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
 			driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders;
-		} else {
-			driver_geo.heads = 0xff;
-			driver_geo.sectors = 0x3f;
-			driver_geo.cylinders = 
-				hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);
-		}
+		} else 
+			return -ENXIO;
 		driver_geo.start= 
 		hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect;
 		if (copy_to_user((void *) arg, &driver_geo,  
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/block/cciss_scsi.c linux-2.4.26-rc3/drivers/block/cciss_scsi.c
--- linux-2.4.25/drivers/block/cciss_scsi.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.26-rc3/drivers/block/cciss_scsi.c	2004-04-12 19:00:11.000000000 +0000
@@ -589,6 +589,8 @@ cciss_find_non_disk_devices(int cntl_num
 
 	for(i=0; i<num_luns; i++) {
 		/* Execute an inquiry to figure the device type */
+		/* Skip over masked devices */
+		if (ld_buff->LUN[i][3] & 0xC0) continue;
 		memset(inq_buff, 0, sizeof(InquiryData_struct));
 		memcpy(scsi3addr, ld_buff->LUN[i], 8); /* ugly... */
 		return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
@@ -1148,6 +1150,7 @@ cciss_update_non_disk_devices(int cntl_n
 		int devtype;
 
 		/* for each physical lun, do an inquiry */
+		if (ld_buff->LUN[i][3] & 0xC0) continue;
 		memset(inq_buff, 0, sizeof(InquiryData_struct));
 		memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/block/ll_rw_blk.c linux-2.4.26-rc3/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-rc3/drivers/block/ll_rw_blk.c	2004-04-12 19:00:47.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-rc3/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-rc3/drivers/bluetooth/hci_usb.c	2004-04-12 19:04:44.125407760 +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,12 +70,12 @@
 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) },
 
+	/* AVM BlueFRITZ! USB v2.0 */
+	{ USB_DEVICE(0x057c, 0x3800) },
+
 	/* Ericsson with non-standard id */
 	{ USB_DEVICE(0x0bdb, 0x1002) },
 
@@ -90,9 +90,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 +654,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 +802,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 +933,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 +998,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-rc3/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-rc3/drivers/bluetooth/hci_usb.h	2004-04-12 19:03:21.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-rc3/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-rc3/drivers/char/agp/agpgart_be.c	2004-04-12 19:00:59.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/drm/r128_state.c linux-2.4.26-rc3/drivers/char/drm/r128_state.c
--- linux-2.4.25/drivers/char/drm/r128_state.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/char/drm/r128_state.c	2004-04-12 19:01:01.000000000 +0000
@@ -914,7 +914,7 @@ static int r128_cce_dispatch_write_span(
 
 	count = depth->n;
 	
-	if( count > 4096 )
+	if( count > 4096 || count <= 0)
 		return -EMSGSIZE;
 	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
 		return -EFAULT;
@@ -1010,7 +1010,7 @@ static int r128_cce_dispatch_write_pixel
 
 	count = depth->n;
 	
-	if( count > 4096 )
+	if( count > 4096 || count <= 0)
 		return -EMSGSIZE;
 
 	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
@@ -1128,7 +1128,7 @@ static int r128_cce_dispatch_read_span( 
 
 	count = depth->n;
 	
-	if ( count > 4096 )
+	if ( count > 4096 || count <= 0)
 		return -EMSGSIZE;
 	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
 		return -EFAULT;
@@ -1172,6 +1172,9 @@ static int r128_cce_dispatch_read_pixels
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
 	count = depth->n;
+	if ( count > 4096 || count <= 0)
+		return -EMSGSIZE;
+
 	if ( count > dev_priv->depth_pitch ) {
 		count = dev_priv->depth_pitch;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/drm-4.0/r128_state.c linux-2.4.26-rc3/drivers/char/drm-4.0/r128_state.c
--- linux-2.4.25/drivers/char/drm-4.0/r128_state.c	2002-02-25 19:37:57.000000000 +0000
+++ linux-2.4.26-rc3/drivers/char/drm-4.0/r128_state.c	2004-04-12 19:03:18.000000000 +0000
@@ -938,6 +938,9 @@ static int r128_cce_dispatch_write_span(
 	}
 
 	count = depth->n;
+
+	if (count > 4096 || count <= 0)
+		return -EMSGSIZE;
 	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
 		return -EFAULT;
 	}
@@ -1048,6 +1051,9 @@ static int r128_cce_dispatch_write_pixel
 
 	count = depth->n;
 
+	if (count > 4096 || count <= 0)
+		return -EMSGSIZE;
+
 	x = kmalloc( count * sizeof(*x), 0 );
 	if ( x == NULL ) {
 		return -ENOMEM;
@@ -1178,6 +1184,10 @@ static int r128_cce_dispatch_read_span( 
 	}
 
 	count = depth->n;
+	
+	if (count > 4096 || count <= 0)
+		return -EMSGSIZE;
+
 	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
 		return -EFAULT;
 	}
@@ -1235,6 +1245,8 @@ static int r128_cce_dispatch_read_pixels
 	}
 
 	count = depth->n;
+	if (count > 4096 || count <= 0)
+		return -EMSGSIZE;
 	if ( count > dev_priv->depth_pitch ) {
 		count = dev_priv->depth_pitch;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/char/q40_keyb.c linux-2.4.26-rc3/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-rc3/drivers/char/q40_keyb.c	2004-04-12 19:02:55.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-rc3/drivers/char/sonypi.c
--- linux-2.4.25/drivers/char/sonypi.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/char/sonypi.c	2004-04-12 19:03:51.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-rc3/drivers/char/sonypi.h
--- linux-2.4.25/drivers/char/sonypi.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/char/sonypi.h	2004-04-12 19:00:22.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-rc3/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-rc3/drivers/char/tty_io.c	2004-04-12 19:03:18.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-rc3/drivers/i2c/Config.in
--- linux-2.4.25/drivers/i2c/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/i2c/Config.in	2004-04-12 19:04:58.318250120 +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-rc3/drivers/ide/Config.in
--- linux-2.4.25/drivers/ide/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/Config.in	2004-04-12 19:04:40.669933072 +0000
@@ -49,6 +49,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the
 	    dep_mbool    '      ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
 	    dep_tristate '    AMD and nVidia IDE support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_mbool    '      AMD Viper ATA-66 Override' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX
+	    dep_tristate '    ATI IXP chipset IDE support' CONFIG_BLK_DEV_ATIIXP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
 	    dep_tristate '    CMD64{3|6|8|9} chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_tristate '    Compaq Triflex IDE support' CONFIG_BLK_DEV_TRIFLEX $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_tristate '    CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI
@@ -190,6 +191,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-rc3/drivers/ide/Makefile
--- linux-2.4.25/drivers/ide/Makefile	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/Makefile	2004-04-12 19:03:30.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-probe.c linux-2.4.26-rc3/drivers/ide/ide-probe.c
--- linux-2.4.25/drivers/ide/ide-probe.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/ide-probe.c	2004-04-12 19:00:02.000000000 +0000
@@ -102,7 +102,8 @@ static inline int drive_is_flashcard (id
 		if (id->config == 0x848a) return 1;	/* CompactFlash */
 		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
 		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
-		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* SunDisk */
+		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* old SanDisk */
+		 || !strncmp(id->model, "SanDisk SDCFB", 13)	/* SanDisk */
 		 || !strncmp(id->model, "HAGIWARA HPC", 12)	/* Hagiwara */
 		 || !strncmp(id->model, "LEXAR ATA_FLASH", 15)	/* Lexar */
 		 || !strncmp(id->model, "ATA_FLASH", 9))	/* Simple Tech */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/ide-proc.c linux-2.4.26-rc3/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-rc3/drivers/ide/ide-proc.c	2004-04-12 19:00:27.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/Makefile linux-2.4.26-rc3/drivers/ide/pci/Makefile
--- linux-2.4.25/drivers/ide/pci/Makefile	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/pci/Makefile	2004-04-12 19:00:38.000000000 +0000
@@ -8,6 +8,7 @@ obj-$(CONFIG_BLK_DEV_ADMA100)		+= adma10
 obj-$(CONFIG_BLK_DEV_AEC62XX)		+= aec62xx.o
 obj-$(CONFIG_BLK_DEV_ALI15X3)		+= alim15x3.o
 obj-$(CONFIG_BLK_DEV_AMD74XX)		+= amd74xx.o
+obj-$(CONFIG_BLK_DEV_ATIIXP)		+= atiixp.o
 obj-$(CONFIG_BLK_DEV_CMD640)		+= cmd640.o
 obj-$(CONFIG_BLK_DEV_CMD64X)		+= cmd64x.o
 obj-$(CONFIG_BLK_DEV_CS5530)		+= cs5530.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/amd74xx.c linux-2.4.26-rc3/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-rc3/drivers/ide/pci/amd74xx.c	2004-04-12 19:03:14.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-rc3/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-rc3/drivers/ide/pci/amd74xx.h	2004-04-12 19:04:40.103019256 +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/atiixp.c linux-2.4.26-rc3/drivers/ide/pci/atiixp.c
--- linux-2.4.25/drivers/ide/pci/atiixp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/pci/atiixp.c	2004-04-12 19:02:44.000000000 +0000
@@ -0,0 +1,522 @@
+/*
+ *  linux/drivers/ide/pci/atiixp.c	Version 0.01-bart2	Feb. 26, 2004
+ *
+ *  Copyright (C) 2003 ATI Inc. <hyu@ati.com>
+ *  Copyright (C) 2004 Bartlomiej Zolnierkiewicz
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define ATIIXP_IDE_PIO_TIMING		0x40
+#define ATIIXP_IDE_MDMA_TIMING		0x44
+#define ATIIXP_IDE_PIO_CONTROL		0x48
+#define ATIIXP_IDE_PIO_MODE		0x4a
+#define ATIIXP_IDE_UDMA_CONTROL		0x54
+#define ATIIXP_IDE_UDMA_MODE		0x56
+
+typedef struct {
+	u8 command_width;
+	u8 recover_width;
+} atiixp_ide_timing;
+
+static atiixp_ide_timing pio_timing[] = {
+	{ 0x05, 0x0d },
+	{ 0x04, 0x07 },
+	{ 0x03, 0x04 },
+	{ 0x02, 0x02 },
+	{ 0x02, 0x00 },
+};
+
+static atiixp_ide_timing mdma_timing[] = {
+	{ 0x07, 0x07 },
+	{ 0x02, 0x01 },
+	{ 0x02, 0x00 },
+};
+
+static int save_mdma_mode[4];
+
+#define DISPLAY_ATIIXP_TIMINGS
+
+#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS)
+
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static u8 atiixp_proc;
+static struct pci_dev *bmide_dev;
+
+/**
+ *	atiixp_get_info		-	fill in /proc for ATIIXP IDE
+ *	@buffer: buffer to fill
+ *	@addr: address of user start in buffer
+ *	@offset: offset into 'file'
+ *	@count: buffer count
+ *
+ *	Output summary data on the tuning.
+ */
+
+static int atiixp_get_info(char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	struct pci_dev *dev = bmide_dev;
+	unsigned long bibma = pci_resource_start(dev, 4);
+	u32 mdma_timing = 0;
+	u16 udma_mode = 0, pio_mode = 0;
+	u8 c0, c1, udma_control = 0;
+
+	p += sprintf(p, "\n                          ATI ");
+	p += sprintf(p, "ATIIXP Ultra100 IDE Chipset.\n");
+
+	pci_read_config_byte(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_control);
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &udma_mode);
+	pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode);
+	pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &mdma_timing);
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb(bibma + 0x02);
+	c1 = inb(bibma + 0x0a);
+
+	p += sprintf(p, "--------------- Primary Channel "
+			"---------------- Secondary Channel "
+			"-------------\n");
+	p += sprintf(p, "                %sabled "
+			"                        %sabled\n",
+			(c0 & 0x80) ? "dis" : " en",
+			(c1 & 0x80) ? "dis" : " en");
+	p += sprintf(p, "--------------- drive0 --------- drive1 "
+			"-------- drive0 ---------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:    %s              %s "
+			"            %s               %s\n",
+			(c0 & 0x20) ? "yes" : "no ",
+			(c0 & 0x40) ? "yes" : "no ",
+			(c1 & 0x20) ? "yes" : "no ",
+			(c1 & 0x40) ? "yes" : "no " );
+	p += sprintf(p, "UDMA enabled:   %s              %s "
+			"            %s               %s\n",
+			(udma_control & 0x01) ? "yes" : "no ",
+			(udma_control & 0x02) ? "yes" : "no ",
+			(udma_control & 0x04) ? "yes" : "no ",
+			(udma_control & 0x08) ? "yes" : "no " );
+	p += sprintf(p, "UDMA mode:      %c                %c "
+			"              %c                 %c\n",
+			(udma_control & 0x01) ?
+			((udma_mode & 0x07) + 48) : 'X',
+			(udma_control & 0x02) ?
+			(((udma_mode >> 4) & 0x07) + 48) : 'X',
+			(udma_control & 0x04) ?
+			(((udma_mode >> 8) & 0x07) + 48) : 'X',
+			(udma_control & 0x08) ?
+			(((udma_mode >> 12) & 0x07) + 48) : 'X');
+	p += sprintf(p, "MDMA mode:      %c                %c "
+			"              %c                 %c\n",
+			(save_mdma_mode[0] && (c0 & 0x20)) ?
+			((save_mdma_mode[0] & 0xf) + 48) : 'X',
+			(save_mdma_mode[1] && (c0 & 0x40)) ?
+			((save_mdma_mode[1] & 0xf) + 48) : 'X',
+			(save_mdma_mode[2] && (c1 & 0x20)) ?
+			((save_mdma_mode[2] & 0xf) + 48) : 'X',
+			(save_mdma_mode[3] && (c1 & 0x40)) ?
+			((save_mdma_mode[3] & 0xf) + 48) : 'X');
+	p += sprintf(p, "PIO mode:       %c                %c "
+			"              %c                 %c\n",
+			(c0 & 0x20) ? 'X' : ((pio_mode & 0x07) + 48),
+			(c0 & 0x40) ? 'X' : (((pio_mode >> 4) & 0x07) + 48),
+			(c1 & 0x20) ? 'X' : (((pio_mode >> 8) & 0x07) + 48),
+			(c1 & 0x40) ? 'X' : (((pio_mode >> 12) & 0x07) + 48));
+
+	return p - buffer;	/* => must be less than 4k! */
+}
+
+static ide_pci_host_proc_t atiixp_procs = {
+	.name		= "atiixp",
+	.set		= 1,
+	.get_info	= atiixp_get_info,
+};
+#endif  /* defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/**
+ *	atiixp_ratemask		-	compute rate mask for ATIIXP IDE
+ *	@drive: IDE drive to compute for
+ *
+ *	Returns the available modes for the ATIIXP IDE controller.
+ */
+
+static u8 atiixp_ratemask(ide_drive_t *drive)
+{
+	u8 mode = 3;
+
+	if (!eighty_ninty_three(drive))
+		mode = min(mode, (u8)1);
+	return mode;
+}
+
+/**
+ *	atiixp_dma_2_pio		-	return the PIO mode matching DMA
+ *	@xfer_rate: transfer speed
+ *
+ *	Returns the nearest equivalent PIO timing for the PIO or DMA
+ *	mode requested by the controller.
+ */
+
+static u8 atiixp_dma_2_pio(u8 xfer_rate) {
+	switch(xfer_rate) {
+		case XFER_UDMA_6:
+		case XFER_UDMA_5:
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+		case XFER_MW_DMA_2:
+		case XFER_PIO_4:
+			return 4;
+		case XFER_MW_DMA_1:
+		case XFER_PIO_3:
+			return 3;
+		case XFER_SW_DMA_2:
+		case XFER_PIO_2:
+			return 2;
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+		case XFER_PIO_SLOW:
+		default:
+			return 0;
+	}
+}
+
+static int atiixp_ide_dma_host_on(ide_drive_t *drive)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+	if (save_mdma_mode[drive->dn])
+		tmp16 &= ~(1 << drive->dn);
+	else
+		tmp16 |= (1 << drive->dn);
+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	return __ide_dma_host_on(drive);
+}
+
+static int atiixp_ide_dma_host_off(ide_drive_t *drive)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+	tmp16 &= ~(1 << drive->dn);
+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	return __ide_dma_host_off(drive);
+}
+
+/**
+ *	atiixp_tune_drive		-	tune a drive attached to a ATIIXP
+ *	@drive: drive to tune
+ *	@pio: desired PIO mode
+ *
+ *	Set the interface PIO mode.
+ */
+
+static void atiixp_tuneproc(ide_drive_t *drive, u8 pio)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	u32 pio_timing_data;
+	u16 pio_mode_data;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
+	pio_mode_data &= ~(0x07 << (drive->dn * 4));
+	pio_mode_data |= (pio << (drive->dn * 4));
+	pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
+
+	pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+	pio_timing_data &= ~(0xff << timing_shift);
+	pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) |
+		 (pio_timing[pio].command_width << (timing_shift + 4));
+	pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+/**
+ *	atiixp_tune_chipset	-	tune a ATIIXP interface
+ *	@drive: IDE drive to tune
+ *	@xferspeed: speed to configure
+ *
+ *	Set a ATIIXP interface channel to the desired speeds. This involves
+ *	requires the right timing data into the ATIIXP configuration space
+ *	then setting the drive parameters appropriately
+ */
+
+static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	u32 tmp32;
+	u16 tmp16;
+	u8 speed, pio;
+
+	speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed);
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	save_mdma_mode[drive->dn] = 0;
+	if (speed >= XFER_UDMA_0) {
+		pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
+		tmp16 &= ~(0x07 << (drive->dn * 4));
+		tmp16 |= ((speed & 0x07) << (drive->dn * 4));
+		pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
+	} else {
+		if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) {
+			save_mdma_mode[drive->dn] = speed;
+			pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
+			tmp32 &= ~(0xff << timing_shift);
+			tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) |
+				(mdma_timing[speed & 0x03].command_width << (timing_shift + 4));
+			pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
+		}
+	}
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	if (speed >= XFER_SW_DMA_0)
+		pio = atiixp_dma_2_pio(speed);
+	else
+		pio = speed - XFER_PIO_0;
+
+	atiixp_tuneproc(drive, pio);
+
+	return ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *	atiixp_config_drive_for_dma	-	configure drive for DMA
+ *	@drive: IDE drive to configure
+ *
+ *	Set up a ATIIXP interface channel for the best available speed.
+ *	We prefer UDMA if it is available and then MWDMA. If DMA is
+ *	not available we switch to PIO and return 0.
+ */
+
+static int atiixp_config_drive_for_dma(ide_drive_t *drive)
+{
+	u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive));
+
+	/* If no DMA speed was available then disable DMA and use PIO. */
+	if (!speed) {
+		u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
+		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
+	}
+
+	(void) atiixp_speedproc(drive, speed);
+	return ide_dma_enable(drive);
+}
+
+/**
+ *	atiixp_dma_check	-	set up an IDE device
+ *	@drive: IDE drive to configure
+ *
+ *	Set up the ATIIXP interface for the best available speed on this
+ *	interface, preferring DMA to PIO.
+ */
+
+static int atiixp_dma_check(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id	= drive->id;
+	u8 tspeed, speed;
+
+	drive->init_speed = 0;
+
+	if ((id->capability & 1) && drive->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (__ide_dma_bad_drive(drive))
+			goto fast_ata_pio;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & hwif->ultra_mask) {
+				/* Force if Capable UltraDMA */
+				if ((id->field_valid & 2) &&
+				    (!atiixp_config_drive_for_dma(drive)))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & hwif->mwdma_mask) ||
+			    (id->dma_1word & hwif->swdma_mask)) {
+				/* Force if Capable regular DMA modes */
+				if (!atiixp_config_drive_for_dma(drive))
+					goto no_dma_set;
+			}
+		} else if (__ide_dma_good_drive(drive) &&
+			   (id->eide_dma_time < 150)) {
+			/* Consult the list of known "good" drives */
+			if (!atiixp_config_drive_for_dma(drive))
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+		return hwif->ide_dma_on(drive);
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+no_dma_set:
+		tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
+		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
+		hwif->speedproc(drive, speed);
+		return hwif->ide_dma_off_quietly(drive);
+	}
+	/* IORDY not supported */
+	return 0;
+}
+
+/**
+ *	init_chipset_atiixp	-	set up the ATIIXP chipset
+ *	@dev: PCI device to set up
+ *	@name: Name of the device
+ *
+ *	Initialize the PCI device as required. For the ATIIXP this turns
+ *	out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_atiixp(struct pci_dev *dev, const char *name)
+{
+#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!atiixp_proc) {
+		atiixp_proc = 1;
+		bmide_dev = dev;
+		ide_pci_register_host_proc(&atiixp_procs);
+	}
+#endif /* DISPLAY_ATIIXP_TIMINGS && CONFIG_PROC_FS */
+	return 0;
+}
+
+/**
+ *	init_hwif_atiixp		-	fill in the hwif for the ATIIXP
+ *	@hwif: IDE interface
+ *
+ *	Set up the ide_hwif_t for the ATIIXP interface according to the
+ *	capabilities of the hardware.
+ */
+
+static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
+{
+	if (!hwif->irq)
+		hwif->irq = hwif->channel ? 15 : 14;
+
+	hwif->autodma = 0;
+	hwif->tuneproc = &atiixp_tuneproc;
+	hwif->speedproc = &atiixp_speedproc;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	if (!hwif->dma_base)
+		return;
+
+	hwif->atapi_dma = 1;
+	hwif->ultra_mask = 0x3f;
+	hwif->mwdma_mask = 0x06;
+	hwif->swdma_mask = 0x04;
+
+	/* FIXME: proper cable detection needed */
+	hwif->udma_four = 1;
+	hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
+	hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
+	hwif->ide_dma_check = &atiixp_dma_check;
+	if (!noautodma)
+		hwif->autodma = 1;
+
+	hwif->drives[1].autodma = hwif->autodma;
+	hwif->drives[0].autodma = hwif->autodma;
+}
+
+static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
+	{	/* 0 */
+		.vendor		= PCI_VENDOR_ID_ATI,
+		.device		= PCI_DEVICE_ID_ATI_IXP_IDE,
+		.name		= "ATIIXP",
+		.init_chipset	= init_chipset_atiixp,
+		.init_hwif	= init_hwif_atiixp,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+		.bootable	= ON_BOARD,
+	}
+};
+
+/**
+ *	atiixp_init_one	-	called when a ATIIXP is found
+ *	@dev: the atiixp device
+ *	@id: the matching pci id
+ *
+ *	Called when the PCI registration layer (or the IDE initialization)
+ *	finds a device matching our IDE device tables.
+ */
+
+static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &atiixp_pci_info[id->driver_data];
+
+	if (dev->device != d->device)
+		BUG();
+	ide_setup_pci_device(dev, d);
+	return 0;
+}
+
+static struct pci_device_id atiixp_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, },
+};
+
+static struct pci_driver driver = {
+	.name		= "ATIIXP IDE",
+	.id_table	= atiixp_pci_tbl,
+	.probe		= atiixp_init_one,
+};
+
+static int atiixp_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+module_init(atiixp_ide_init);
+
+MODULE_AUTHOR("HUI YU");
+MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/generic.h linux-2.4.26-rc3/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-rc3/drivers/ide/pci/generic.h	2004-04-12 19:01:02.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/hpt366.c linux-2.4.26-rc3/drivers/ide/pci/hpt366.c
--- linux-2.4.25/drivers/ide/pci/hpt366.c	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/pci/hpt366.c	2004-04-12 19:00:56.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/ide/pci/hpt366.c		Version 0.36	April 25, 2003
  *
- * Copyright (C) 1999-2002		Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
  *
@@ -668,6 +668,31 @@ static int hpt370_ide_dma_lostirq (ide_d
 	return __ide_dma_lostirq(drive);
 }
 
+/* returns 1 if DMA IRQ issued, 0 otherwise */
+static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	u16 bfifo		= 0;
+	u8 reginfo		= hwif->channel ? 0x56 : 0x52;
+	u8 dma_stat;
+
+	pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);
+	if (bfifo & 0x1FF) {
+//		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
+		return 0;
+	}
+
+	dma_stat = hwif->INB(hwif->dma_status);
+	/* return 1 if INTR asserted */
+	if ((dma_stat & 4) == 4)
+		return 1;
+
+	if (!drive->waiting_for_dma)
+		printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+				drive->name, __FUNCTION__);
+	return 0;
+}
+
 static int hpt374_ide_dma_end (ide_drive_t *drive)
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
@@ -1245,11 +1270,13 @@ static void __init init_hwif_hpt366 (ide
 		hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
 	hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
 
-	if (hpt_minimum_revision(dev,8))
+	if (hpt_minimum_revision(dev,8)) {
+		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
 		hwif->ide_dma_end = &hpt374_ide_dma_end;
-	else if (hpt_minimum_revision(dev,5))
+	} else if (hpt_minimum_revision(dev,5)) {
+		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
 		hwif->ide_dma_end = &hpt374_ide_dma_end;
-	else if (hpt_minimum_revision(dev,3)) {
+	} else if (hpt_minimum_revision(dev,3)) {
 		hwif->ide_dma_begin = &hpt370_ide_dma_begin;
 		hwif->ide_dma_end = &hpt370_ide_dma_end;
 		hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/pci/piix.c linux-2.4.26-rc3/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-rc3/drivers/ide/pci/piix.c	2004-04-12 19:04:45.122256216 +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-rc3/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-rc3/drivers/ide/pci/piix.h	2004-04-12 19:04:52.257171544 +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-rc3/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-rc3/drivers/ide/pci/siimage.c	2004-04-12 19:04:22.012769392 +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-rc3/drivers/ide/raid/Makefile
--- linux-2.4.25/drivers/ide/raid/Makefile	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ide/raid/Makefile	2004-04-12 19:04:00.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-rc3/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-rc3/drivers/ide/raid/medley.c	2004-04-12 19:00:39.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-rc3/drivers/ieee1394/dma.c
--- linux-2.4.25/drivers/ieee1394/dma.c	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ieee1394/dma.c	2004-04-12 19:02:11.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-rc3/drivers/ieee1394/video1394.c
--- linux-2.4.25/drivers/ieee1394/video1394.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-rc3/drivers/ieee1394/video1394.c	2004-04-12 19:01:00.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-rc3/drivers/input/input.c
--- linux-2.4.25/drivers/input/input.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.26-rc3/drivers/input/input.c	2004-04-12 19:03:10.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-rc3/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-rc3/drivers/isdn/avmb1/capidrv.c	2004-04-12 19:02:34.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-rc3/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-rc3/drivers/isdn/avmb1/kcapi.c	2004-04-12 19:04:13.833012904 +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-rc3/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-rc3/drivers/isdn/hisax/isurf.c	2004-04-12 19:03:09.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-rc3/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-rc3/drivers/md/lvm-snap.c	2004-04-12 19:03:54.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/md/raid1.c linux-2.4.26-rc3/drivers/md/raid1.c
--- linux-2.4.25/drivers/md/raid1.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/md/raid1.c	2004-04-12 19:03:09.000000000 +0000
@@ -487,6 +487,12 @@ static int raid1_read_balance (raid1_con
 		goto rb_out;
 	
 
+#if defined(CONFIG_ALPHA) && ((__GNUC__ < 3) || \
+			      ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3)))
+	/* Work around a compiler bug in older gcc */
+	new_disk = *(volatile int *)&new_disk;
+#endif
+
 	/* make sure that disk is operational */
 	while( !conf->mirrors[new_disk].operational) {
 		if (new_disk <= 0) new_disk = conf->raid_disks;
@@ -544,6 +550,11 @@ static int raid1_read_balance (raid1_con
 	
 	/* Find the disk which is closest */
 	
+#if defined(CONFIG_ALPHA) && ((__GNUC__ < 3) || \
+			      ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3)))
+	/* Work around a compiler bug in older gcc */
+	disk = *(volatile int *)&disk;
+#endif
 	do {
 		if (disk <= 0)
 			disk = conf->raid_disks;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/media/video/Config.in linux-2.4.26-rc3/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-rc3/drivers/media/video/Config.in	2004-04-12 19:03:09.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-rc3/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-rc3/drivers/media/video/meye.c	2004-04-12 19:03:17.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-rc3/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-rc3/drivers/media/video/meye.h	2004-04-12 19:03:07.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-rc3/drivers/net/8139too.c
--- linux-2.4.25/drivers/net/8139too.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/8139too.c	2004-04-12 19:00:00.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-rc3/drivers/net/Config.in
--- linux-2.4.25/drivers/net/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/Config.in	2004-04-12 19:03:25.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-rc3/drivers/net/Makefile
--- linux-2.4.25/drivers/net/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/Makefile	2004-04-12 19:01:41.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-rc3/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-rc3/drivers/net/bonding/bond_3ad.c	2004-04-12 19:04:33.935956792 +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-rc3/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-rc3/drivers/net/bonding/bond_3ad.h	2004-04-12 19:02:30.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-rc3/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-rc3/drivers/net/bonding/bond_alb.c	2004-04-12 19:02:00.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-rc3/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-rc3/drivers/net/bonding/bond_alb.h	2004-04-12 19:03:17.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-rc3/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-rc3/drivers/net/bonding/bond_main.c	2004-04-12 19:02:14.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-rc3/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-rc3/drivers/net/bonding/bonding.h	2004-04-12 19:02:20.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-rc3/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-rc3/drivers/net/e1000/e1000.h	2004-04-12 19:02:11.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-rc3/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-rc3/drivers/net/e1000/e1000_ethtool.c	2004-04-12 19:03:37.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-rc3/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-rc3/drivers/net/e1000/e1000_hw.c	2004-04-12 19:03:44.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-rc3/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-rc3/drivers/net/e1000/e1000_hw.h	2004-04-12 19:01:02.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-rc3/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-rc3/drivers/net/e1000/e1000_main.c	2004-04-12 19:02:29.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-rc3/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-rc3/drivers/net/e1000/e1000_osdep.h	2004-04-12 19:01:39.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-rc3/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-rc3/drivers/net/e1000/e1000_param.c	2004-04-12 19:00:54.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-rc3/drivers/net/forcedeth.c
--- linux-2.4.25/drivers/net/forcedeth.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/forcedeth.c	2004-04-12 19:00:35.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-rc3/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-rc3/drivers/net/ibm_emac/ibm_emac.h	2004-04-12 19:03:02.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-rc3/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-rc3/drivers/net/ibm_emac/ibm_ocp_enet.c	2004-04-12 19:00:32.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-rc3/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-rc3/drivers/net/ibm_emac/ibm_ocp_mal.c	2004-04-12 19:02:20.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-rc3/drivers/net/natsemi.c
--- linux-2.4.25/drivers/net/natsemi.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/natsemi.c	2004-04-12 19:00:32.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-rc3/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-rc3/drivers/net/ne2k-pci.c	2004-04-12 19:01:23.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-rc3/drivers/net/pcnet32.c
--- linux-2.4.25/drivers/net/pcnet32.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/pcnet32.c	2004-04-12 19:01:38.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-rc3/drivers/net/r8169.c
--- linux-2.4.25/drivers/net/r8169.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/r8169.c	2004-04-12 19:01:21.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-rc3/drivers/net/sis900.c
--- linux-2.4.25/drivers/net/sis900.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/sis900.c	2004-04-12 19:02:32.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-rc3/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-rc3/drivers/net/sk98lin/h/lm80.h	2004-04-12 19:04:33.345046624 +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-rc3/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-rc3/drivers/net/sk98lin/h/skaddr.h	2004-04-12 19:03:02.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-rc3/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-rc3/drivers/net/sk98lin/h/skcsum.h	2004-04-12 19:00:34.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-rc3/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-rc3/drivers/net/sk98lin/h/skdebug.h	2004-04-12 19:02:57.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-rc3/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-rc3/drivers/net/sk98lin/h/skdrv1st.h	2004-04-12 19:00:16.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-rc3/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-rc3/drivers/net/sk98lin/h/skdrv2nd.h	2004-04-12 19:05:03.280495744 +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-rc3/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-rc3/drivers/net/sk98lin/h/skerror.h	2004-04-12 19:02:49.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-rc3/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-rc3/drivers/net/sk98lin/h/skgedrv.h	2004-04-12 19:03:30.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-rc3/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-rc3/drivers/net/sk98lin/h/skgehw.h	2004-04-12 19:04:52.308163792 +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-rc3/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-rc3/drivers/net/sk98lin/h/skgehwt.h	2004-04-12 19:02:13.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-rc3/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-rc3/drivers/net/sk98lin/h/skgei2c.h	2004-04-12 19:03:57.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-rc3/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-rc3/drivers/net/sk98lin/h/skgeinit.h	2004-04-12 19:03:57.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-rc3/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-rc3/drivers/net/sk98lin/h/skgepnm2.h	2004-04-12 19:03:35.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-rc3/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-rc3/drivers/net/sk98lin/h/skgepnmi.h	2004-04-12 19:00:46.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-rc3/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-rc3/drivers/net/sk98lin/h/skgesirq.h	2004-04-12 19:04:42.033725744 +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-rc3/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-rc3/drivers/net/sk98lin/h/ski2c.h	2004-04-12 19:01:45.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-rc3/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-rc3/drivers/net/sk98lin/h/skqueue.h	2004-04-12 19:05:03.329488296 +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-rc3/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-rc3/drivers/net/sk98lin/h/skrlmt.h	2004-04-12 19:05:16.197532056 +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-rc3/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-rc3/drivers/net/sk98lin/h/sktimer.h	2004-04-12 19:01:10.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-rc3/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-rc3/drivers/net/sk98lin/h/sktypes.h	2004-04-12 19:05:09.292581768 +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-rc3/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-rc3/drivers/net/sk98lin/h/skversion.h	2004-04-12 19:03:14.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-rc3/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-rc3/drivers/net/sk98lin/h/skvpd.h	2004-04-12 19:01:55.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-rc3/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-rc3/drivers/net/sk98lin/h/xmac_ii.h	2004-04-12 19:04:24.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-rc3/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-rc3/drivers/net/sk98lin/skaddr.c	2004-04-12 19:03:20.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-rc3/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-rc3/drivers/net/sk98lin/skcsum.c	2004-04-12 19:00:21.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-rc3/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-rc3/drivers/net/sk98lin/skdim.c	2004-04-12 19:04:38.835211992 +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-rc3/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-rc3/drivers/net/sk98lin/skge.c	2004-04-12 19:00:59.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-rc3/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-rc3/drivers/net/sk98lin/skgehwt.c	2004-04-12 19:04:36.108626496 +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-rc3/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-rc3/drivers/net/sk98lin/skgeinit.c	2004-04-12 19:03:03.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-rc3/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-rc3/drivers/net/sk98lin/skgemib.c	2004-04-12 19:02:08.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-rc3/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-rc3/drivers/net/sk98lin/skgepnmi.c	2004-04-12 19:03:51.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-rc3/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-rc3/drivers/net/sk98lin/skgesirq.c	2004-04-12 19:00:05.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-rc3/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-rc3/drivers/net/sk98lin/ski2c.c	2004-04-12 19:00:02.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-rc3/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-rc3/drivers/net/sk98lin/sklm80.c	2004-04-12 19:04:30.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-rc3/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-rc3/drivers/net/sk98lin/skproc.c	2004-04-12 19:00:35.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-rc3/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-rc3/drivers/net/sk98lin/skqueue.c	2004-04-12 19:01:27.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-rc3/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-rc3/drivers/net/sk98lin/skrlmt.c	2004-04-12 19:03:27.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-rc3/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-rc3/drivers/net/sk98lin/sktimer.c	2004-04-12 19:00:46.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-rc3/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-rc3/drivers/net/sk98lin/skvpd.c	2004-04-12 19:03:17.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-rc3/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-rc3/drivers/net/sk98lin/skxmac2.c	2004-04-12 19:02:32.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/sk_mca.c linux-2.4.26-rc3/drivers/net/sk_mca.c
--- linux-2.4.25/drivers/net/sk_mca.c	2001-10-17 04:56:29.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/sk_mca.c	2004-04-12 19:03:33.000000000 +0000
@@ -1048,13 +1048,13 @@ static void skmca_set_multicast_list(str
 		block.Mode &= ~LANCE_INIT_PROM;
 
 	if (dev->flags & IFF_ALLMULTI) {	/* get all multicasts */
-		memset(block.LAdrF, 8, 0xff);
+		memset(block.LAdrF, 0xff, sizeof(block.LAdrF));
 	} else {		/* get selected/no multicasts */
 
 		struct dev_mc_list *mptr;
 		int code;
 
-		memset(block.LAdrF, 8, 0x00);
+		memset(block.LAdrF, 0, sizeof(block.LAdrF));
 		for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next) {
 			code = GetHash(mptr->dmi_addr);
 			block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sungem.c linux-2.4.26-rc3/drivers/net/sungem.c
--- linux-2.4.25/drivers/net/sungem.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/sungem.c	2004-04-12 19:04:52.283167592 +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-rc3/drivers/net/tg3.c
--- linux-2.4.25/drivers/net/tg3.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/tg3.c	2004-04-12 19:02:30.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-rc3/drivers/net/tg3.h
--- linux-2.4.25/drivers/net/tg3.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/tg3.h	2004-04-12 19:03:23.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-rc3/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-rc3/drivers/net/tulip/tulip_core.c	2004-04-12 19:03:18.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-rc3/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-rc3/drivers/net/typhoon-firmware.h	2004-04-12 19:04:05.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-rc3/drivers/net/typhoon.c
--- linux-2.4.25/drivers/net/typhoon.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/typhoon.c	2004-04-12 19:04:05.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-rc3/drivers/net/typhoon.h
--- linux-2.4.25/drivers/net/typhoon.h	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/typhoon.h	2004-04-12 19:04:20.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-rc3/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-rc3/drivers/net/wireless/Config.in	2004-04-12 19:01:44.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-rc3/drivers/net/wireless/Makefile
--- linux-2.4.25/drivers/net/wireless/Makefile	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/net/wireless/Makefile	2004-04-12 19:05:16.989411672 +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-rc3/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-rc3/drivers/net/wireless/airo.c	2004-04-12 19:00:49.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-rc3/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-rc3/drivers/net/wireless/atmel.c	2004-04-12 19:03:11.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-rc3/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-rc3/drivers/net/wireless/atmel_cs.c	2004-04-12 19:02: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-rc3/drivers/pcmcia/yenta.c
--- linux-2.4.25/drivers/pcmcia/yenta.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/pcmcia/yenta.c	2004-04-12 19:03:22.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-rc3/drivers/scsi/advansys.c
--- linux-2.4.25/drivers/scsi/advansys.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-rc3/drivers/scsi/advansys.c	2004-04-12 19:01:45.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-rc3/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-rc3/drivers/scsi/eata_dma.c	2004-04-12 19:00:21.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-rc3/drivers/scsi/qlogicfc.c
--- linux-2.4.25/drivers/scsi/qlogicfc.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-rc3/drivers/scsi/qlogicfc.c	2004-04-12 19:03:53.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-rc3/drivers/scsi/qlogicpti.c
--- linux-2.4.25/drivers/scsi/qlogicpti.c	2001-10-30 23:08:11.000000000 +0000
+++ linux-2.4.26-rc3/drivers/scsi/qlogicpti.c	2004-04-12 19:03:42.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-rc3/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-rc3/drivers/scsi/scsi_error.c	2004-04-12 19:00:09.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-rc3/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-rc3/drivers/scsi/scsi_lib.c	2004-04-12 19:02:51.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-rc3/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-rc3/drivers/scsi/scsi_scan.c	2004-04-12 19:04:08.000000000 +0000
@@ -176,6 +176,7 @@ static struct dev_info device_list[] =
 	{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
 	{"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},
 	{"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},
+	{"APPLE", "Xserve", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"COMPAQ", "MSA1000", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ", "MSA1000 VOLUME", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ", "HSV110", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
@@ -189,6 +190,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 +223,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 +250,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 +641,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 +652,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 +707,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 +919,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-rc3/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-rc3/drivers/scsi/scsi_syms.c	2004-04-12 19:02:50.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-rc3/drivers/scsi/sym53c8xx.c
--- linux-2.4.25/drivers/scsi/sym53c8xx.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-rc3/drivers/scsi/sym53c8xx.c	2004-04-12 19:03:38.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-rc3/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-rc3/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-04-12 19:00:05.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-rc3/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-rc3/drivers/sound/i810_audio.c	2004-04-12 19:03:59.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-rc3/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-rc3/drivers/sound/sb_audio.c	2004-04-12 19:04:14.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-rc3/drivers/usb/audio.c
--- linux-2.4.25/drivers/usb/audio.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/audio.c	2004-04-12 19:04:59.312099032 +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-rc3/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-rc3/drivers/usb/gadget/Config.in	2004-04-12 19:02:43.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-rc3/drivers/usb/gadget/Makefile
--- linux-2.4.25/drivers/usb/gadget/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/gadget/Makefile	2004-04-12 19:01:46.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-rc3/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-rc3/drivers/usb/gadget/config.c	2004-04-12 19:01:30.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-rc3/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-rc3/drivers/usb/gadget/ether.c	2004-04-12 19:00:22.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-rc3/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-rc3/drivers/usb/gadget/gadget_chips.h	2004-04-12 19:01:09.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-rc3/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-rc3/drivers/usb/gadget/net2280.c	2004-04-12 19:01:38.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-rc3/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-rc3/drivers/usb/gadget/usbstring.c	2004-04-12 19:01:14.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-rc3/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-rc3/drivers/usb/gadget/zero.c	2004-04-12 19:00:51.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-rc3/drivers/usb/hcd.c
--- linux-2.4.25/drivers/usb/hcd.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/hcd.c	2004-04-12 19:02:43.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-rc3/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-rc3/drivers/usb/hid-core.c	2004-04-12 19:03:16.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-rc3/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-rc3/drivers/usb/hid-input.c	2004-04-12 19:02: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-rc3/drivers/usb/hiddev.c
--- linux-2.4.25/drivers/usb/hiddev.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/hiddev.c	2004-04-12 19:02:30.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-rc3/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-rc3/drivers/usb/host/ehci-dbg.c	2004-04-12 19:02:57.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-rc3/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-rc3/drivers/usb/host/ehci-hub.c	2004-04-12 19:03:25.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-rc3/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-rc3/drivers/usb/host/ehci-sched.c	2004-04-12 19:02:03.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/host/usb-ohci.c linux-2.4.26-rc3/drivers/usb/host/usb-ohci.c
--- linux-2.4.25/drivers/usb/host/usb-ohci.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/host/usb-ohci.c	2004-04-12 19:01:26.000000000 +0000
@@ -104,10 +104,6 @@
 
 #define OHCI_UNLINK_TIMEOUT	(HZ / 10)
 
-static LIST_HEAD (ohci_hcd_list);
-static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
-
-
 /*-------------------------------------------------------------------------*/
 
 /* AMD-756 (D2 rev) reports corrupt register contents in some cases.
@@ -134,6 +130,57 @@ static u32 roothub_portstatus (struct oh
 /*-------------------------------------------------------------------------*
  * URB support functions 
  *-------------------------------------------------------------------------*/ 
+
+static void ohci_complete_add(struct ohci *ohci, struct urb *urb)
+{
+
+	if (urb->hcpriv != NULL) {
+		printk("completing with non-null priv!\n");
+		return;
+	}
+
+	if (ohci->complete_tail == NULL) {
+		ohci->complete_head = urb;
+		ohci->complete_tail = urb;
+	} else {
+		ohci->complete_head->hcpriv = urb;
+		ohci->complete_tail = urb;
+	}
+}
+
+static inline struct urb *ohci_complete_get(struct ohci *ohci)
+{
+	struct urb *urb;
+
+	if ((urb = ohci->complete_head) == NULL)
+		return NULL;
+	if (urb == ohci->complete_tail) {
+		ohci->complete_tail = NULL;
+		ohci->complete_head = NULL;
+	} else {
+		ohci->complete_head = urb->hcpriv;
+	}
+	urb->hcpriv = NULL;
+	return urb;
+}
+
+static inline void ohci_complete(struct ohci *ohci)
+{
+	struct urb *urb;
+
+	spin_lock(&ohci->ohci_lock);
+	while ((urb = ohci_complete_get(ohci)) != NULL) {
+		spin_unlock(&ohci->ohci_lock);
+		if (urb->dev) {
+			usb_dec_dev_use (urb->dev);
+			urb->dev = NULL;
+		}
+		if (urb->complete)
+			(*urb->complete)(urb);
+		spin_lock(&ohci->ohci_lock);
+	}
+	spin_unlock(&ohci->ohci_lock);
+}
  
 /* free HCD-private data associated with this URB */
 
@@ -209,20 +256,14 @@ static void urb_rm_priv_locked (struct u
 		}
 
 		urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
-		usb_dec_dev_use (urb->dev);
-		urb->dev = NULL;
+	} else {
+		if (urb->dev != NULL) {
+			err ("Non-null dev at rm_priv time");
+			// urb->dev = NULL;
+		}
 	}
 }
 
-static void urb_rm_priv (struct urb * urb)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave (&usb_ed_lock, flags);
-	urb_rm_priv_locked (urb);
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
-}
-
 /*-------------------------------------------------------------------------*/
  
 #ifdef DEBUG
@@ -466,7 +507,6 @@ static int sohci_return_urb (struct ohci
 {
 	urb_priv_t * urb_priv = urb->hcpriv;
 	struct urb * urbt;
-	unsigned long flags;
 	int i;
 	
 	if (!urb_priv)
@@ -474,7 +514,8 @@ static int sohci_return_urb (struct ohci
 
 	/* just to be sure */
 	if (!urb->complete) {
-		urb_rm_priv (urb);
+		urb_rm_priv_locked (urb);
+		ohci_complete_add(hc, urb);	/* Just usb_dec_dev_use */
 		return -1;
 	}
 	
@@ -490,20 +531,18 @@ static int sohci_return_urb (struct ohci
 				usb_pipeout (urb->pipe)
 					? PCI_DMA_TODEVICE
 					: PCI_DMA_FROMDEVICE);
-
 			if (urb->interval) {
 				urb->complete (urb);
- 
+
 				/* implicitly requeued */
 				urb->actual_length = 0;
 				urb->status = -EINPROGRESS;
 				td_submit_urb (urb);
 			} else {
-				urb_rm_priv(urb);
-				urb->complete (urb);
+				urb_rm_priv_locked (urb);
+				ohci_complete_add(hc, urb);
 			}
-   			break;
-
+  			break;
   			
 		case PIPE_ISOCHRONOUS:
 			for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
@@ -515,7 +554,6 @@ static int sohci_return_urb (struct ohci
 						? PCI_DMA_TODEVICE
 						: PCI_DMA_FROMDEVICE);
 				urb->complete (urb);
-				spin_lock_irqsave (&usb_ed_lock, flags);
 				urb->actual_length = 0;
   				urb->status = USB_ST_URB_PENDING;
   				urb->start_frame = urb_priv->ed->last_iso + 1;
@@ -526,18 +564,17 @@ static int sohci_return_urb (struct ohci
   					}
   					td_submit_urb (urb);
   				}
-  				spin_unlock_irqrestore (&usb_ed_lock, flags);
-  				
+
   			} else { /* unlink URB, call complete */
-				urb_rm_priv (urb);
-				urb->complete (urb); 	
+				urb_rm_priv_locked (urb);
+				ohci_complete_add(hc, urb);
 			}		
 			break;
   				
 		case PIPE_BULK:
 		case PIPE_CONTROL: /* unlink URB, call complete */
-			urb_rm_priv (urb);
-			urb->complete (urb);	
+			urb_rm_priv_locked (urb);
+			ohci_complete_add(hc, urb);
 			break;
 	}
 	return 0;
@@ -574,20 +611,24 @@ static int sohci_submit_urb (struct urb 
 #ifdef DEBUG
 	urb_print (urb, "SUB", usb_pipein (pipe));
 #endif
-	
+
 	/* handle a request to the virtual root hub */
 	if (usb_pipedevice (pipe) == ohci->rh.devnum) 
 		return rh_submit_urb (urb);
-	
+
+	spin_lock_irqsave(&ohci->ohci_lock, flags);
+
 	/* when controller's hung, permit only roothub cleanup attempts
 	 * such as powering down ports */
 	if (ohci->disabled) {
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 		usb_dec_dev_use (urb->dev);	
 		return -ESHUTDOWN;
 	}
 
 	/* every endpoint has a ed, locate and fill it */
 	if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 		usb_dec_dev_use (urb->dev);	
 		return -ENOMEM;
 	}
@@ -609,6 +650,7 @@ static int sohci_submit_urb (struct urb 
 		case PIPE_ISOCHRONOUS: /* number of packets from URB */
 			size = urb->number_of_packets;
 			if (size <= 0) {
+				spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 				usb_dec_dev_use (urb->dev);	
 				return -EINVAL;
 			}
@@ -628,8 +670,9 @@ static int sohci_submit_urb (struct urb 
 
 	/* allocate the private part of the URB */
 	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), 
-							in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
+							GFP_ATOMIC);
 	if (!urb_priv) {
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 		usb_dec_dev_use (urb->dev);	
 		return -ENOMEM;
 	}
@@ -640,13 +683,12 @@ static int sohci_submit_urb (struct urb 
 	urb_priv->ed = ed;	
 
 	/* allocate the TDs (updating hash chains) */
-	spin_lock_irqsave (&usb_ed_lock, flags);
 	for (i = 0; i < size; i++) { 
 		urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
 		if (!urb_priv->td[i]) {
 			urb_priv->length = i;
 			urb_free_priv (ohci, urb_priv);
-			spin_unlock_irqrestore (&usb_ed_lock, flags);
+			spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 			usb_dec_dev_use (urb->dev);	
 			return -ENOMEM;
 		}
@@ -654,7 +696,7 @@ static int sohci_submit_urb (struct urb 
 
 	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
 		urb_free_priv (ohci, urb_priv);
-		spin_unlock_irqrestore (&usb_ed_lock, flags);
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 		usb_dec_dev_use (urb->dev);	
 		return -EINVAL;
 	}
@@ -676,7 +718,7 @@ static int sohci_submit_urb (struct urb 
 			}
 			if (bustime < 0) {
 				urb_free_priv (ohci, urb_priv);
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 				usb_dec_dev_use (urb->dev);	
 				return bustime;
 			}
@@ -719,7 +761,7 @@ static int sohci_submit_urb (struct urb 
 	}
 #endif
 
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
+	spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 
 	return 0;	
 }
@@ -750,6 +792,7 @@ static int sohci_unlink_urb (struct urb 
 	if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
 		return rh_unlink_urb (urb);
 
+	spin_lock_irqsave(&ohci->ohci_lock, flags);
 	if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { 
 		if (!ohci->disabled) {
 			urb_priv_t  * urb_priv;
@@ -759,6 +802,7 @@ static int sohci_unlink_urb (struct urb 
 			 */
 			if (!(urb->transfer_flags & USB_ASYNC_UNLINK)
 					&& in_interrupt ()) {
+				spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 				err ("bug in call from %p; use async!",
 					__builtin_return_address(0));
 				return -EWOULDBLOCK;
@@ -767,11 +811,10 @@ static int sohci_unlink_urb (struct urb 
 			/* flag the urb and its TDs for deletion in some
 			 * upcoming SF interrupt delete list processing
 			 */
-			spin_lock_irqsave (&usb_ed_lock, flags);
 			urb_priv = urb->hcpriv;
 
 			if (!urb_priv || (urb_priv->state == URB_DEL)) {
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 				return 0;
 			}
 				
@@ -786,7 +829,7 @@ static int sohci_unlink_urb (struct urb 
 
 				add_wait_queue (&unlink_wakeup, &wait);
 				urb_priv->wait = &unlink_wakeup;
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 
 				/* wait until all TDs are deleted */
 				set_current_state(TASK_UNINTERRUPTIBLE);
@@ -800,14 +843,22 @@ static int sohci_unlink_urb (struct urb 
 					err ("unlink URB timeout");
 					return -ETIMEDOUT;
 				}
+
+				usb_dec_dev_use (urb->dev);
+				urb->dev = NULL;
+				if (urb->complete)
+					urb->complete (urb); 
 			} else {
 				/* usb_dec_dev_use done in dl_del_list() */
 				urb->status = -EINPROGRESS;
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 				return -EINPROGRESS;
 			}
 		} else {
-			urb_rm_priv (urb);
+			urb_rm_priv_locked (urb);
+			spin_unlock_irqrestore(&ohci->ohci_lock, flags);
+			usb_dec_dev_use (urb->dev);
+			urb->dev = NULL;
 			if (urb->transfer_flags & USB_ASYNC_UNLINK) {
 				urb->status = -ECONNRESET;
 				if (urb->complete)
@@ -815,6 +866,8 @@ static int sohci_unlink_urb (struct urb 
 			} else 
 				urb->status = -ENOENT;
 		}	
+	} else {
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 	}	
 	return 0;
 }
@@ -857,7 +910,7 @@ static int sohci_free_dev (struct usb_de
 		 * (freeing all the TDs, unlinking EDs) but we need
 		 * to defend against bugs that prevent that.
 		 */
-		spin_lock_irqsave (&usb_ed_lock, flags);	
+		spin_lock_irqsave(&ohci->ohci_lock, flags);	
 		for(i = 0; i < NUM_EDS; i++) {
   			ed = &(dev->ed[i]);
   			if (ed->state != ED_NEW) {
@@ -872,7 +925,7 @@ static int sohci_free_dev (struct usb_de
   				cnt++;
   			}
   		}
-  		spin_unlock_irqrestore (&usb_ed_lock, flags);
+  		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
   		
 		/* if the controller is running, tds for those unlinked
 		 * urbs get freed by dl_del_list at the next SF interrupt
@@ -1206,17 +1259,12 @@ static ed_t * ep_add_ed (
 	td_t * td;
 	ed_t * ed_ret;
 	volatile ed_t * ed; 
-	unsigned long flags;
- 	
- 	
-	spin_lock_irqsave (&usb_ed_lock, flags);
 
 	ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | 
 			(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]);
 
 	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
 		/* pending delete request */
-		spin_unlock_irqrestore (&usb_ed_lock, flags);
 		return NULL;
 	}
 	
@@ -1229,7 +1277,6 @@ static ed_t * ep_add_ed (
 			/* out of memory */
 		        if (td)
 		            td_free(ohci, td);
-			spin_unlock_irqrestore (&usb_ed_lock, flags);
 			return NULL;
 		}
 		ed->hwTailP = cpu_to_le32 (td->td_dma);
@@ -1252,8 +1299,7 @@ static ed_t * ep_add_ed (
   		ed->int_period = interval;
   		ed->int_load = load;
   	}
-  	
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
+
 	return ed_ret; 
 }
 
@@ -1512,7 +1558,7 @@ static void dl_transfer_length(td_t * td
 
 /* handle an urb that is being unlinked */
 
-static void dl_del_urb (struct urb * urb)
+static void dl_del_urb (ohci_t *ohci, struct urb * urb)
 {
 	wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
 
@@ -1520,12 +1566,9 @@ static void dl_del_urb (struct urb * urb
 
 	if (urb->transfer_flags & USB_ASYNC_UNLINK) {
 		urb->status = -ECONNRESET;
-		if (urb->complete)
-			urb->complete (urb);
+		ohci_complete_add(ohci, urb);
 	} else {
 		urb->status = -ENOENT;
-		if (urb->complete)
-			urb->complete (urb);
 
 		/* unblock sohci_unlink_urb */
 		if (wait_head)
@@ -1544,10 +1587,7 @@ static td_t * dl_reverse_done_list (ohci
 	td_t * td_rev = NULL;
 	td_t * td_list = NULL;
   	urb_priv_t * urb_priv = NULL;
-  	unsigned long flags;
-  	
-  	spin_lock_irqsave (&usb_ed_lock, flags);
-  	
+
 	td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
 	ohci->hcca->done_head = 0;
 	
@@ -1573,7 +1613,6 @@ static td_t * dl_reverse_done_list (ohci
 		td_rev = td_list;
 		td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;	
 	}	
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
 	return td_list;
 }
 
@@ -1585,7 +1624,6 @@ static td_t * dl_reverse_done_list (ohci
  
 static void dl_del_list (ohci_t  * ohci, unsigned int frame)
 {
-	unsigned long flags;
 	ed_t * ed;
 	__u32 edINFO;
 	__u32 tdINFO;
@@ -1593,8 +1631,6 @@ static void dl_del_list (ohci_t  * ohci,
 	__u32 * td_p;
 	int ctrl = 0, bulk = 0;
 
-	spin_lock_irqsave (&usb_ed_lock, flags);
-
 	for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
 
 		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
@@ -1615,7 +1651,7 @@ static void dl_del_list (ohci_t  * ohci,
 
 				/* URB is done; clean up */
 				if (++(urb_priv->td_cnt) == urb_priv->length)
-					dl_del_urb (urb);
+					dl_del_urb (ohci, urb);
 			} else {
 				td_p = &td->hwNextTD;
 			}
@@ -1672,7 +1708,6 @@ static void dl_del_list (ohci_t  * ohci,
 	}
 
    	ohci->ed_rm_list[frame] = NULL;
-   	spin_unlock_irqrestore (&usb_ed_lock, flags);
 }
 
 
@@ -1689,9 +1724,7 @@ static void dl_done_list (ohci_t * ohci,
 	struct urb * urb;
 	urb_priv_t * urb_priv;
  	__u32 tdINFO, edHeadP, edTailP;
- 	
- 	unsigned long flags;
- 	
+ 
   	while (td_list) {
    		td_list_next = td_list->next_dl_td;
    		
@@ -1720,13 +1753,10 @@ static void dl_done_list (ohci_t * ohci,
   				urb->status = cc_to_error[cc];
   				sohci_return_urb (ohci, urb);
   			} else {
-				spin_lock_irqsave (&usb_ed_lock, flags);
-  				dl_del_urb (urb);
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
+  				dl_del_urb (ohci, urb);
 			}
   		}
   		
-  		spin_lock_irqsave (&usb_ed_lock, flags);
   		if (ed->state != ED_NEW) { 
   			edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
   			edTailP = le32_to_cpup (&ed->hwTailP);
@@ -1735,7 +1765,6 @@ static void dl_done_list (ohci_t * ohci,
      			if ((edHeadP == edTailP) && (ed->state == ED_OPER)) 
      				ep_unlink (ohci, ed);
      		}	
-     		spin_unlock_irqrestore (&usb_ed_lock, flags);
      	
     		td_list = td_list_next;
   	}  
@@ -1926,7 +1955,8 @@ static int rh_submit_urb (struct urb * u
 	int leni = urb->transfer_buffer_length;
 	int len = 0;
 	int status = TD_CC_NOERROR;
-	
+	unsigned long flags;
+
 	__u32 datab[4];
 	__u8  * data_buf = (__u8 *) datab;
 	
@@ -1935,13 +1965,16 @@ static int rh_submit_urb (struct urb * u
 	__u16 wIndex;
 	__u16 wLength;
 
+	spin_lock_irqsave(&ohci->ohci_lock, flags);
+
 	if (usb_pipeint(pipe)) {
 		ohci->rh.urb =  urb;
 		ohci->rh.send = 1;
 		ohci->rh.interval = urb->interval;
 		rh_init_int_timer(urb);
 		urb->status = cc_to_error [TD_CC_NOERROR];
-		
+
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 		return 0;
 	}
 
@@ -2113,6 +2146,7 @@ static int rh_submit_urb (struct urb * u
 #endif
 
 	urb->hcpriv = NULL;
+	spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 	usb_dec_dev_use (usb_dev);
 	urb->dev = NULL;
 	if (urb->complete)
@@ -2125,13 +2159,16 @@ static int rh_submit_urb (struct urb * u
 static int rh_unlink_urb (struct urb * urb)
 {
 	ohci_t * ohci = urb->dev->bus->hcpriv;
+	unsigned int flags;
  
+	spin_lock_irqsave(&ohci->ohci_lock, flags);
 	if (ohci->rh.urb == urb) {
 		ohci->rh.send = 0;
 		del_timer (&ohci->rh.rh_int_timer);
 		ohci->rh.urb = NULL;
 
 		urb->hcpriv = NULL;
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 		usb_dec_dev_use(urb->dev);
 		urb->dev = NULL;
 		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
@@ -2140,6 +2177,8 @@ static int rh_unlink_urb (struct urb * u
 				urb->complete (urb);
 		} else
 			urb->status = -ENOENT;
+	} else {
+		spin_unlock_irqrestore(&ohci->ohci_lock, flags);
 	}
 	return 0;
 }
@@ -2283,7 +2322,7 @@ static int hc_start (ohci_t * ohci)
 
 static void check_timeouts (struct ohci *ohci)
 {
-	spin_lock (&usb_ed_lock);
+	spin_lock (&ohci->ohci_lock);
 	while (!list_empty (&ohci->timeout_list)) {
 		struct urb	*urb;
 
@@ -2296,15 +2335,15 @@ static void check_timeouts (struct ohci 
 			continue;
 
 		urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
-		spin_unlock (&usb_ed_lock);
+		spin_unlock (&ohci->ohci_lock);
 
 		// outside the interrupt handler (in a timer...)
 		// this reference would race interrupts
 		sohci_unlink_urb (urb);
 
-		spin_lock (&usb_ed_lock);
+		spin_lock (&ohci->ohci_lock);
 	}
-	spin_unlock (&usb_ed_lock);
+	spin_unlock (&ohci->ohci_lock);
 }
 
 
@@ -2318,6 +2357,8 @@ static void hc_interrupt (int irq, void 
 	struct ohci_regs * regs = ohci->regs;
  	int ints; 
 
+	spin_lock (&ohci->ohci_lock);
+
 	/* avoid (slow) readl if only WDH happened */
 	if ((ohci->hcca->done_head != 0)
 			&& !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
@@ -2326,11 +2367,13 @@ static void hc_interrupt (int irq, void 
 	/* cardbus/... hardware gone before remove() */
 	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
 		ohci->disabled++;
+		spin_unlock (&ohci->ohci_lock);
 		err ("%s device removed!", ohci->ohci_dev->slot_name);
 		return;
 
 	/* interrupt for some other device? */
 	} else if ((ints &= readl (&regs->intrenable)) == 0) {
+		spin_unlock (&ohci->ohci_lock);
 		return;
 	} 
 
@@ -2381,6 +2424,13 @@ static void hc_interrupt (int irq, void 
 		}
 	}
 
+	/*
+	 * Finally, we are done with trashing about our hardware lists
+	 * and other CPUs are allowed in. The festive flipping of the lock
+	 * ensues as we struggle with the check_timeouts disaster.
+	 */
+	spin_unlock (&ohci->ohci_lock);
+
 	if (!list_empty (&ohci->timeout_list)) {
 		check_timeouts (ohci);
 // FIXME:  enable SF as needed in a timer;
@@ -2393,6 +2443,8 @@ static void hc_interrupt (int irq, void 
 	writel (ints, &regs->intrstatus);
 	writel (OHCI_INTR_MIE, &regs->intrenable);	
 	(void)readl (&regs->intrdisable); /* PCI posting flush */
+
+	ohci_complete(ohci);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2425,10 +2477,8 @@ static ohci_t * __devinit hc_alloc_ohci 
 	ohci->ohci_dev = dev;
 	pci_set_drvdata(dev, ohci);
  
-	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-	list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
-
 	INIT_LIST_HEAD (&ohci->timeout_list);
+	spin_lock_init(&ohci->ohci_lock);
 
 	ohci->bus = usb_alloc_bus (&sohci_device_operations);
 	if (!ohci->bus) {
@@ -2472,9 +2522,6 @@ static void hc_release_ohci (ohci_t * oh
 		usb_free_bus (ohci->bus);
 	}
 
-	list_del (&ohci->ohci_hcd_list);
-	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-
 	ohci_mem_cleanup (ohci);
     
 	/* unmap the IO address space */
@@ -2720,12 +2767,12 @@ ohci_pci_suspend (struct pci_dev *dev, u
 	ohci->sleeping = 1;
 
 	/* First stop processing */
-  	spin_lock_irqsave (&usb_ed_lock, flags);
+  	spin_lock_irqsave (&ohci->ohci_lock, flags);
 	ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
 	writel (ohci->hc_control, &ohci->regs->control);
 	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
 	(void) readl (&ohci->regs->intrstatus);
-  	spin_unlock_irqrestore (&usb_ed_lock, flags);
+  	spin_unlock_irqrestore (&ohci->ohci_lock, flags);
 
 	/* Wait a frame or two */
 	mdelay(1);
@@ -2851,7 +2898,7 @@ ohci_pci_resume (struct pci_dev *dev)
 		mdelay (3);
 
 		/* Then re-enable operations */
-		spin_lock_irqsave (&usb_ed_lock, flags);
+		spin_lock_irqsave (&ohci->ohci_lock, flags);
 		ohci->disabled = 0;
 		ohci->sleeping = 0;
 		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
@@ -2867,7 +2914,6 @@ ohci_pci_resume (struct pci_dev *dev)
 		/* Check for a pending done list */
 		writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);	
 		(void) readl (&ohci->regs->intrdisable);
-		spin_unlock_irqrestore (&usb_ed_lock, flags);
 #ifdef CONFIG_PMAC_PBOOK
 		if (_machine == _MACH_Pmac)
 			enable_irq (ohci->irq);
@@ -2877,6 +2923,7 @@ ohci_pci_resume (struct pci_dev *dev)
 		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
 		writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
 		writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+		spin_unlock_irqrestore (&ohci->ohci_lock, flags);
 		break;
 
 	default:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/host/usb-ohci.h linux-2.4.26-rc3/drivers/usb/host/usb-ohci.h
--- linux-2.4.25/drivers/usb/host/usb-ohci.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/host/usb-ohci.h	2004-04-12 19:01:16.000000000 +0000
@@ -384,12 +384,12 @@ typedef struct ohci {
 #define OHCI_QUIRK_SUCKYIO	0x02		/* NSC superio */
 
 	struct ohci_regs * regs;	/* OHCI controller's memory */
-	struct list_head ohci_hcd_list;	/* list of all ohci_hcd */
 
 	struct list_head timeout_list;
 	// struct list_head urb_list; 	// list of all pending urbs
-	// spinlock_t urb_list_lock; 	// lock to keep consistency 
-  
+	spinlock_t ohci_lock;		/* Covers all fields up & down */
+	struct urb *complete_head, *complete_tail;
+
 	int ohci_int_load[32];		/* load of the 32 Interrupt Chains (for load balancing)*/
 	ed_t * ed_rm_list[2];     /* lists of all endpoints to be removed */
 	ed_t * ed_bulktail;       /* last endpoint of bulk list */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/pegasus.h linux-2.4.26-rc3/drivers/usb/pegasus.h
--- linux-2.4.25/drivers/usb/pegasus.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/pegasus.h	2004-04-12 19:04:59.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-rc3/drivers/usb/printer.c
--- linux-2.4.25/drivers/usb/printer.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/printer.c	2004-04-12 19:01:12.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-rc3/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-rc3/drivers/usb/serial/ftdi_sio.c	2004-04-12 19:04:05.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,
@@ -1325,15 +1343,16 @@ static void ftdi_close (struct usb_seria
 			/* drop RTS */
 			if (set_rts(port, LOW) < 0) {
 				err("Error from RTS LOW urb");
-			}	
-			/* shutdown our bulk read */
-			if (port->read_urb) {
-				usb_unlink_urb (port->read_urb);	
 			}
-			/* unlink the running write urbs */
-			
-
 		} /* Note change no line is hupcl is off */
+
+		/* shutdown our bulk read */
+		if (port->read_urb) {
+			if(usb_unlink_urb (port->read_urb)<0)
+				err("Error unlinking urb");
+		}
+		/* unlink the running write urbs */
+
 	} /* if (serial->dev) */
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/serial/ftdi_sio.h linux-2.4.26-rc3/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-rc3/drivers/usb/serial/ftdi_sio.h	2004-04-12 19:04:29.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-rc3/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-rc3/drivers/usb/serial/io_edgeport.c	2004-04-12 19:00:35.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-rc3/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-rc3/drivers/usb/serial/pl2303.c	2004-04-12 19:02:42.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-rc3/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-rc3/drivers/usb/serial/visor.c	2004-04-12 19:01:49.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-rc3/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-rc3/drivers/usb/serial/visor.h	2004-04-12 19:01:41.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/datafab.c linux-2.4.26-rc3/drivers/usb/storage/datafab.c
--- linux-2.4.25/drivers/usb/storage/datafab.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/storage/datafab.c	2004-04-12 19:05:01.000000000 +0000
@@ -695,20 +695,24 @@ int datafab_transport(Scsi_Cmnd * srb, s
 	}
 
 	if (srb->cmnd[0] == READ_CAPACITY) {
+		unsigned int max_sector;
+
 		info->ssize = 0x200;  // hard coded 512 byte sectors as per ATA spec
 		rc = datafab_id_device(us, info);
 		if (rc != USB_STOR_TRANSPORT_GOOD)
 			return rc;
 
-		US_DEBUGP("datafab_transport:  READ_CAPACITY:  %ld sectors, %ld bytes per sector\n",
+		US_DEBUGP("datafab_transport:  READ_CAPACITY:  "
+			  "%ld sectors, %ld bytes per sector\n",
 			  info->sectors, info->ssize);
 
 		// build the reply
 		//
-		ptr[0] = (info->sectors >> 24) & 0xFF;
-		ptr[1] = (info->sectors >> 16) & 0xFF;
-		ptr[2] = (info->sectors >> 8) & 0xFF;
-		ptr[3] = (info->sectors) & 0xFF;
+		max_sector = info->sectors - 1;
+		ptr[0] = (max_sector >> 24) & 0xFF;
+		ptr[1] = (max_sector >> 16) & 0xFF;
+		ptr[2] = (max_sector >> 8) & 0xFF;
+		ptr[3] = (max_sector) & 0xFF;
 
 		ptr[4] = (info->ssize >> 24) & 0xFF;
 		ptr[5] = (info->ssize >> 16) & 0xFF;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/storage/scsiglue.c linux-2.4.26-rc3/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-rc3/drivers/usb/storage/scsiglue.c	2004-04-12 19:02:51.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-rc3/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-rc3/drivers/usb/storage/unusual_devs.h	2004-04-12 19:04:01.000000000 +0000
@@ -249,7 +249,7 @@ UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x
 UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100, 
 		"Sony",
 		"Memorystick NW-MS7",
-		US_SC_UFI, US_PR_CB, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 #ifdef CONFIG_USB_STORAGE_ISD200
@@ -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",
@@ -353,7 +360,7 @@ UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x
 UNUSUAL_DEV(  0x05dc, 0xb002, 0x0000, 0x0113,
 		"Lexar",
 		"USB CF Reader",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Reported by Carlos Villegas <cav@uniscope.co.jp>
@@ -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/usb/usbnet.c linux-2.4.26-rc3/drivers/usb/usbnet.c
--- linux-2.4.25/drivers/usb/usbnet.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/usbnet.c	2004-04-12 19:03:09.000000000 +0000
@@ -2594,7 +2594,11 @@ static const struct usb_device_id	produc
 	// Hawking UF200, TrendNet TU2-ET100
 	USB_DEVICE (0x07b8, 0x420a),
 	.driver_info =	(unsigned long) &hawking_uf200_info,
-}, 
+}, {
+	// ATEN UC210T
+	USB_DEVICE (0x0557, 0x2009),
+	.driver_info =  (unsigned long) &ax8817x_info,
+},
 #endif
 
 #ifdef	CONFIG_USB_BELKIN
@@ -2724,6 +2728,15 @@ static const struct usb_device_id	produc
 	.bInterfaceSubClass	= 0x0a,
 	.bInterfaceProtocol	= 0x00,
 	.driver_info =	(unsigned long) &zaurus_pxa_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x9032, /* SL-6000 */
+	.bInterfaceClass	= 0x02,
+	.bInterfaceSubClass	= 0x0a,
+	.bInterfaceProtocol	= 0x00,
+	.driver_info =	(unsigned long) &zaurus_pxa_info,
 },
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/usb/w9968cf.c linux-2.4.26-rc3/drivers/usb/w9968cf.c
--- linux-2.4.25/drivers/usb/w9968cf.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.26-rc3/drivers/usb/w9968cf.c	2004-04-12 19:02:13.000000000 +0000
@@ -2943,7 +2943,7 @@ static int w9968cf_open(struct inode* in
 		return -ENODEV;
 	}
 
-	if (cam->users) {
+	while (cam->users) {
 		DBG(2, "%s (/dev/video%d) has been already occupied by '%s'.",
 		    symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command)
 		if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
@@ -3632,7 +3632,7 @@ w9968cf_v4l_ioctl(struct inode* inode, s
 		if (copy_from_user(&tuner, arg, sizeof(tuner)))
 			return -EFAULT;
 
-		if (tuner.tuner != 0);
+		if (tuner.tuner != 0)
 			return -EINVAL;
 
 		strcpy(tuner.name, "no_tuner");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/amifb.c linux-2.4.26-rc3/drivers/video/amifb.c
--- linux-2.4.25/drivers/video/amifb.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.26-rc3/drivers/video/amifb.c	2004-04-12 19:04:30.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-rc3/drivers/video/pm3fb.c
--- linux-2.4.25/drivers/video/pm3fb.c	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.26-rc3/drivers/video/pm3fb.c	2004-04-12 19:03:03.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-rc3/drivers/video/radeonfb.c
--- linux-2.4.25/drivers/video/radeonfb.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.26-rc3/drivers/video/radeonfb.c	2004-04-12 19:04:58.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-rc3/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-rc3/drivers/video/sis/300vtbl.h	2004-04-12 19:01:06.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-rc3/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-rc3/drivers/video/sis/310vtbl.h	2004-04-12 19:03:21.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-rc3/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-rc3/drivers/video/sis/init.c	2004-04-12 19:01:40.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;
-        CRYPTO_HM    }54-        ca   breIS650740) {
+      if((ROMAddr[0x1a] ==09,0x5F,r,0x5F,r,0  } else >jChipType >= SIS_315H) {
    s asS_SetRegCND(SiS_Pr->SiS_P3c4,0x87SetCRT1CRTC(SiS_Private *SiS_Pr, USH
 
      temp = (SiS_Kr->CCRT1CRTC[17;
+     for(i = 0C13; i <= 0x14; i++) {
+        CRTCda8a = SiS_Pr->SiS_StandTable[StatPanelTypPr->SiS_32:];
+        SiS_SetReg(SiS_Pr->SiS_P3case PetReg(SiS_Pr->SiS_P3case PetReg(( (HwS_Pr->SiS_LCDACRT11024x768_2_H;   break;
-  _H;   break;
-        case Panel_1280x1024 +00000 +0tr = SiS_Pr gCND(SiS_Pr 	     eel_1400x105>el_1600x1200eak;
-        case Panel_1024x768  + 48: LCDACRT1Ptr = SiS, 0x10, 0x23, 0x42, 0x68, 0RT1Ptr = SiS_0x10, 0xe0DACRT11280x1024_2_H;  break;
-        case P0x68, 0x1a, 0x43, 
-0x0a, 0xe0,r = SiS_Pr->SiS_LCDACRT11400x1050_2_O01:16.000000000 +0000
@@ -384,12 +384,12 @@ t+	   (0ine	ga12 +_is== SIS_315_VGA) {
+	        if(VBFla]) % slave3¡C[17;5eg(SiS_Pr->SiS_P3case PetReg(SiS_Pr->SiS_P3case PetReg(( (HwS_Pr->SiPSI
SHORT *Display     caseRegReg(HwS_Pr->SiPSI
SHORT *Display     caseRegReg(HORT *Displ00x105>el_1600x12     caseRegReg(HORT *Displ00x105>el_1600x12     caPtr =Reg(HORT *Displ00x105>el_1600x12     caPtr =0x10, 0xe0DACRT11280x1024_2_H;  break;
-     x10, 0xe07