diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/Configure.help linux-2.4.26-pre1/Documentation/Configure.help --- linux-2.4.25/Documentation/Configure.help 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.26-pre1/Documentation/Configure.help 2004-02-25 15:45:02.000000000 +0000 @@ -6206,17 +6206,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 +6223,29 @@ CONFIG_SCTP_DBG_OBJCNT If unsure, say N +#choice +SCTP: HMAC algorithm +CONFIG_SCTP_HMAC_NONE + Choose an HMAC algorithm to be used during association establishment. + It can be one of SHA1, MD5 or NONE. It is advised to use either HMAC-MD5 + or HMAC-SHA1. + See configuration for Cryptographic API and enable these algorithms + to make usable by SCTP. + +SCTP: SHA1 HMAC algorithm +CONFIG_SCTP_HMAC_SHA1 + Enable the use of HMAC-SHA1 during association establishment. It + is advised to use either HMAC-MD5 or HMAC-SHA1. + See configuration for Cryptographic API and enable these algorithms + to make usable by SCTP. + +SCTP: MD5 HMAC algorithm +config SCTP_HMAC_MD5 + Enable the use of HMAC-MD5 during association establishment. It is + advised to use either HMAC-MD5 or HMAC-SHA1. + See configuration for Cryptographic API and enable these algorithms + to make usable by SCTP. + Kernel httpd acceleration CONFIG_KHTTPD The kernel httpd acceleration daemon (kHTTPd) is a (limited) web @@ -10237,6 +10249,19 @@ CONFIG_AIRO_CS say M here and read . The module will be called airo_cs.o. +Atmel at76c502/at76c504 PCMCIA cards +CONFIG_PCMCIA_ATMEL + A driver for PCMCIA 802.11 wireless cards based on the + Atmel fast-vnet chips. This driver supports standard + Linux wireless extensions. + + Many cards based on this chipset do not have flash memory + and need their firmware loaded at start-up. If yours is + one of these, you will need to provide a firmware image + to be loaded into the card by the driver. The Atmel + firmware package can be downloaded from + http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz + Aviator/Raytheon 2.4MHz wireless support CONFIG_PCMCIA_RAYCS Say Y here if you intend to attach an Aviator/Raytheon PCMCIA @@ -12358,6 +12383,16 @@ CONFIG_B44 . 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 + . + + To compile this driver as a module, choose M here and read + . 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 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Documentation/networking/bonding.txt linux-2.4.26-pre1/Documentation/networking/bonding.txt --- linux-2.4.25/Documentation/networking/bonding.txt 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.26-pre1/Documentation/networking/bonding.txt 2004-02-25 15:42:06.000000000 +0000 @@ -21,7 +21,7 @@ userspace tools, please follow the links Table of Contents ================= - + Installation Bond Configuration Module Parameters @@ -66,7 +66,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 +74,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 +113,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 +128,30 @@ 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 +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 +189,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 +202,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 +223,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 +247,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 +258,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 +273,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 +293,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 +317,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 +327,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 +363,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 +383,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 +515,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 +536,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 +591,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. @@ -622,8 +608,8 @@ Frequently Asked Questions 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 +622,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 +632,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,21 +653,21 @@ 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 @@ -729,27 +715,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 +747,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 +797,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 @@ -870,10 +856,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). +----------+ +----------+ @@ -957,7 +943,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-pre1/Documentation/networking/ifenslave.c --- linux-2.4.25/Documentation/networking/ifenslave.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.26-pre1/Documentation/networking/ifenslave.c 2004-02-25 15:41:41.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 ] > ... - * * Author: Donald Becker * 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 + * - 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] < [metric ] > ...\n" -" ifenslave -c master-interface slave-if\n"; +"Usage: ifenslave [-f] [...]\n" +" ifenslave -d [...]\n" +" ifenslave -c \n" +" ifenslave --help\n"; -static const char *howto_msg = -"Usage: ifenslave [-adfrvVh] < [metric ] > ...\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 netmask broadcast \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 @@ -153,476 +171,332 @@ typedef __uint8_t u8; /* ditto */ #include 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-pre1/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-pre1/Documentation/networking/ip-sysctl.txt 2004-02-25 15:42:53.000000000 +0000 @@ -481,6 +481,55 @@ arp_filter - BOOLEAN conf/{all,interface}/arp_filter is set to TRUE, it will be disabled otherwise +arp_announce - INTEGER + Define different restriction levels for announcing the local + source IP address from IP packets in ARP requests sent on + interface: + 0 - (default) Use any local address, configured on any interface + 1 - Try to avoid local addresses that are not in the target's + subnet for this interface. This mode is useful when target + hosts reachable via this interface require the source IP + address in ARP requests to be part of their logical network + configured on the receiving interface. When we generate the + request we will check all our subnets that include the + target IP and will preserve the source address if it is from + such subnet. If there is no such subnet we select source + address according to the rules for level 2. + 2 - Always use the best local address for this target. + In this mode we ignore the source address in the IP packet + and try to select local address that we prefer for talks with + the target host. Such local address is selected by looking + for primary IP addresses on all our subnets on the outgoing + interface that include the target IP address. If no suitable + local address is found we select the first local address + we have on the outgoing interface or on all other interfaces, + with the hope we will receive reply for our request and + even sometimes no matter the source IP address we announce. + + The max value from conf/{all,interface}/arp_announce is used. + + Increasing the restriction level gives more chance for + receiving answer from the resolved target while decreasing + the level announces more valid sender's information. + +arp_ignore - INTEGER + Define different modes for sending replies in response to + received ARP requests that resolve local target IP addresses: + 0 - (default): reply for any local target IP address, configured + on any interface + 1 - reply only if the target IP address is local address + configured on the incoming interface + 2 - reply only if the target IP address is local address + configured on the incoming interface and both with the + sender's IP address are part from same subnet on this interface + 3 - do not reply for local addresses configured with scope host, + only resolutions for global and link addresses are replied + 4-7 - reserved + 8 - do not reply for all local addresses + + The max value from conf/{all,interface}/arp_ignore is used + when ARP request is received on the {interface} + tag - INTEGER Allows you to write a number, which can be used as required. Default value is 0. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/MAINTAINERS linux-2.4.26-pre1/MAINTAINERS --- linux-2.4.25/MAINTAINERS 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.26-pre1/MAINTAINERS 2004-02-25 15:43:43.000000000 +0000 @@ -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 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/Makefile linux-2.4.26-pre1/Makefile --- linux-2.4.25/Makefile 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/Makefile 2004-02-25 15:44:02.000000000 +0000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 25 -EXTRAVERSION = +SUBLEVEL = 26 +EXTRAVERSION = -pre1 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -223,7 +223,8 @@ CLEAN_FILES = \ drivers/tc/lk201-map.c \ net/khttpd/make_times_h \ net/khttpd/times.h \ - submenu* + submenu* \ + drivers/ieee1394/oui.c # directories removed with 'make clean' CLEAN_DIRS = \ modules diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/defconfig linux-2.4.26-pre1/arch/i386/defconfig --- linux-2.4.25/arch/i386/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.26-pre1/arch/i386/defconfig 2004-02-25 15:41:22.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/i386_ksyms.c linux-2.4.26-pre1/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-pre1/arch/i386/kernel/i386_ksyms.c 2004-02-25 15:43:07.000000000 +0000 @@ -146,6 +146,10 @@ EXPORT_SYMBOL(smp_call_function); /* TLB flushing */ EXPORT_SYMBOL(flush_tlb_page); + +/* HT support */ +EXPORT_SYMBOL(smp_num_siblings); +EXPORT_SYMBOL(cpu_sibling_map); #endif #ifdef CONFIG_X86_IO_APIC diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/i386/kernel/microcode.c linux-2.4.26-pre1/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-pre1/arch/i386/kernel/microcode.c 2004-02-25 15:41:54.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 + * 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 #include #include +#include #include #include @@ -84,8 +89,8 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) mi MODULE_AUTHOR("Tigran Aivazian "); 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 = µcode_fops, }; +static devfs_handle_t devfs_handle; + static int __init microcode_init (void) { int error; error = misc_register(µcode_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, + µcode_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 \n", - MICROCODE_VERSION); - return 0; + "IA-32 Microcode Update Driver: v" + MICROCODE_VERSION " \n"); +out: + return error; } static void __exit microcode_exit (void) { misc_deregister(µcode_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/mm/init.c linux-2.4.26-pre1/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-pre1/arch/i386/mm/init.c 2004-02-25 15:44:20.000000000 +0000 @@ -510,7 +510,15 @@ void __init mem_init(void) if (!mem_map) BUG(); - +#ifdef CONFIG_HIGHMEM + /* check that fixmap and pkmap do not overlap */ + if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) { + printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n"); + printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n", + PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START); + BUG(); + } +#endif set_max_mapnr_init(); high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/arch/ia64/tools/Makefile linux-2.4.26-pre1/arch/ia64/tools/Makefile --- linux-2.4.25/arch/ia64/tools/Makefile 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.26-pre1/arch/ia64/tools/Makefile 2004-02-25 15:43:26.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/drivers/acpi/Config.in linux-2.4.26-pre1/drivers/acpi/Config.in --- linux-2.4.25/drivers/acpi/Config.in 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.26-pre1/drivers/acpi/Config.in 2004-02-25 15:44:45.000000000 +0000 @@ -25,9 +25,6 @@ if [ "$CONFIG_X86" = "y" ]; then tristate ' Fan' CONFIG_ACPI_FAN tristate ' Processor' CONFIG_ACPI_PROCESSOR dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR - if [ "$CONFIG_NUMA" = "y" -a "$CONFIG_X86_64" != "y" ]; then - dep_bool ' NUMA support' CONFIG_ACPI_NUMA $CONFIG_NUMA - fi tristate ' ASUS Laptop Extras' CONFIG_ACPI_ASUS tristate ' Toshiba Laptop Extras' CONFIG_ACPI_TOSHIBA bool ' Debug Statements' CONFIG_ACPI_DEBUG diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsmthdat.c linux-2.4.26-pre1/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-pre1/drivers/acpi/dispatcher/dsmthdat.c 2004-02-25 15:42:35.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-pre1/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-pre1/drivers/acpi/dispatcher/dsobject.c 2004-02-25 15:40:49.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-pre1/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-pre1/drivers/acpi/dispatcher/dsopcode.c 2004-02-25 15:44:38.000000000 +0000 @@ -243,8 +243,8 @@ acpi_ds_get_buffer_arguments ( node = obj_desc->buffer.node; if (!node) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "No pointer back to NS node in buffer %p\n", obj_desc)); + ACPI_REPORT_ERROR (( + "No pointer back to NS node in buffer obj %p\n", obj_desc)); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -290,7 +290,7 @@ acpi_ds_get_package_arguments ( node = obj_desc->package.node; if (!node) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + ACPI_REPORT_ERROR (( "No pointer back to NS node in package %p\n", obj_desc)); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/dispatcher/dsutils.c linux-2.4.26-pre1/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-pre1/drivers/acpi/dispatcher/dsutils.c 2004-02-25 15:43:07.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-pre1/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-pre1/drivers/acpi/dispatcher/dswstate.c 2004-02-25 15:44:45.000000000 +0000 @@ -328,7 +328,7 @@ acpi_ds_result_push ( state = walk_state->results; if (!state) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result stack frame\n")); + ACPI_REPORT_ERROR (("No result stack frame during push\n")); return (AE_AML_INTERNAL); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exconvrt.c linux-2.4.26-pre1/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-pre1/drivers/acpi/executer/exconvrt.c 2004-02-25 15:40:55.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/exfldio.c linux-2.4.26-pre1/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-pre1/drivers/acpi/executer/exfldio.c 2004-02-25 15:42:21.000000000 +0000 @@ -507,8 +507,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-pre1/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-pre1/drivers/acpi/executer/exmisc.c 2004-02-25 15:44:39.000000000 +0000 @@ -103,7 +103,7 @@ acpi_ex_get_object_reference ( default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference subtype %X\n", + ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n", obj_desc->reference.opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -121,8 +121,8 @@ acpi_ex_get_object_reference ( default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p has invalid descriptor [%s]\n", - obj_desc, acpi_ut_get_descriptor_name (obj_desc))); + ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n", + ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); return_ACPI_STATUS (AE_TYPE); } @@ -349,6 +349,8 @@ acpi_ex_do_concatenate ( /* Invalid object type, should not happen here */ + ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", + ACPI_GET_OBJECT_TYPE (obj_desc1))); status = AE_AML_INTERNAL; return_desc = NULL; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exoparg2.c linux-2.4.26-pre1/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-pre1/drivers/acpi/executer/exoparg2.c 2004-02-25 15:43:24.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-pre1/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-pre1/drivers/acpi/executer/exprep.c 2004-02-25 15:41:43.000000000 +0000 @@ -507,7 +507,7 @@ acpi_ex_prep_field_value ( (info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width)); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n")); + ACPI_REPORT_ERROR (("Null Index Object during field prep\n")); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exresolv.c linux-2.4.26-pre1/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-pre1/drivers/acpi/executer/exresolv.c 2004-02-25 15:42:43.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-pre1/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-pre1/drivers/acpi/executer/exresop.c 2004-02-25 15:44:49.000000000 +0000 @@ -154,7 +154,7 @@ acpi_ex_resolve_operands ( arg_types = op_info->runtime_args; if (arg_types == ARGI_INVALID_OPCODE) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - %X is not a valid AML opcode\n", + ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n", opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); @@ -172,7 +172,7 @@ acpi_ex_resolve_operands ( */ while (GET_CURRENT_ARG_TYPE (arg_types)) { if (!stack_ptr || !*stack_ptr) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null stack entry at %p\n", + ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n", stack_ptr)); return_ACPI_STATUS (AE_AML_INTERNAL); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/executer/exstore.c linux-2.4.26-pre1/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-pre1/drivers/acpi/executer/exstore.c 2004-02-25 15:42:53.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-pre1/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-pre1/drivers/acpi/executer/exstoren.c 2004-02-25 15:41:17.000000000 +0000 @@ -112,6 +112,12 @@ acpi_ex_resolve_object ( } } + /* For copy_object, no further validation necessary */ + + if (walk_state->opcode == AML_COPY_OP) { + break; + } + /* * Must have a Integer, Buffer, or String */ @@ -136,7 +142,7 @@ acpi_ex_resolve_object ( /* * Aliases are resolved by acpi_ex_prep_operands */ - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into Alias - should never happen\n")); + ACPI_REPORT_ERROR (("Store into Alias - should never happen\n")); status = AE_AML_INTERNAL; break; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/namespace/nsaccess.c linux-2.4.26-pre1/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-pre1/drivers/acpi/namespace/nsaccess.c 2004-02-25 15:45:11.000000000 +0000 @@ -314,7 +314,7 @@ acpi_ns_lookup ( else { prefix_node = scope_info->scope.node; if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p Not a namespace node [%s]\n", + ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name (prefix_node))); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/acpi/parser/psargs.c linux-2.4.26-pre1/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-pre1/drivers/acpi/parser/psargs.c 2004-02-25 15:42:18.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/system.c linux-2.4.26-pre1/drivers/acpi/system.c --- linux-2.4.25/drivers/acpi/system.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.26-pre1/drivers/acpi/system.c 2004-02-25 15:42:45.000000000 +0000 @@ -95,6 +95,7 @@ acpi_power_off (void) { if (unlikely(in_interrupt())) BUG(); + 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/i2c/Config.in linux-2.4.26-pre1/drivers/i2c/Config.in --- linux-2.4.25/drivers/i2c/Config.in 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.26-pre1/drivers/i2c/Config.in 2004-02-25 15:45:13.000000000 +0000 @@ -12,7 +12,7 @@ if [ "$CONFIG_I2C" != "n" ]; then dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT $CONFIG_PARPORT dep_tristate ' ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT dep_tristate ' Velleman K8000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT - dep_tristate ' NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200 $CONFIG_I2C_ALGOBIT + dep_tristate ' NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200_GPIO $CONFIG_I2C_ALGOBIT if [ "$CONFIG_SCx200_I2C" != "n" ]; then int ' GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12 int ' GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ide/ide-proc.c linux-2.4.26-pre1/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-pre1/drivers/ide/ide-proc.c 2004-02-25 15:40:57.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/generic.h linux-2.4.26-pre1/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-pre1/drivers/ide/pci/generic.h 2004-02-25 15:41:37.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/siimage.c linux-2.4.26-pre1/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-pre1/drivers/ide/pci/siimage.c 2004-02-25 15:44:38.000000000 +0000 @@ -62,6 +62,7 @@ static int pdev_is_sata(struct pci_dev * return 0; } BUG(); + return 0; } /** diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/ieee1394/dma.c linux-2.4.26-pre1/drivers/ieee1394/dma.c --- linux-2.4.25/drivers/ieee1394/dma.c 2003-08-25 11:44:41.000000000 +0000 +++ linux-2.4.26-pre1/drivers/ieee1394/dma.c 2004-02-25 15:42:34.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-pre1/drivers/ieee1394/video1394.c --- linux-2.4.25/drivers/ieee1394/video1394.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.26-pre1/drivers/ieee1394/video1394.c 2004-02-25 15:41:34.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/isdn/avmb1/capidrv.c linux-2.4.26-pre1/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-pre1/drivers/isdn/avmb1/capidrv.c 2004-02-25 15:42:55.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-pre1/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-pre1/drivers/isdn/avmb1/kcapi.c 2004-02-25 15:44:34.000000000 +0000 @@ -546,7 +546,13 @@ static int notify_push(unsigned int cmd, static void notify_up(__u32 contr) { struct capi_interface_user *p; + __u16 appl; + for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { + if (!VALID_APPLID(appl)) continue; + if (APPL(appl)->releasing) continue; + CARD(contr)->driver->register_appl(CARD(contr), appl, &APPL(appl)->rparam); + } printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr); spin_lock(&capi_users_lock); for (p = capi_users; p; p = p->next) { @@ -714,12 +720,16 @@ static void controllercb_appl_released(s nextpp = &(*pp)->next; } } - APPL(appl)->releasing--; - if (APPL(appl)->releasing <= 0) { - APPL(appl)->signal = 0; - APPL_MARK_FREE(appl); - printk(KERN_INFO "kcapi: appl %d down\n", appl); - } + if (APPL(appl)->releasing) { /* only release if the application was marked for release */ + printk(KERN_DEBUG "kcapi: appl %d releasing(%d)\n", appl, APPL(appl)->releasing); + APPL(appl)->releasing--; + if (APPL(appl)->releasing <= 0) { + APPL(appl)->signal = 0; + APPL_MARK_FREE(appl); + printk(KERN_INFO "kcapi: appl %d down\n", appl); + } + } else + printk(KERN_WARNING "kcapi: appl %d card%d released without request\n", appl, card->cnr); } /* * ncci management @@ -872,16 +882,7 @@ error: static void controllercb_ready(struct capi_ctr * card) { - __u16 appl; - card->cardstate = CARD_RUNNING; - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - if (!VALID_APPLID(appl)) continue; - if (APPL(appl)->releasing) continue; - card->driver->register_appl(card, appl, &APPL(appl)->rparam); - } - printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", CARDNR(card), card->name); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/isdn/hisax/isurf.c linux-2.4.26-pre1/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-pre1/drivers/isdn/hisax/isurf.c 2004-02-25 15:43:30.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/media/video/Config.in linux-2.4.26-pre1/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-pre1/drivers/media/video/Config.in 2004-02-25 15:43:31.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-pre1/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-pre1/drivers/media/video/meye.c 2004-02-25 15:43:40.000000000 +0000 @@ -188,23 +188,29 @@ 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 corectness 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 +218,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 +239,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 +251,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-pre1/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-pre1/drivers/media/video/meye.h 2004-02-25 15:43:29.000000000 +0000 @@ -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/Config.in linux-2.4.26-pre1/drivers/net/Config.in --- linux-2.4.25/drivers/net/Config.in 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/Config.in 2004-02-25 15:43:51.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-pre1/drivers/net/Makefile --- linux-2.4.25/drivers/net/Makefile 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/Makefile 2004-02-25 15:42:12.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-pre1/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-pre1/drivers/net/bonding/bond_3ad.c 2004-02-25 15:44:49.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. + * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -47,8 +47,13 @@ * - Send LACPDU as highest priority packet to further fix the above * problem on very high Tx traffic load where packets may get dropped * by the slave. + * + * 2003/12/01 - Shmulik Hen + * - Code cleanup and style changes */ +//#define BONDING_DEBUG 1 + #include #include #include @@ -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,27 @@ 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; - 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 free_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 free_out; } slaves_in_agg = ad_info.ports; @@ -2399,21 +2383,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 free_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,37 +2397,18 @@ 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 free_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; @@ -2463,20 +2419,24 @@ int bond_3ad_xmit_xor(struct sk_buff *sk skb->dev = slave->dev; skb->priority = 1; dev_queue_xmit(skb); - read_unlock(&bond->lock); - return 0; + + goto out; } - } while ((slave = slave->next) != start_at); + } - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); +out: read_unlock(&bond->lock); return 0; + +free_out: + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + goto out; } 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-pre1/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-pre1/drivers/net/bonding/bond_3ad.h 2004-02-25 15:42:51.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 * - Renamed bond_3ad_link_status_changed() to * bond_3ad_handle_link_change() for compatibility with TLB. + * + * 2003/12/01 - Shmulik Hen + * - 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-pre1/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-pre1/drivers/net/bonding/bond_alb.c 2004-02-25 15:42:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. + * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -28,8 +28,16 @@ * 2003/08/06 - Amir Noam * - Add support for setting bond's MAC address with special * handling required for ALB/TLB. + * + * 2003/12/01 - Shmulik Hen + * - Code cleanup and style changes + * + * 2003/12/30 - Amir Noam + * - Fixed: Cannot remove and re-enslave the original active slave. */ +//#define BONDING_DEBUG 1 + #include #include #include @@ -50,11 +58,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,7 +74,7 @@ #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 ! */ @@ -86,12 +94,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 +121,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; iload_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; itx_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 +313,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 +326,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 +349,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 +418,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,23 +480,24 @@ 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; iip_dst, client_info->slave->dev, @@ -561,20 +509,14 @@ rlb_update_client(struct rlb_client_info } /* 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 +537,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 +568,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 +603,22 @@ 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 bonding *bond, struct arp_pkt *arp) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - struct rlb_client_info *client_info = NULL; + 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 +631,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,8 +657,7 @@ 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; } @@ -760,10 +680,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; @@ -776,9 +695,8 @@ rlb_arp_xmit(struct sk_buff *skb, struct 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 @@ -797,34 +715,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 +752,84 @@ 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; irx_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; + _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 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_RETRY; i++) { + struct sk_buff *skb; + char *data; + skb = dev_alloc_skb(size); if (!skb) { return; @@ -937,28 +837,26 @@ 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; + 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 +867,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 +900,7 @@ alb_swap_mac_addr(struct bonding *bond, */ rlb_req_update_slave_clients(bond, slave1); } - } - else { + } else { disabled_slave = slave1; } @@ -1018,15 +912,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 +937,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 +946,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 +993,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 +1008,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 +1097,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 +1134,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 +1172,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 +1183,38 @@ 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; - } - - /* 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 free_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 +1222,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 +1232,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 +1244,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,16 +1262,16 @@ 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); } else { @@ -1387,26 +1279,35 @@ bond_alb_xmit(struct sk_buff *skb, struc if (tx_slave) { tlb_clear_slave(bond, tx_slave, 0); } - dev_kfree_skb(skb); + goto free_out; } - read_unlock(&bond->ptrlock); +out: + read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); return 0; + +free_out: + dev_kfree_skb(skb); + goto out; } -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 +1315,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 +1369,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 +1395,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 +1419,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 +1440,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 +1455,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,109 +1479,111 @@ 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); } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/bonding/bond_alb.h linux-2.4.26-pre1/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-pre1/drivers/net/bonding/bond_alb.h 2004-02-25 15:43:40.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 * - Add support for setting bond's MAC address with special * handling required for ALB/TLB. + * + * 2003/12/01 - Shmulik Hen + * - Code cleanup and style changes */ #ifndef __BOND_ALB_H__ @@ -126,10 +129,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); #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-pre1/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-pre1/drivers/net/bonding/bond_main.c 2004-02-25 15:42:41.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 * - Ported to 2.4 Kernel - * + * * 2001/5/2 - Jeffrey E. Mast * - 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 - * - 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 * - Added /proc support for getting bond and slave information. - * Information is in /proc/net//info. + * Information is in /proc/net//info. * - Changed the locking when calling bond_close to prevent deadlock. * * 2001/8/05 - Janice Girouard @@ -144,8 +144,8 @@ * but only for an up link. * * 2001/9/20 - Chad N. Tindel - * - 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 @@ -155,10 +155,10 @@ * - Various memory leak fixes * * 2001/11/5 - Mark Huth - * - 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 - * - 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 * - 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 * - 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 @@ -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 * - 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 - * - 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 * - 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,45 @@ * - 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 + * - Fix /proc creation/destruction. + * + * 2003/12/01 - Shmulik Hen + * - 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 + * - 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 + * - Save bonding parameters per bond instead of using the global values. */ +//#define BONDING_DEBUG 1 + #include #include #include @@ -452,7 +489,6 @@ #include #include #include - #include #include #include @@ -461,58 +497,71 @@ #include #include #include - -#include #include #include #include #include #include +#include #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 +570,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 +592,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; (idev, - 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,149 +620,7 @@ bond_mode_name(void) } } -static const char * -multicast_mode_name(void) -{ - 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"; - } -} - -void bond_set_slave_inactive_flags(slave_t *slave) -{ - slave->state = BOND_STATE_BACKUP; - slave->dev->flags |= IFF_NOARP; -} - -void bond_set_slave_active_flags(slave_t *slave) -{ - slave->state = BOND_STATE_ACTIVE; - slave->dev->flags &= ~IFF_NOARP; -} - -/* - * 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. - */ -static inline void -update_slave_cnt(bonding_t *bond, int incr) -{ - slave_t *slave = NULL; - int expect = bond->slave_cnt + incr; - - bond->slave_cnt = 0; - for (slave = bond->prev; slave != (slave_t*)bond; - slave = slave->prev) { - bond->slave_cnt++; - } - - if (expect != bond->slave_cnt) - BUG(); -} - -/* - * This function detaches the slave from the list . - * WARNING: no check is made to verify if the slave effectively - * belongs to . It returns in case it's needed. - * Nothing is freed on return, structures are just unchained. - * If the bond->current_slave pointer was pointing to , - * it should be changed by the calling function. - * - * bond->lock held for writing by caller. - */ -static slave_t * -bond_detach_slave(bonding_t *bond, slave_t *slave) -{ - 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; - } - } - - update_slave_cnt(bond, -1); - - return slave; -} - -/* - * This function attaches the slave to the list . - * - * bond->lock held for writing by caller. - */ -static void -bond_attach_slave(struct bonding *bond, struct slave *new_slave) -{ - /* - * 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; - - update_slave_cnt(bond, 1); -} - - -/* - * 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; }) +/*------------------------------- Link status -------------------------------*/ /* * Get link speed and duplex from the slave's base driver @@ -809,52 +630,63 @@ bond_attach_slave(struct bonding *bond, */ static int bond_update_speed_duplex(struct slave *slave) { - struct net_device *dev = slave->dev; + struct net_device *slave_dev = slave->dev; static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct ethtool_cmd etool; - 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; + /* Fake speed and duplex */ + slave->speed = SPEED_100; + slave->duplex = DUPLEX_FULL; + + if (slave_dev->ethtool_ops) { + u32 res; + + if (!slave_dev->ethtool_ops->get_settings) { + return -1; } - } else { - goto err_out; + + res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); + if (res < 0) { + return -1; + } + + goto verify; } - switch (slave->speed) { - case SPEED_10: - case SPEED_100: - case SPEED_1000: - break; - default: - goto err_out; + 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; } - switch (slave->duplex) { - case DUPLEX_FULL: - case DUPLEX_HALF: - break; - default: - goto err_out; + switch (etool.duplex) { + case DUPLEX_FULL: + case DUPLEX_HALF: + break; + default: + return -1; } - return 0; + slave->speed = etool.speed; + slave->duplex = etool.duplex; -err_out: - /* Fake speed and duplex */ - slave->speed = SPEED_100; - slave->duplex = DUPLEX_FULL; - return -1; + return 0; } -/* +/* * if supports MII link status reporting, check its link status. * * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(), @@ -870,19 +702,18 @@ err_out: * 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 net_device *dev, int reporting) +static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting) { static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; struct ethtool_value etool; - if (use_carrier) { - return netif_carrier_ok(dev) ? BMSR_LSTATUS : 0; + if (bond->params.use_carrier) { + return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; } - ioctl = dev->do_ioctl; + 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 */ @@ -897,478 +728,509 @@ bond_check_dev_link(struct net_device *d */ /* 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(dev, &ifr, SIOCGMIIPHY) == 0) { + if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) { mii->reg_num = MII_BMSR; - if (IOCTL(dev, &ifr, SIOCGMIIREG) == 0) { - return mii->val_out & BMSR_LSTATUS; + if (IOCTL(slave_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... */ + if (slave_dev->ethtool_ops) { + if (slave_dev->ethtool_ops->get_link) { + u32 link; + + link = slave_dev->ethtool_ops->get_link(slave_dev); + + return link ? BMSR_LSTATUS : 0; + } + } - /* 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 (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 { -#ifdef BONDING_DEBUG - printk(KERN_INFO - ":: SIOCETHTOOL shows link down \n"); -#endif + } else { + dprintk("SIOCETHTOOL shows link down\n"); 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; + return (reporting ? -1 : BMSR_LSTATUS); } -static u16 bond_check_mii_link(bonding_t *bond) -{ - int has_active_interface = 0; - - 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); +/*----------------------------- Multicast list ------------------------------*/ - return (has_active_interface ? BMSR_LSTATUS : 0); +/* + * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise + */ +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; } -/* register to receive lacpdus on a bond */ -static void bond_register_lacpdu(struct bonding *bond) +/* + * 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 packet_type* pk_type = &(BOND_AD_INFO(bond).ad_pkt_type); + struct dev_mc_list *idmi; - /* 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 */ + for (idmi = mc_list; idmi; idmi = idmi->next) { + if (bond_is_dmi_same(dmi, idmi)) { + return idmi; + } + } - dev_add_pack(pk_type); + return NULL; } -/* unregister to receive lacpdus on a bond */ -static void bond_unregister_lacpdu(struct bonding *bond) +/* + * Push the promiscuity flag down to appropriate slaves + */ +static void bond_set_promiscuity(struct bonding *bond, int inc) { - dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); + 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); + } + } } -static int bond_open(struct net_device *dev) +/* + * Push the allmulti flag down to all slaves + */ +static void bond_set_allmulti(struct bonding *bond, int inc) { - 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; - - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { - struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer); - - /* 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 */ - return -1; + 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); } - - 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); } +} - 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); - } - - 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 a Multicast address to slaves + * according to mode + */ +static void bond_mc_add(struct bonding *bond, void *addr, int alen) +{ + if (USES_PRIMARY(bond->params.mode)) { + /* write lock already acquired */ + 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); } - add_timer(arp_timer); - } - - 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); } - - return 0; } -static int bond_close(struct net_device *master) +/* + * Remove a multicast address from slave + * according to mode + */ +static void bond_mc_delete(struct bonding *bond, void *addr, int alen) { - bonding_t *bond = (struct bonding *) master->priv; - - write_lock_bh(&bond->lock); - - 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 (USES_PRIMARY(bond->params.mode)) { + /* write lock already acquired */ + 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); } } +} - if (bond_mode == BOND_MODE_8023AD) { - del_timer_sync(&(BOND_AD_INFO(bond).ad_timer)); +/* + * Totally destroys the mc_list in bond + */ +static void bond_mc_list_destroy(struct bonding *bond) +{ + struct dev_mc_list *dmi; - /* Unregister the receive of LACPDUs */ - bond_unregister_lacpdu(bond); + dmi = bond->mc_list; + while (dmi) { + bond->mc_list = dmi->next; + kfree(dmi); + dmi = bond->mc_list; } +} - bond_mc_list_destroy (bond); - - write_unlock_bh(&bond->lock); +/* + * Copy all the Multicast addresses from src to the bonding device dst + */ +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; - /* Release the bonded slaves */ - bond_release_all(master); + for (dmi = mc_list; dmi; dmi = dmi->next) { + new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag); - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { - del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer)); + if (!new_dmi) { + /* FIXME: Potential memory leak !!! */ + return -ENOMEM; + } - bond_alb_deinitialize(bond); + 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; } return 0; } -/* +/* * flush all members of flush->mc_list from device dev->mc_list */ -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 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; - if (bond_mode == BOND_MODE_8023AD) { + for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { + dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); + } + + 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(dev, lacpdu_multicast, ETH_ALEN, 0); + dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0); } } +/*--------------------------- Active slave change ---------------------------*/ + /* - * Totally destroys the mc_list in bond + * 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 void bond_mc_list_destroy(struct bonding *bond) +static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active) { struct dev_mc_list *dmi; - dmi = bond->mc_list; - while (dmi) { - bond->mc_list = dmi->next; - kfree(dmi); - dmi = bond->mc_list; - } -} - -/* - * Add a Multicast address to every slave in the bonding group - */ -static void bond_mc_add(bonding_t *bond, void *addr, int alen) -{ - slave_t *slave; - switch (multicast_mode) { - case BOND_MULTICAST_ACTIVE : - /* 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) - dev_mc_add(slave->dev, addr, alen, 0); - break; - case BOND_MULTICAST_DISABLED : - break; + if (!USES_PRIMARY(bond->params.mode)) { + /* nothing to do - mc list is already up-to-date on + * all slaves + */ + return; } -} -/* - * Remove a multicast address from every slave in the bonding group - */ -static void bond_mc_delete(bonding_t *bond, void *addr, int alen) -{ - slave_t *slave; - switch (multicast_mode) { - case BOND_MULTICAST_ACTIVE : - /* 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) - dev_mc_delete(slave->dev, addr, alen, 0); - break; - case BOND_MULTICAST_DISABLED : - break; - } -} + if (old_active) { + if (bond->dev->flags & IFF_PROMISC) { + dev_set_promiscuity(old_active->dev, -1); + } -/* - * 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) -{ - struct dev_mc_list *dmi, *new_dmi; + if (bond->dev->flags & IFF_ALLMULTI) { + dev_set_allmulti(old_active->dev, -1); + } - for (dmi = src; dmi != NULL; dmi = dmi->next) { - new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag); + for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { + dev_mc_delete(old_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); + } + } - if (new_dmi == NULL) { - return -ENOMEM; + if (new_active) { + if (bond->dev->flags & IFF_PROMISC) { + dev_set_promiscuity(new_active->dev, 1); } - new_dmi->next = dst->mc_list; - dst->mc_list = new_dmi; + if (bond->dev->flags & IFF_ALLMULTI) { + dev_set_allmulti(new_active->dev, 1); + } - 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; - } - return 0; + for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { + dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); + } + } } -/* - * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise +/** + * 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 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; -} +static struct slave *bond_find_best_slave(struct bonding *bond) +{ + struct slave *new_active, *old_active; + struct slave *bestslave = NULL; + int mintime = bond->params.updelay; + int i; -/* - * Push the promiscuity flag down to appropriate slaves - */ -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); - } + new_active = old_active = bond->curr_active_slave; - } else { - for (slave = bond->prev; slave != (slave_t*)bond; - slave = slave->prev) { - dev_set_promiscuity(slave->dev, inc); + 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 */ } } -} -/* - * 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; + /* 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 ((bond->primary_slave) && + (!bond->params.arp_interval) && + (IS_UP(bond->primary_slave->dev))) { + new_active = bond->primary_slave; } -} -/* - * 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; + /* remember where to stop iterating over the slaves */ + old_active = new_active; - for (idmi = mc_list; idmi != NULL; idmi = idmi->next) { - if (dmi_same(dmi, idmi)) { - return idmi; + 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 NULL; -} -static void set_multicast_list(struct net_device *master) + 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) { - bonding_t *bond = master->priv; - struct dev_mc_list *dmi; + struct slave *old_active = bond->curr_active_slave; - write_lock_bh(&bond->lock); + if (old_active == new_active) { + return; + } - /* - * Do promisc before checking multicast_mode - */ - if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) ) - bond_set_promiscuity(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); + } - if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) ) - bond_set_promiscuity(bond, -1); + new_active->delay = 0; + new_active->link = BOND_LINK_UP; + new_active->jiffies = jiffies; - if (multicast_mode == BOND_MULTICAST_DISABLED) { - bond->flags = master->flags; - write_unlock_bh(&bond->lock); - return; + if (bond->params.mode == BOND_MODE_8023AD) { + bond_3ad_handle_link_change(new_active, BOND_LINK_UP); + } + + 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); + } + } } - /* set allmulti flag to slaves */ - if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) ) - bond_set_allmulti(bond, 1); + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { + if (old_active) { + bond_set_slave_inactive_flags(old_active); + } + + if (new_active) { + bond_set_slave_active_flags(new_active); + } + } - if ( !(master->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI) ) - bond_set_allmulti(bond, -1); + if (USES_PRIMARY(bond->params.mode)) { + bond_mc_swap(bond, new_active, old_active); + } - bond->flags = master->flags; + 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; + } +} - /* 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); - } +/** + * 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; - /* 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); + best_slave = bond_find_best_slave(bond); + if (best_slave != bond->curr_active_slave) { + bond_change_active_slave(bond, best_slave); } +} +/*--------------------------- slave list handling ---------------------------*/ - /* save master's multicast list */ - bond_mc_list_destroy (bond); - bond_mc_list_copy (master->mc_list, bond, GFP_ATOMIC); +/* + * This function attaches the slave to the end of list. + * + * bond->lock held for writing by caller. + */ +static void bond_attach_slave(struct bonding *bond, struct slave *new_slave) +{ + 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; + } - write_unlock_bh(&bond->lock); + bond->slave_cnt++; } /* - * 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 detaches the slave from the list. + * WARNING: no check is made to verify if the slave effectively + * belongs to . + * Nothing is freed on return, structures are just unchained. + * If any slave pointer in bond was pointing to , + * it should be changed by the calling function. + * + * bond->lock held for writing by caller. */ -static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old) +static void bond_detach_slave(struct bonding *bond, struct slave *slave) { - struct dev_mc_list *dmi; + if (slave->next) { + slave->next->prev = slave->prev; + } - 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); - } + if (slave->prev) { + slave->prev->next = slave->next; } - 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 (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 to bond device */ -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 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; } @@ -1377,19 +1239,19 @@ static int bond_enslave(struct net_devic * slave interface to be closed. */ if ((slave_dev->flags & IFF_UP)) { -#ifdef BONDING_DEBUG - printk(KERN_CRIT "Error, slave_dev is up\n"); -#endif + printk(KERN_ERR DRV_NAME + ": Error: %s is up\n", + slave_dev->name); return -EPERM; } 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; } @@ -1398,26 +1260,29 @@ static int bond_enslave(struct net_devic * 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 + printk(KERN_ERR DRV_NAME + ": Error: %s is not running\n", + slave_dev->name); return -EINVAL; } - 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()); + 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)); return -EOPNOTSUPP; } } - if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) { + new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); + if (!new_slave) { return -ENOMEM; } - 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 +1296,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,40 +1328,40 @@ 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; @@ -1512,15 +1369,16 @@ static int bond_enslave(struct net_devic } 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 +1387,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 +1530,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,227 +1576,12 @@ err_restore_mac: err_free: kfree(new_slave); - return err; -} - -/* - * This function changes the active slave to slave . - * It returns -EINVAL in the following cases. - * - is not found in the list. - * - There is not active slave now. - * - is already active. - * - The link state of is not BOND_LINK_UP. - * - 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_change_active(struct net_device *master_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; - } - - /* Verify that master_dev is indeed the master of slave_dev */ - if (!(slave_dev->flags & IFF_SLAVE) || - (slave_dev->master != master_dev)) { - - 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; - } - - if ((newactive != NULL)&& - (oldactive != NULL)&& - (newactive->link == BOND_LINK_UP)&& - IS_UP(newactive->dev)) { - change_active_interface(bond, newactive); - } else { - ret = -EINVAL; - } - 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; - - newslave = oldslave = bond->current_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 */ - } - } - - mintime = updelay; - - /* 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; - } - - /* 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 (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_mode == BOND_MODE_ACTIVEBACKUP) { - if (old) { - bond_set_slave_inactive_flags(old); - } - - if (new) { - bond_set_slave_active_flags(new); - } - } - - 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); - } + return res; } /* * Try to release the slave device from the bond device - * It is legal to access current_slave without a lock because all the function + * 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: @@ -1972,206 +1590,196 @@ static void reselect_active_interface(st * 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) +static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) { - bonding_t *bond; - slave_t *our_slave, *old_current; + struct bonding *bond = bond_dev->priv; + struct slave *slave, *oldcurrent; struct sockaddr addr; - - if (master == NULL || slave == NULL) { - return -ENODEV; + int mac_addr_differ; + + /* slave is not a slave or master is not master of this slave */ + if (!(slave_dev->flags & IFF_SLAVE) || + (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->priv; + write_lock_bh(&bond->lock); - /* 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); + 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; } - 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); - } + 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); + } - /* 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 DRV_NAME + ": %s: releasing %s interface %s\n", + bond_dev->name, + (slave->state == BOND_STATE_ACTIVE) + ? "active" : "backup", + slave_dev->name); - printk (KERN_INFO "%s: releasing %s interface %s\n", - master->name, - (our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup", - slave->name); + oldcurrent = bond->curr_active_slave; - /* release the slave from its bond */ - bond_detach_slave(bond, our_slave); + bond->current_arp_slave = NULL; - if (bond->primary_slave == our_slave) { - bond->primary_slave = NULL; - } + /* release the slave from its bond */ + bond_detach_slave(bond, slave); - if (bond->current_slave == our_slave) { - change_active_interface(bond, NULL); - reselect_active_interface(bond); - } + if (bond->primary_slave == slave) { + bond->primary_slave = NULL; + } - if (bond->current_slave == NULL) { - printk(KERN_INFO - "%s: now running without any active interface !\n", - master->name); - } + if (oldcurrent == slave) { + bond_change_active_slave(bond, NULL); + } - 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); - } + 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); + } - break; - } + if (oldcurrent == slave) { + bond_select_active_slave(bond); + if (!bond->curr_active_slave) { + printk(KERN_INFO DRV_NAME + ": %s: now running without any active " + "interface !\n", + bond_dev->name); + } } + 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); + /* 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); } - } - /* 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 (bond_dev->flags & IFF_ALLMULTI) { + dev_set_allmulti(slave_dev, -1); + } - /* 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); + kfree(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); + if (bond->slave_cnt == 0) { + memset(bond_dev->dev_addr, 0, bond_dev->addr_len); } 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 +1788,23 @@ 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); + /* 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); + } + + /* unset allmulti level from slave */ + if (bond_dev->flags & IFF_ALLMULTI) { + dev_set_allmulti(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); + /* flush master's mc_list from slave */ + bond_mc_list_flush(bond_dev, slave_dev); } netdev_set_master(slave_dev, NULL); @@ -2203,7 +1814,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 +1822,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,72 +1836,240 @@ 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); - 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 . + * It returns -EINVAL in the following cases. + * - is not found in the list. + * - There is not active slave now. + * - is already active. + * - The link state of is not BOND_LINK_UP. + * - 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; - - read_lock(&bond->lock); - - /* 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. - */ - - slave = (slave_t *)bond; + struct bonding *bond = bond_dev->priv; + struct slave *old_active = NULL; + struct slave *new_active = NULL; + int res = 0; - read_lock(&bond->ptrlock); - oldcurrent = bond->current_slave; - read_unlock(&bond->ptrlock); + if (!USES_PRIMARY(bond->params.mode)) { + return -EINVAL; + } - while ((slave = slave->prev) != (slave_t *)bond) { - struct net_device *dev = slave->dev; + /* Verify that master_dev is indeed the master of slave_dev */ + if (!(slave_dev->flags & IFF_SLAVE) || + (slave_dev->master != bond_dev)) { + return -EINVAL; + } + + write_lock_bh(&bond->lock); + + old_active = bond->curr_active_slave; + new_active = bond_get_slave_by_dev(bond, slave_dev); + + /* + * Changing to the current active: do nothing; return success. + */ + if (new_active && (new_active == old_active)) { + write_unlock_bh(&bond->lock); + return 0; + } + + 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; + } + + write_unlock_bh(&bond->lock); + + return res; +} + +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 (get_user(cmd, (uint32_t *)addr)) { + return -EFAULT; + } + + 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(dev, 0); + + 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 */ + } else { /* link going down */ slave->link = BOND_LINK_FAIL; - slave->delay = downdelay; + slave->delay = bond->params.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); - } + + 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 @@ -2301,35 +2080,35 @@ static void bond_mii_monitor(struct net_ 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)) { + if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) || + (bond->params.mode == BOND_MODE_8023AD)) { bond_set_slave_inactive_flags(slave); } - printk(KERN_INFO - "%s: link status definitely down " - "for interface %s, disabling it", - master->name, - dev->name); + 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_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { bond_3ad_handle_link_change(slave, BOND_LINK_DOWN); } - 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_DOWN); } if (slave == oldcurrent) { do_failover = 1; } - - slave_died = 1; } else { slave->delay--; } @@ -2337,12 +2116,12 @@ static void bond_mii_monitor(struct net_ /* 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 +2130,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 +2151,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 +2165,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 +2176,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 +2201,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. + * 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) +static void bond_loadbalance_arp_mon(struct net_device *bond_dev) { - bonding_t *bond; - slave_t *slave, *oldcurrent; - int the_delta_in_ticks = arp_interval * HZ / 1000; - int next_timer = jiffies + (arp_interval * HZ / 1000); + 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 +2330,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 +2570,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; -} +/*------------------------------ proc/seq_file-------------------------------*/ -static int bond_info_query(struct net_device *master, struct ifbond *info) -{ - bonding_t *bond = (struct bonding *) master->priv; - slave_t *slave; +#ifdef CONFIG_PROC_FS + +#define SEQ_START_TOKEN ((void *)1) - info->bond_mode = bond_mode; - info->num_slaves = 0; - info->miimon = miimon; +static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) +{ + 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; slave = slave->prev) { - info->num_slaves++; + + if (*pos == 0) { + return SEQ_START_TOKEN; } - read_unlock_bh(&bond->lock); - return 0; + bond_for_each_slave(bond, slave, i) { + if (++off == *pos) { + return slave; + } + } + + return NULL; } -static int bond_slave_info_query(struct net_device *master, - struct ifslave *info) +static void *bond_info_seq_next(struct seq_file *seq, void *v, 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; + struct slave *slave = v; - read_lock_bh(&bond->lock); - for (slave = bond->prev; - slave != (slave_t *)bond && cur_ndx < info->slave_id; - slave = slave->prev) { - cur_ndx++; + ++*pos; + if (v == SEQ_START_TOKEN) { + return bond->first_slave; } - 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; - } + slave = slave->next; - return 0; + return (slave == bond->first_slave) ? NULL : slave; } -static int bond_ethtool_ioctl(struct net_device *master_dev, struct ifreq *ifr) +static void bond_info_seq_stop(struct seq_file *seq, void *v) { - void *addr = ifr->ifr_data; - uint32_t cmd; - - if (get_user(cmd, (uint32_t *) addr)) - return -EFAULT; + struct bonding *bond = seq->private; - switch (cmd) { + read_unlock_bh(&bond->lock); + read_unlock(&dev_base_lock); +} - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info; - char *endptr; - - if (copy_from_user(&info, addr, sizeof(info))) - return -EFAULT; - - if (strcmp(info.driver, "ifenslave") == 0) { - int new_abi_ver; +static void bond_info_show_master(struct seq_file *seq) +{ + struct bonding *bond = seq->private; + struct slave *curr; - 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_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"); - return -EINVAL; - } + seq_printf(seq, "Currently Active Slave: %s\n", + (curr) ? curr->dev->name : "None"); + } - if (orig_app_abi_ver == -1) { - orig_app_abi_ver = new_abi_ver; - } + 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); - app_abi_ver = new_abi_ver; - } + if (bond->params.mode == BOND_MODE_8023AD) { + struct ad_info ad_info; - strncpy(info.driver, DRV_NAME, 32); - strncpy(info.version, DRV_VERSION, 32); - snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); + seq_puts(seq, "\n802.3ad info\n"); + seq_printf(seq, "LACP rate: %s\n", + (bond->params.lacp_fast) ? "fast" : "slow"); - if (copy_to_user(addr, &info, sizeof(info))) - return -EFAULT; + 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"); - return 0; + 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); - break; - case BOND_CHANGE_ACTIVE_OLD: - case SIOCBONDCHANGEACTIVE: - if (USES_PRIMARY(bond_mode)) { - ret = bond_change_active(master_dev, slave_dev); - } - else { - ret = -EINVAL; - } - break; - default: - ret = -EOPNOTSUPP; - } - dev_put(slave_dev); - } +static int bond_create_proc_entry(struct bonding *bond) +{ + struct net_device *bond_dev = bond->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. - */ - orig_app_abi_ver = prev_abi_ver; + 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 ret; + return 0; } -#ifdef CONFIG_NET_FASTROUTE -static int bond_accept_fastpath(struct net_device *dev, struct dst_entry *dst) +static void bond_remove_proc_entry(struct bonding *bond) { - return -1; + 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; + } } -#endif -/* - * in broadcast mode, we send everything to all usable interfaces. +/* Create the bonding directory under /proc/net, if doesn't exist yet. + * Caller must hold rtnl_lock. */ -static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *dev) +static void bond_create_proc_dir(void) { - slave_t *slave, *start_at; - struct bonding *bond = (struct bonding *) dev->priv; - struct net_device *device_we_should_send_to = 0; + int len = strlen(DRV_NAME); - if (!IS_UP(dev)) { /* bond down */ - dev_kfree_skb(skb); - return 0; + 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; + } } - read_lock(&bond->lock); + 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); + } + } +} - read_lock(&bond->ptrlock); - slave = start_at = bond->current_slave; - read_unlock(&bond->ptrlock); - - 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; +/* 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; } - 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; - } + /* verify that the /proc dir is empty */ + for (de = bond_proc_dir->subdir; de; de = de->next) { + /* ignore . and .. */ + if (*(de->name) != '.') { + break; + } + } - skb2->dev = device_we_should_send_to; - skb2->priority = 1; - dev_queue_xmit(skb2); - } - device_we_should_send_to = slave->dev; + if (de) { + if (bond_proc_dir->owner == THIS_MODULE) { + bond_proc_dir->owner = NULL; } - } while ((slave = slave->next) != start_at); + } else { + remove_proc_entry(DRV_NAME, proc_net); + bond_proc_dir = NULL; + } +} +#endif /* CONFIG_PROC_FS */ - 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); +/*-------------------------- netdev event handling --------------------------*/ - /* frame sent to all suitable interfaces */ - read_unlock(&bond->lock); - return 0; +/* + * 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? + */ + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev) +{ + 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; } -static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev) +/* + * 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_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 *event_dev = (struct net_device *)ptr; - if (!IS_UP(dev)) { /* bond down */ - dev_kfree_skb(skb); - return 0; + 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); } - read_lock(&bond->lock); - - read_lock(&bond->ptrlock); - slave = start_at = bond->current_slave; - read_unlock(&bond->ptrlock); - - 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; + if (event_dev->flags & IFF_SLAVE) { + dprintk("IFF_SLAVE\n"); + return bond_slave_netdev_event(event, event_dev); } - do { - if (IS_UP(slave->dev) - && (slave->link == BOND_LINK_UP) - && (slave->state == BOND_STATE_ACTIVE)) { + return NOTIFY_DONE; +} - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); +static struct notifier_block bond_netdev_notifier = { + .notifier_call = bond_netdev_event, +}; - write_lock(&bond->ptrlock); - bond->current_slave = slave->next; - write_unlock(&bond->ptrlock); +/*-------------------------- Packet type handling ---------------------------*/ - read_unlock(&bond->lock); - return 0; - } - } while ((slave = slave->next) != start_at); +/* 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); - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - read_unlock(&bond->lock); - return 0; + /* 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 */ + + dev_add_pack(pk_type); } -/* - * 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) +/* unregister to receive lacpdus on a bond */ +static void bond_unregister_lacpdu(struct bonding *bond) { - slave_t *slave, *start_at; - struct bonding *bond = (struct bonding *) dev->priv; - struct ethhdr *data = (struct ethhdr *)skb->data; - int slave_no; + dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); +} - if (!IS_UP(dev)) { /* bond down */ - dev_kfree_skb(skb); - return 0; - } +/*-------------------------- Device entry points ----------------------------*/ - read_lock(&bond->lock); - slave = bond->prev; +static int bond_open(struct net_device *bond_dev) +{ + struct bonding *bond = bond_dev->priv; + struct timer_list *mii_timer = &bond->mii_timer; + struct timer_list *arp_timer = &bond->arp_timer; - /* 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; - } + bond->kill_timers = 0; - slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt; + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { + struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer); - while ( (slave_no > 0) && (slave != (slave_t *)bond) ) { - slave = slave->prev; - slave_no--; - } - start_at = slave; + /* 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; + } - do { - if (IS_UP(slave->dev) - && (slave->link == BOND_LINK_UP) - && (slave->state == BOND_STATE_ACTIVE)) { + 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); + } - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); + 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 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) +static int bond_close(struct net_device *bond_dev) { - struct bonding *bond = (struct bonding *) dev->priv; - int ret; + struct bonding *bond = bond_dev->priv; - if (!IS_UP(dev)) { /* bond down */ - dev_kfree_skb(skb); - return 0; - } + write_lock_bh(&bond->lock); - /* 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); + bond_mc_list_destroy(bond); + + if (bond->params.mode == BOND_MODE_8023AD) { + /* Unregister the receive of LACPDUs */ + bond_unregister_lacpdu(bond); } - /* 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. + /* signal timers not to re-arm */ + bond->kill_timers = 1; + + write_unlock_bh(&bond->lock); + + /* del_timer_sync must run without holding the bond->lock + * because a running timer might be trying to hold it too */ - 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); - } + + if (bond->params.miimon) { /* link check interval, in milliseconds. */ + del_timer_sync(&bond->mii_timer); } - read_lock(&bond->lock); + if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ + del_timer_sync(&bond->arp_timer); + } - 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; + 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; } - else { - read_unlock(&bond->ptrlock); + + /* Release the bonded slaves */ + bond_release_all(bond_dev); + + 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 +3199,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 +3491,394 @@ 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; + + read_lock(&bond->lock); + + if (!BOND_IS_OK(bond)) { + goto free_out; + } - for (slave = slave->next; slave != bond->next; - slave = slave->next) { - int tmp_error; + read_lock(&bond->curr_slave_lock); + slave = start_at = bond->curr_active_slave; + read_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); + if (!slave) { + goto free_out; + } + + 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)) { + skb->dev = slave->dev; + skb->priority = 1; + dev_queue_xmit(skb); + + write_lock(&bond->curr_slave_lock); + bond->curr_active_slave = slave->next; + write_unlock(&bond->curr_slave_lock); + + goto out; } } - return error; +out: + read_unlock(&bond->lock); + return 0; + +free_out: + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + goto out; } /* - * 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; - 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 free_out; + } + + if (bond->curr_active_slave) { /* one usable interface */ + skb->dev = bond->curr_active_slave->dev; + skb->priority = 1; + dev_queue_xmit(skb); + goto out; + } else { + goto free_out; + } +out: + read_unlock(&bond->curr_slave_lock); + read_unlock(&bond->lock); return 0; +free_out: + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + goto out; +} -unwind: - for (slave = slave->next; slave != bond->next; - slave = slave->next) { +/* + * 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; - if (slave->dev->change_mtu) { - slave->dev->change_mtu(slave->dev, dev->mtu); - } else { - slave->dev->mtu = dev->mtu; + read_lock(&bond->lock); + + if (!BOND_IS_OK(bond)) { + goto free_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)) { + skb->dev = slave->dev; + skb->priority = 1; + dev_queue_xmit(skb); + + goto out; } } - return error; +out: + read_unlock(&bond->lock); + return 0; + +free_out: + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + goto out; } /* - * 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; - 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 free_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 free_out; + } + + 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; + } + + skb2->dev = tx_dev; + skb2->priority = 1; + dev_queue_xmit(skb2); + } + tx_dev = slave->dev; } } - if (event_bond == NULL) { - return NOTIFY_DONE; + if (tx_dev) { + skb->dev = tx_dev; + skb->priority = 1; + dev_queue_xmit(skb); + } else { + goto free_out; } - switch (event) { - case NETDEV_CHANGENAME: - return bond_event_changename(event_bond); - case NETDEV_UNREGISTER: - /* - * TODO: remove a bond from the list? - */ - break; - default: - break; - } +out: + /* frame sent to all suitable interfaces */ + read_unlock(&bond->lock); + return 0; - return NOTIFY_DONE; +free_out: + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + goto out; } -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; + + /* 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; + + +#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 +3890,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 +3902,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 ; countbond_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 +3924,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(¶ms); + 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 +4206,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, ¶ms); + 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 +4233,7 @@ out_err: rtnl_unlock(); - return err; + return res; } static void __exit bonding_exit(void) @@ -4362,6 +4249,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 +4259,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-pre1/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-pre1/drivers/net/bonding/bonding.h 2004-02-25 15:42:46.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 , * Tsippy Mendelson and @@ -22,159 +22,220 @@ * * 2003/05/01 - Shmulik Hen * - Added support for Transmit load balancing mode. + * + * 2003/12/01 - Shmulik Hen + * - Code cleanup and style changes */ - + #ifndef _LINUX_BONDING_H #define _LINUX_BONDING_H #include #include +#include #include "bond_3ad.h" #include "bond_alb.h" -#ifdef BONDING_DEBUG +#define DRV_VERSION "2.5.4" +#define DRV_RELDATE "December 30, 2003" +#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 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; +}; /** * 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; - - /* check if the list of slaves is empty */ - if (our_slave == (slave_t *)bond) { - return NULL; - } + struct slave *slave = NULL; + int i; - 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; } #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-pre1/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-pre1/drivers/net/e1000/e1000.h 2004-02-25 15:42:35.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-pre1/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-pre1/drivers/net/e1000/e1000_ethtool.c 2004-02-25 15:44:03.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-pre1/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-pre1/drivers/net/e1000/e1000_hw.c 2004-02-25 15:44:06.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-pre1/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-pre1/drivers/net/e1000/e1000_hw.h 2004-02-25 15:41: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 @@ -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-pre1/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-pre1/drivers/net/e1000/e1000_main.c 2004-02-25 15:42:49.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-pre1/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-pre1/drivers/net/e1000/e1000_osdep.h 2004-02-25 15:42:10.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-pre1/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-pre1/drivers/net/e1000/e1000_param.c 2004-02-25 15:41:27.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-pre1/drivers/net/forcedeth.c --- linux-2.4.25/drivers/net/forcedeth.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/forcedeth.c 2004-02-25 15:41:02.000000000 +0000 @@ -0,0 +1,1576 @@ +/* + * 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 + * + * 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 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, 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 (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 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 + * + * 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.23" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 + + 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; + + /* 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 start_rx(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 *base = get_hwbase(dev); + + dprintk(KERN_DEBUG "%s: 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 stop_rx(struct net_device *dev) +{ + u8 *base = get_hwbase(dev); + + dprintk(KERN_DEBUG "%s: 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 "stop_rx: ReceiverStatus remained busy"); + + udelay(NV_RXSTOP_DELAY2); + writel(0, base + NvRegLinkSpeed); +} + +static void start_tx(struct net_device *dev) +{ + u8 *base = get_hwbase(dev); + + dprintk(KERN_DEBUG "%s: start_tx\n", dev->name); + writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl); + pci_push(base); +} + +static void stop_tx(struct net_device *dev) +{ + u8 *base = get_hwbase(dev); + + dprintk(KERN_DEBUG "%s: 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 "stop_tx: TransmitterStatus remained busy"); + + udelay(NV_TXSTOP_DELAY2); + writel(0, base + NvRegUnknownTransmitterReg); +} + +static void txrx_reset(struct net_device *dev) +{ + u8 *base = get_hwbase(dev); + + dprintk(KERN_DEBUG "%s: 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); + u32 ethcmd; + + if (copy_from_user(ðcmd, 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; + } + + 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; + } +} + +/* + * 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 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: 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 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 (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 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 alloc_rx(dev); +} + +static void 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 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) +{ + drain_tx(dev); + 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; +} + +/* + * tx_done: check for completed packets, release the skbs. + * + * Caller must own np->lock. + */ +static void 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: 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 */ + stop_tx(dev); + + /* 2) check that the packets were not sent already: */ + 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); + 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 */ + start_tx(dev); + spin_unlock_irq(&np->lock); +} + +static void 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: 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: 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); + 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); + start_rx(dev); + spin_unlock_irq(&np->lock); +} + +static int 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: 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 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) { + update_linkspeed(dev); + + if (netif_carrier_ok(dev)) { + 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); + start_rx(dev); + } else { + if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); + printk(KERN_INFO "%s: link down.\n", dev->name); + stop_rx(dev); + } + writel(np->linkspeed, base + NvRegLinkSpeed); + pci_push(base); + } +} + +static irqreturn_t 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: 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); + tx_done(dev); + spin_unlock(&np->lock); + } + + if (events & (NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)) { + rx_process(dev); + if (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); + 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 nic_irq.\n", dev->name, i); + spin_unlock(&np->lock); + break; + } + + } + dprintk(KERN_DEBUG "%s: nic_irq completed\n", dev->name); + + return IRQ_RETVAL(i); +} + +static void 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); + /* + * reenable interrupts on the nic, we have to do this before calling + * nic_irq because that may decide to do otherwise + */ + writel(np->irqmask, base + NvRegIrqMask); + pci_push(base); + 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); + txrx_reset(dev); + writel(0, base + NvRegUnknownSetupReg6); + + /* 2) initialize descriptor rings */ + np->in_shutdown = 0; + oom = 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); + 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, &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); + start_rx(dev); + 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); + stop_tx(dev); + 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); + + /* 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 = &do_rx_refill; /* timer handler */ + init_timer(&np->nic_poll); + np->nic_poll.data = (unsigned long) dev; + np->nic_poll.function = &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]); + + 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 "); +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-pre1/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-pre1/drivers/net/ibm_emac/ibm_emac.h 2004-02-25 15:43:27.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-pre1/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-pre1/drivers/net/ibm_emac/ibm_ocp_enet.c 2004-02-25 15:40:58.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-pre1/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-pre1/drivers/net/ibm_emac/ibm_ocp_mal.c 2004-02-25 15:42:45.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/sis900.c linux-2.4.26-pre1/drivers/net/sis900.c --- linux-2.4.25/drivers/net/sis900.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/sis900.c 2004-02-25 15:42:53.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-pre1/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-pre1/drivers/net/sk98lin/h/lm80.h 2004-02-25 15:44:48.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: lm80.h * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.6 $ - * Date: $Date: 2003/05/13 17:26:52 $ * Purpose: Contains all defines for the LM80 Chip * (National Semiconductor). * @@ -23,32 +21,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * $Log: lm80.h,v $ - * Revision 1.6 2003/05/13 17:26:52 mkarl - * Editorial changes. - * - * Revision 1.5 2003/03/31 07:15:18 mkarl - * Corrected Copyright. - * Editorial changes. - * - * Revision 1.4 2002/04/25 11:04:10 rschmidt - * Editorial changes - * - * Revision 1.3 1999/11/22 13:41:19 cgoos - * Changed license header to GPL. - * - * Revision 1.2 1999/03/12 13:26:51 malthoff - * remove __STDC__. - * - * Revision 1.1 1998/06/19 09:28:31 malthoff - * created. - * - * - ******************************************************************************/ - #ifndef __INC_LM80_H #define __INC_LM80_H diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skaddr.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/skaddr.h 2004-02-25 15:43:27.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-pre1/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-pre1/drivers/net/sk98lin/h/skcsum.h 2004-02-25 15:41:01.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-pre1/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-pre1/drivers/net/sk98lin/h/skdebug.h 2004-02-25 15:43:24.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-pre1/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-pre1/drivers/net/sk98lin/h/skdrv1st.h 2004-02-25 15:40:46.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-pre1/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-pre1/drivers/net/sk98lin/h/skdrv2nd.h 2004-02-25 15:45:18.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skdrv2nd.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/12/11 16:04:45 $ * Purpose: Second header file for driver and all other modules * ******************************************************************************/ @@ -24,122 +22,6 @@ /****************************************************************************** * - * History: - * - * $Log: skdrv2nd.h,v $ - * Revision 1.10 2003/12/11 16:04:45 mlindner - * Add: New pnmi data backup structure - * - * Revision 1.9 2003/11/10 09:31:37 rroesler - * Add: pnmiBackup structure for DIAG backup restore - * - * Revision 1.8 2003/10/22 14:18:32 rroesler - * Fix: DIAG handling for DualNet cards - * - * Revision 1.7 2003/10/07 09:34:59 mlindner - * Add: New defines for lower and upper range values (interrupt moderation) - * - * Revision 1.6 2003/10/07 08:16:51 mlindner - * Fix: Copyright changes - * - * Revision 1.5 2003/09/01 13:10:39 rroesler - * Add: Prototypes for DIAG Attach/Detach functions - * - * Revision 1.4 2003/09/01 12:33:38 rroesler - * Add: Defines for optimized DIAG interaction - * - * Revision 1.3 2003/08/12 16:51:18 mlindner - * Fix: UDP and TCP Proto checks - * Fix: UDP header offset - * - * Revision 1.2 2003/08/07 10:50:54 mlindner - * Add: Speed and HW-Csum support for Yukon Lite chipset - * - * Revision 1.1 2003/07/21 07:25:29 rroesler - * Fix: Re-Enter after CVS crash - * - * Revision 1.19 2003/07/07 09:53:10 rroesler - * Fix: Removed proprietary RxTx defines and used the ones from skgehw.h instead - * - * Revision 1.18 2003/06/12 07:54:14 mlindner - * Fix: Changed Descriptor Alignment to 64 Byte - * - * Revision 1.17 2003/05/26 12:56:39 mlindner - * Add: Support for Kernel 2.5/2.6 - * Add: New SkOsGetTimeCurrent function - * Add: SK_PNMI_HUNDREDS_SEC definition - * Fix: SK_TICKS_PER_SEC on Intel Itanium2 - * - * Revision 1.16 2003/03/21 14:56:18 rroesler - * Added code regarding interrupt moderation - * - * Revision 1.15 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.14 2003/02/25 13:26:26 mlindner - * Add: Support for various vendors - * - * Revision 1.13 2002/10/02 12:46:02 mlindner - * Add: Support for Yukon - * - * Revision 1.12.2.2 2001/09/05 12:14:50 mlindner - * add: New hardware revision int - * - * Revision 1.12.2.1 2001/03/12 16:50:59 mlindner - * chg: kernel 2.4 adaption - * - * Revision 1.12 2001/03/01 12:52:15 mlindner - * Fixed ring size - * - * Revision 1.11 2001/02/19 13:28:02 mlindner - * Changed PNMI parameter values - * - * Revision 1.10 2001/01/22 14:16:04 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * Revision 1.1 2000/10/05 19:46:50 phargrov - * Add directory src/vipk_devs_nonlbl/vipk_sk98lin/ - * This is the SysKonnect SK-98xx Gigabit Ethernet driver, - * contributed by SysKonnect. - * - * Revision 1.9 2000/02/21 10:39:55 cgoos - * Added flag for jumbo support usage. - * - * Revision 1.8 1999/11/22 13:50:44 cgoos - * Changed license header to GPL. - * Fixed two comments. - * - * Revision 1.7 1999/09/28 12:38:21 cgoos - * Added CheckQueue to SK_AC. - * - * Revision 1.6 1999/07/27 08:04:05 cgoos - * Added checksumming variables to SK_AC. - * - * Revision 1.5 1999/03/29 12:33:26 cgoos - * Rreversed to fine lock granularity. - * - * Revision 1.4 1999/03/15 12:14:02 cgoos - * Added DriverLock to SK_AC. - * Removed other locks. - * - * Revision 1.3 1999/03/01 08:52:27 cgoos - * Changed pAC->PciDev declaration. - * - * Revision 1.2 1999/02/18 10:57:14 cgoos - * Removed SkDrvTimeStamp prototype. - * Fixed SkGeOsGetTime prototype. - * - * Revision 1.1 1999/02/16 07:41:01 cgoos - * First version. - * - * - * - ******************************************************************************/ - -/****************************************************************************** - * * Description: * * This is the second include file of the driver, which includes all other diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skerror.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/skerror.h 2004-02-25 15:43:16.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-pre1/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-pre1/drivers/net/sk98lin/h/skgedrv.h 2004-02-25 15:43:56.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-pre1/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-pre1/drivers/net/sk98lin/h/skgehw.h 2004-02-25 15:45:11.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skgehw.h * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.56 $ - * Date: $Date: 2003/09/23 09:01:00 $ * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family * ******************************************************************************/ @@ -22,236 +20,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * $Log: skgehw.h,v $ - * Revision 1.56 2003/09/23 09:01:00 malthoff - * Minor change: Define I2C device size constants as long. - * - * Revision 1.55 2003/09/16 14:03:34 rschmidt - * Added define for YUKON-Lite Rev. A1,A2 Chip Revision - * Moved defines for PHY power down modes to skgeinit.h - * Editorial changes - * - * Revision 1.54 2003/09/16 07:37:58 mschmid - * Added defines for Marvell PHY low power modes - * - * Revision 1.53 2003/07/04 12:39:01 rschmidt - * Added SK_FAR to pointers in XM_IN32() and GM_IN32() macros (for PXE) - * Editorial changes - * - * Revision 1.52 2003/05/13 17:16:36 mkarl - * Added SK_FAR for PXE. - * Editorial changes. - * - * Revision 1.51 2003/04/08 16:31:50 rschmidt - * Added defines for new Chip IDs (YUKON-Lite, YUKON-LP) - * Editorial changes - * - * Revision 1.50 2003/03/31 07:29:45 mkarl - * Corrected Copyright. - * Editorial changes. - * - * Revision 1.49 2003/01/28 09:43:49 rschmidt - * Added defines for PCI-Spec. 2.3 IRQ - * Added defines for CLK_RUN (YUKON-Lite) - * Editorial changes - * - * Revision 1.48 2002/12/05 10:25:11 rschmidt - * Added defines for Half Duplex Burst Mode On/Off - * Added defines for Rx GMAC FIFO Flush feature - * Editorial changes - * - * Revision 1.47 2002/11/12 17:01:31 rschmidt - * Added defines for WOL_CTL_DEFAULT - * Editorial changes - * - * Revision 1.46 2002/10/14 14:47:57 rschmidt - * Corrected bit mask for HW self test results - * Added defines for WOL Registers - * Editorial changes - * - * Revision 1.45 2002/10/11 09:25:22 mkarl - * Added bit mask for HW self test results. - * - * Revision 1.44 2002/08/16 14:44:36 rschmidt - * Added define GPC_HWCFG_GMII_FIB for YUKON Fiber - * - * Revision 1.43 2002/08/12 13:31:50 rschmidt - * Corrected macros for GMAC Address Registers: GM_INADDR(), - * GM_OUTADDR(), GM_INHASH, GM_OUTHASH. - * Editorial changes - * - * Revision 1.42 2002/08/08 15:37:56 rschmidt - * Added defines for Power Management Capabilities - * Editorial changes - * - * Revision 1.41 2002/07/23 16:02:25 rschmidt - * Added macro WOL_REG() to access WOL reg. (HW-Bug in YUKON 1st rev.) - * - * Revision 1.40 2002/07/15 15:41:37 rschmidt - * Added new defines for Power Management Cap. & Control - * Editorial changes - * - * Revision 1.39 2002/06/10 09:37:07 rschmidt - * Added macros for the ADDR-Module - * - * Revision 1.38 2002/06/05 08:15:19 rschmidt - * Added defines for WOL Registers - * Editorial changes - * - * Revision 1.37 2002/04/25 11:39:23 rschmidt - * Added new defines for PCI Our Register 1 - * Added new registers and defines for YUKON (Rx FIFO, Tx FIFO, - * Time Stamp Timer, GMAC Control, GPHY Control,Link Control, - * GMAC IRQ Source and Mask, Wake-up Frame Pattern Match); - * Added new defines for Control/Status (VAUX available) - * Added Chip ID for YUKON - * Added define for descriptors with UDP ext. for YUKON - * Added macros to access the GMAC - * Added new Phy Type for Marvell 88E1011S (GPHY) - * Editorial changes - * - * Revision 1.36 2000/11/09 12:32:49 rassmann - * Renamed variables. - * - * Revision 1.35 2000/05/19 10:17:13 cgoos - * Added inactivity check in PHY_READ (in DEBUG mode only). - * - * Revision 1.34 1999/11/22 13:53:40 cgoos - * Changed license header to GPL. - * - * Revision 1.33 1999/08/27 11:17:10 malthoff - * It's more savely to put brackets around macro parameters. - * Brackets added for PHY_READ and PHY_WRITE. - * - * Revision 1.32 1999/05/19 07:31:01 cgoos - * Changes for 1000Base-T. - * Added HWAC_LINK_LED macro. - * - * Revision 1.31 1999/03/12 13:27:40 malthoff - * Remove __STDC__. - * - * Revision 1.30 1999/02/09 09:28:20 malthoff - * Add PCI_ERRBITS. - * - * Revision 1.29 1999/01/26 08:55:48 malthoff - * Bugfix: The 16 bit field relations inside the descriptor are - * endianess dependend if the descriptor reversal feature - * (PCI_REV_DESC bit in PCI_OUR_REG_2) is enabled. - * Drivers which use this feature has to set the define - * SK_USE_REV_DESC. - * - * Revision 1.28 1998/12/10 11:10:22 malthoff - * bug fix: IS_IRQ_STAT and IS_IRQ_MST_ERR has been twisted. - * - * Revision 1.27 1998/11/13 14:19:21 malthoff - * Bug Fix: The bit definition of B3_PA_CTRL has completely - * changed from HW Spec v1.3 to v1.5. - * - * Revision 1.26 1998/11/04 08:31:48 cgoos - * Fixed byte ordering in XM_OUTADDR/XM_OUTHASH macros. - * - * Revision 1.25 1998/11/04 07:16:25 cgoos - * Changed byte ordering in XM_INADDR/XM_INHASH again. - * - * Revision 1.24 1998/11/02 11:08:43 malthoff - * RxCtrl and TxCtrl must be volatile. - * - * Revision 1.23 1998/10/28 13:50:45 malthoff - * Fix: Endian support missing in XM_IN/OUT-ADDR/HASH macros. - * - * Revision 1.22 1998/10/26 08:01:36 malthoff - * RX_MFF_CTRL1 is split up into RX_MFF_CTRL1, - * RX_MFF_STAT_TO, and RX_MFF_TIST_TO. - * TX_MFF_CTRL1 is split up TX_MFF_CTRL1 and TX_MFF_WAF. - * - * Revision 1.21 1998/10/20 07:43:10 malthoff - * Fix: XM_IN/OUT/ADDR/HASH macros: - * The pointer must be casted. - * - * Revision 1.20 1998/10/19 15:53:59 malthoff - * Remove ML proto definitions. - * - * Revision 1.19 1998/10/16 14:40:17 gklug - * fix: typo B0_XM_IMSK regs - * - * Revision 1.18 1998/10/16 09:46:54 malthoff - * Remove temp defines for ML diag prototype. - * Fix register definition for B0_XM1_PHY_DATA, B0_XM1_PHY_DATA - * B0_XM2_PHY_DATA, B0_XM2_PHY_ADDR, B0_XA1_CSR, B0_XS1_CSR, - * B0_XS2_CSR, and B0_XA2_CSR. - * - * Revision 1.17 1998/10/14 06:03:14 cgoos - * Changed shifted constant to ULONG. - * - * Revision 1.16 1998/10/09 07:05:41 malthoff - * Rename ALL_PA_ENA_TO to PA_ENA_TO_ALL. - * - * Revision 1.15 1998/10/05 07:54:23 malthoff - * Split up RB_CTRL and it's bit definition into - * RB_CTRL, RB_TST1, and RB_TST2. - * Rename RB_RX_HTPP to RB_RX_LTPP. - * Add ALL_PA_ENA_TO. Modify F_WATER_MARK - * according to HW Spec. v1.5. - * Add MFF_TX_CTRL_DEF. - * - * Revision 1.14 1998/09/28 13:31:16 malthoff - * bug fix: B2_MAC_3 is 0x110 not 0x114 - * - * Revision 1.13 1998/09/24 14:42:56 malthoff - * Split the RX_MFF_TST into RX_MFF_CTRL2, - * RX_MFF_TST1, and RX_MFF_TST2. - * Rename RX_MFF_CTRL to RX_MFF_CTRL1. - * Add BMU bit CSR_SV_IDLE. - * Add macros PHY_READ() and PHY_WRITE(). - * Rename macro SK_ADDR() to SK_HW_ADDR() - * because of conflicts with the Address Module. - * - * Revision 1.12 1998/09/16 07:25:33 malthoff - * Change the parameter order in the XM_INxx and XM_OUTxx macros, - * to have the IoC as first parameter. - * - * Revision 1.11 1998/09/03 09:58:41 malthoff - * Rework the XM_xxx macros. Use {} instead of () to - * be compatible with SK_xxx macros which are defined - * with {}. - * - * Revision 1.10 1998/09/02 11:16:39 malthoff - * Temporary modify B2_I2C_SW to make tests with - * the GE/ML prototype. - * - * Revision 1.9 1998/08/19 09:11:49 gklug - * fix: struct are removed from c-source (see CCC) - * add: typedefs for all structs - * - * Revision 1.8 1998/08/18 08:27:27 malthoff - * Add some temporary workarounds to test GE - * sources with the ML. - * - * Revision 1.7 1998/07/03 14:42:26 malthoff - * bug fix: Correct macro XMA(). - * Add temporary workaround to access the PCI config space over I/O - * - * Revision 1.6 1998/06/23 11:30:36 malthoff - * Remove ';' with ',' in macors. - * - * Revision 1.5 1998/06/22 14:20:57 malthoff - * Add macro SK_ADDR(Base,Addr). - * - * Revision 1.4 1998/06/19 13:35:43 malthoff - * change 'pGec' with 'pAC' - * - * Revision 1.3 1998/06/17 14:58:16 cvs - * Lost keywords reinserted. - * - * Revision 1.1 1998/06/17 14:16:36 cvs - * created - * - * - ******************************************************************************/ - #ifndef __INC_SKGEHW_H #define __INC_SKGEHW_H diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skgehwt.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/skgehwt.h 2004-02-25 15:42:39.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-pre1/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-pre1/drivers/net/sk98lin/h/skgei2c.h 2004-02-25 15:44:18.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-pre1/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-pre1/drivers/net/sk98lin/h/skgeinit.h 2004-02-25 15:44:18.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-pre1/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-pre1/drivers/net/sk98lin/h/skgepnm2.h 2004-02-25 15:44:01.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-pre1/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-pre1/drivers/net/sk98lin/h/skgepnmi.h 2004-02-25 15:41:13.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-pre1/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-pre1/drivers/net/sk98lin/h/skgesirq.h 2004-02-25 15:45:01.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skgesirq.h * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.30 $ - * Date: $Date: 2003/07/04 12:34:13 $ * Purpose: SK specific Gigabit Ethernet special IRQ functions * ******************************************************************************/ @@ -22,111 +20,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * $Log: skgesirq.h,v $ - * Revision 1.30 2003/07/04 12:34:13 rschmidt - * Added SKERR_SIRQ_E025 for Downshift detected (Yukon-Copper) - * - * Revision 1.29 2003/05/28 15:14:49 rschmidt - * Moved defines for return codes of SkGePortCheckUp() to header file. - * Minor changes to avoid LINT warnings. - * - * Revision 1.28 2003/05/13 17:22:43 mkarl - * Editorial changes. - * - * Revision 1.27 2003/03/31 07:32:34 mkarl - * Corrected Copyright. - * Editorial changes. - * - * Revision 1.26 2002/10/14 09:52:36 rschmidt - * Added SKERR_SIRQ_E023 and SKERR_SIRQ_E024 for GPHY (Yukon) - * Editorial changes - * - * Revision 1.25 2002/07/15 18:15:52 rwahl - * Editorial changes. - * - * Revision 1.24 2002/07/15 15:39:21 rschmidt - * Corrected define for SKERR_SIRQ_E022 - * Editorial changes - * - * Revision 1.23 2002/04/25 11:09:45 rschmidt - * Removed declarations for SkXmInitPhy(), SkXmRxTxEnable() - * Editorial changes - * - * Revision 1.22 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.21 2000/10/18 12:22:40 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.20 1999/12/06 10:00:44 cgoos - * Added SET event for role. - * - * Revision 1.19 1999/11/22 13:58:26 cgoos - * Changed license header to GPL. - * - * Revision 1.18 1999/05/19 07:32:59 cgoos - * Changes for 1000Base-T. - * - * Revision 1.17 1999/03/12 13:29:31 malthoff - * Move Autonegotiation Error Codes to skgeinit.h. - * - * Revision 1.16 1999/03/08 10:11:28 gklug - * add: AutoNegDone return codes - * - * Revision 1.15 1998/11/18 13:20:53 gklug - * add: different timeouts for active and non-active links - * - * Revision 1.14 1998/11/04 07:18:14 cgoos - * Added prototype for SkXmRxTxEnable. - * - * Revision 1.13 1998/10/21 05:52:23 gklug - * add: parameter DoLoop to InitPhy function - * - * Revision 1.12 1998/10/19 06:45:03 cgoos - * Added prototype for SkXmInitPhy. - * - * Revision 1.11 1998/10/15 14:34:10 gklug - * add: WA_TIME is 500 msec - * - * Revision 1.10 1998/10/14 14:49:41 malthoff - * Remove err log defines E021 and E022. They are - * defined in skgeinit.h now. - * - * Revision 1.9 1998/10/14 14:00:39 gklug - * add: error logs for init phys - * - * Revision 1.8 1998/10/14 05:44:05 gklug - * add: E020 - * - * Revision 1.7 1998/10/02 06:24:58 gklug - * add: error messages - * - * Revision 1.6 1998/10/01 07:54:45 gklug - * add: PNMI debug module - * - * Revision 1.5 1998/09/28 13:36:31 malthoff - * Move the bit definitions for Autonegotiation - * and Flow Control to skgeinit.h. - * - * Revision 1.4 1998/09/15 12:29:34 gklug - * add: error logs - * - * Revision 1.3 1998/09/03 13:54:02 gklug - * add: function prototypes - * - * Revision 1.2 1998/09/03 10:24:36 gklug - * add: Events send by PNMI - * add: parameter definition for Flow Control etc. - * - * Revision 1.1 1998/08/27 11:50:27 gklug - * initial revision - * - * - ******************************************************************************/ - #ifndef _INC_SKGESIRQ_H_ #define _INC_SKGESIRQ_H_ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/ski2c.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/ski2c.h 2004-02-25 15:42:15.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-pre1/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-pre1/drivers/net/sk98lin/h/skqueue.h 2004-02-25 15:45:18.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skqueue.h * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.16 $ - * Date: $Date: 2003/09/16 12:50:32 $ * Purpose: Defines for the Event queue * ******************************************************************************/ @@ -22,68 +20,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skqueue.h,v $ - * Revision 1.16 2003/09/16 12:50:32 rschmidt - * Editorial changes - * - * Revision 1.15 2003/05/13 17:54:57 mkarl - * Editorial changes. - * - * Revision 1.14 2002/03/15 10:52:13 mkunz - * Added event classes for link aggregation - * - * Revision 1.13 1999/11/22 13:59:05 cgoos - * Changed license header to GPL. - * - * Revision 1.12 1998/09/08 08:48:01 gklug - * add: init level handling - * - * Revision 1.11 1998/09/03 14:15:11 gklug - * add: CSUM and HWAC Eventclass and function. - * fix: pParaPtr according to CCC - * - * Revision 1.10 1998/08/20 12:43:03 gklug - * add: typedef SK_QUEUE - * - * Revision 1.9 1998/08/19 09:50:59 gklug - * fix: remove struct keyword from C-code (see CCC) add typedefs - * - * Revision 1.8 1998/08/18 07:00:01 gklug - * fix: SK_PTR not defined use void * instead. - * - * Revision 1.7 1998/08/17 13:43:19 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.6 1998/08/14 07:09:30 gklug - * fix: chg pAc -> pAC - * - * Revision 1.5 1998/08/11 14:26:44 gklug - * chg: Event Dispatcher returns now int. - * - * Revision 1.4 1998/08/11 12:15:21 gklug - * add: Error numbers of skqueue module - * - * Revision 1.3 1998/08/07 12:54:23 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:34:00 gklug - * adapt structure defs to CCC - * add: prototypes for functions - * - * Revision 1.1 1998/07/30 14:52:12 gklug - * Initial version. - * Defines Event Classes, Event structs and queue management variables. - * - ******************************************************************************/ - -/* - * SKQUEUE.H contains all defines and types for the event queue - */ - #ifndef _SKQUEUE_H_ #define _SKQUEUE_H_ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skrlmt.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/skrlmt.h 2004-02-25 15:45:29.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skrlmt.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/04/15 09:43:43 $ * Purpose: Header file for Redundant Link ManagemenT. * ******************************************************************************/ @@ -24,137 +22,6 @@ /****************************************************************************** * - * History: - * - * $Log: skrlmt.h,v $ - * Revision 1.37 2003/04/15 09:43:43 tschilli - * Copyright messages changed. - * - * Revision 1.36 2003/04/14 15:56:22 tschilli - * "#error C++ is not yet supported." removed. - * - * Revision 1.35 2003/01/31 14:12:41 mkunz - * single port adapter runs now with two identical MAC addresses - * - * Revision 1.34 2002/09/23 15:13:41 rwahl - * Editorial changes. - * - * Revision 1.33 2001/07/03 12:16:48 mkunz - * New Flag ChgBcPrio (Change priority of last broadcast received) - * - * Revision 1.32 2001/02/14 14:06:31 rassmann - * Editorial changes. - * - * Revision 1.31 2001/02/05 14:25:26 rassmann - * Prepared RLMT for transparent operation. - * - * Revision 1.30 2001/01/22 13:41:39 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.29 2000/11/17 08:58:00 rassmann - * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. - * - * Revision 1.28 2000/11/09 12:24:34 rassmann - * Editorial changes. - * - * Revision 1.27 1999/11/22 13:59:56 cgoos - * Changed license header to GPL. - * - * Revision 1.26 1999/10/04 14:01:19 rassmann - * Corrected reaction to reception of BPDU frames (#10441). - * - * Revision 1.25 1999/07/20 12:53:39 rassmann - * Fixed documentation errors for lookahead macros. - * - * Revision 1.24 1999/05/28 11:15:56 rassmann - * Changed behaviour to reflect Design Spec v1.2. - * Controlling Link LED(s). - * Introduced RLMT Packet Version field in RLMT Packet. - * Newstyle lookahead macros (checking meta-information before looking at - * the packet). - * - * Revision 1.23 1999/01/28 12:50:42 rassmann - * Not using broadcast time stamps in CheckLinkState mode. - * - * Revision 1.22 1999/01/27 14:13:04 rassmann - * Monitoring broadcast traffic. - * Switching more reliably and not too early if switch is - * configured for spanning tree. - * - * Revision 1.21 1998/12/08 13:11:25 rassmann - * Stopping SegTimer at RlmtStop. - * - * Revision 1.20 1998/11/24 12:37:33 rassmann - * Implemented segmentation check. - * - * Revision 1.19 1998/11/17 13:43:06 rassmann - * Handling (logical) tx failure. - * Sending packet on logical address after PORT_SWITCH. - * - * Revision 1.18 1998/11/13 16:56:56 rassmann - * Added macro version of SkRlmtLookaheadPacket. - * - * Revision 1.17 1998/11/06 18:06:05 rassmann - * Corrected timing when RLMT checks fail. - * Clearing tx counter earlier in periodical checks. - * - * Revision 1.16 1998/11/03 13:53:50 rassmann - * RLMT should switch now (at least in mode 3). - * - * Revision 1.15 1998/10/22 11:39:52 rassmann - * Corrected signed/unsigned mismatches. - * Corrected receive list handling and address recognition. - * - * Revision 1.14 1998/10/15 15:16:36 rassmann - * Finished Spanning Tree checking. - * Checked with lint. - * - * Revision 1.13 1998/09/24 19:16:08 rassmann - * Code cleanup. - * Introduced Timer for PORT_DOWN due to no RX. - * - * Revision 1.12 1998/09/16 11:09:52 rassmann - * Syntax corrections. - * - * Revision 1.11 1998/09/15 11:28:50 rassmann - * Syntax corrections. - * - * Revision 1.10 1998/09/14 17:07:38 rassmann - * Added code for port checking via LAN. - * Changed Mbuf definition. - * - * Revision 1.9 1998/09/07 11:14:15 rassmann - * Syntax corrections. - * - * Revision 1.8 1998/09/07 09:06:08 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/04 19:41:34 rassmann - * Syntax corrections. - * Started entering code for checking local links. - * - * Revision 1.6 1998/09/04 12:14:28 rassmann - * Interface cleanup. - * - * Revision 1.5 1998/09/02 16:55:29 rassmann - * Updated to reflect new DRV/HWAC/RLMT interface. - * - * Revision 1.4 1998/09/02 07:26:02 afischer - * typedef for SK_RLMT_PORT - * - * Revision 1.3 1998/08/27 14:29:03 rassmann - * Code cleanup. - * - * Revision 1.2 1998/08/27 14:26:25 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:29:10 rassmann - * First public version. - * - ******************************************************************************/ - -/****************************************************************************** - * * Description: * * This is the header file for Redundant Link ManagemenT. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/sktimer.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/sktimer.h 2004-02-25 15:41:41.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-pre1/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-pre1/drivers/net/sk98lin/h/sktypes.h 2004-02-25 15:45:23.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: sktypes.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.2 $ - * Date: $Date: 2003/10/07 08:16:51 $ * Purpose: Define data types for Linux * ******************************************************************************/ @@ -22,31 +20,6 @@ * ******************************************************************************/ - /***************************************************************************** - * - * History: - * - * $Log: sktypes.h,v $ - * Revision 1.2 2003/10/07 08:16:51 mlindner - * Fix: Copyright changes - * - * Revision 1.1 2003/07/21 07:26:01 rroesler - * Fix: Re-Enter after CVS crash - * - * Revision 1.3 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.2 1999/11/22 14:01:58 cgoos - * Changed license header to GPL. - * Now using Linux' fixed size types instead of standard types. - * - * Revision 1.1 1999/02/16 07:41:40 cgoos - * First version. - * - * - * - *****************************************************************************/ - /****************************************************************************** * * Description: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/h/skversion.h linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/h/skversion.h 2004-02-25 15:43:35.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-pre1/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-pre1/drivers/net/sk98lin/h/skvpd.h 2004-02-25 15:42:21.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-pre1/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-pre1/drivers/net/sk98lin/h/xmac_ii.h 2004-02-25 15:44:40.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-pre1/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-pre1/drivers/net/sk98lin/skaddr.c 2004-02-25 15:43:41.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-pre1/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-pre1/drivers/net/sk98lin/skcsum.c 2004-02-25 15:40:51.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-pre1/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-pre1/drivers/net/sk98lin/skdim.c 2004-02-25 15:44:55.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skdim.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2003/11/28 12:55:40 $ * Purpose: All functions to maintain interrupt moderation * ******************************************************************************/ @@ -24,40 +22,6 @@ /****************************************************************************** * - * History: - * - * $Log: skdim.c,v $ - * Revision 1.5 2003/11/28 12:55:40 rroesler - * Fix: support for new process timing interface added - * - * Revision 1.4 2003/10/10 10:58:56 mlindner - * Fix: CPU detection under the kernel 2.6 - * - * Revision 1.3 2003/10/07 08:17:08 mlindner - * Fix: Copyright changes - * - * Revision 1.2 2003/08/21 12:35:05 mlindner - * Fix: Corrected CPU detection and compile errors on single CPU machines - * - * Revision 1.1 2003/07/18 13:39:55 rroesler - * Fix: Re-enter after CVS crash - * - * Revision 1.4 2003/07/07 09:45:47 rroesler - * Fix: Compiler warnings corrected - * - * Revision 1.3 2003/06/10 09:16:40 rroesler - * Adapt GetCurrentSystemLoad() to NOT access the kernels - * kstat-structure in kernel 2.5/2.6. This must be done - * due to a not exported symbol. Instead of evaluating the - * SystemLoad directly, the nbr of interrupts is used as - * a rough basis for the load. - * - * - * - ******************************************************************************/ - -/****************************************************************************** - * * Description: * * This module is intended to manage the dynamic interrupt moderation on both diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skge.c linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/skge.c 2004-02-25 15:41:32.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-pre1/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-pre1/drivers/net/sk98lin/skgehwt.c 2004-02-25 15:44:51.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skgehwt.c * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/09/16 13:41:23 $ * Purpose: Hardware Timer * ******************************************************************************/ @@ -22,60 +20,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skgehwt.c,v $ - * Revision 1.15 2003/09/16 13:41:23 rschmidt - * Added (C) Marvell to SysKonnectFileId - * Editorial changes - * - * Revision 1.14 2003/05/13 18:01:58 mkarl - * Editorial changes. - * - * Revision 1.13 1999/11/22 13:31:12 cgoos - * Changed license header to GPL. - * - * Revision 1.12 1998/10/15 15:11:34 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.11 1998/10/08 15:27:51 gklug - * chg: correction factor is host clock dependent - * - * Revision 1.10 1998/09/15 14:18:31 cgoos - * Changed more BOOLEANs to SK_xxx - * - * Revision 1.9 1998/09/15 14:16:06 cgoos - * Changed line 107: FALSE to SK_FALSE - * - * Revision 1.8 1998/08/24 13:04:44 gklug - * fix: typo - * - * Revision 1.7 1998/08/19 09:50:49 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.6 1998/08/17 09:59:02 gklug - * fix: typos - * - * Revision 1.5 1998/08/14 07:09:10 gklug - * fix: chg pAc -> pAC - * - * Revision 1.4 1998/08/10 14:14:52 gklug - * rmv: unneccessary SK_ADDR macro - * - * Revision 1.3 1998/08/07 12:53:44 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:19:29 gklug - * adapt functions to the C coding conventions - * rmv unneccessary functions. - * - * Revision 1.1 1998/08/05 11:28:36 gklug - * first version: adapted from SMT/FDDI - * - ******************************************************************************/ - /* * Event queue and dispatcher */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skgeinit.c linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/skgeinit.c 2004-02-25 15:43:28.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-pre1/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-pre1/drivers/net/sk98lin/skgemib.c 2004-02-25 15:42:31.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-pre1/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-pre1/drivers/net/sk98lin/skgepnmi.c 2004-02-25 15:44:13.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-pre1/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-pre1/drivers/net/sk98lin/skgesirq.c 2004-02-25 15:40:33.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-pre1/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-pre1/drivers/net/sk98lin/ski2c.c 2004-02-25 15:40:30.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-pre1/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-pre1/drivers/net/sk98lin/sklm80.c 2004-02-25 15:44:44.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-pre1/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-pre1/drivers/net/sk98lin/skproc.c 2004-02-25 15:41:02.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 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sk98lin/skqueue.c linux-2.4.26-pre1/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-pre1/drivers/net/sk98lin/skqueue.c 2004-02-25 15:41:54.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-pre1/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-pre1/drivers/net/sk98lin/skrlmt.c 2004-02-25 15:43:53.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-pre1/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-pre1/drivers/net/sk98lin/sktimer.c 2004-02-25 15:41:13.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-pre1/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-pre1/drivers/net/sk98lin/skvpd.c 2004-02-25 15:43:40.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-pre1/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-pre1/drivers/net/sk98lin/skxmac2.c 2004-02-25 15:42:54.000000000 +0000 @@ -2,8 +2,6 @@ * * Name: skxmac2.c * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.102 $ - * Date: $Date: 2003/10/02 16:53:58 $ * Purpose: Contains functions to initialize the MACs and PHYs * ******************************************************************************/ @@ -22,461 +20,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skxmac2.c,v $ - * Revision 1.102 2003/10/02 16:53:58 rschmidt - * Changed setting of GMAC parameters with new macros. - * Added define SLIM around SkGm...LowPowerMode(). - * Editorial changes. - * - * Revision 1.101 2003/09/16 14:49:07 rschmidt - * Added routines SkGmClearRst(), SkXmClearRst, SkMacClearRst(). - * Added WA code for Yukon-Lite's COMA mode in SkGmHardRst(). - * Replaced PCI-Config R/W through internal access. - * Fixed return from coma mode in SkGmLeaveLowPowerMode(). - * Fixed compiler warnings for different types. - * Editorial changes. - * - * Revision 1.100 2003/09/16 07:09:11 mschmid - * Added functions SkGmEnterLowPowerMode() and - * SkGmLeaveLowPowerMode() - * - * Revision 1.99 2003/07/11 12:19:33 rschmidt - * Reduced init values for Master & Slave downshift counters to - * minimum values. - * Editorial changes. - * - * Revision 1.98 2003/07/04 12:53:56 rschmidt - * Changed setting of downshift feature in SkGmInitPhyMarv(). - * Enabled downshift feature only for para 'Speed' set to 'Auto'. - * Changed init values for Master & Slave downshift counters. - * Editorial changes. - * - * Revision 1.97 2003/05/28 15:53:47 rschmidt - * Removed setting of Yukon PHY's 'force link good' in loopback mode. - * Replaced call pFnMacOverflow() with SkXmOverflowStatus() resp. - * SkGmOverflowStatus(). - * Editorial changes. - * - * Revision 1.96 2003/05/13 17:37:11 mkarl - * Removed calls to PNMI for SLIM driver. - * Added SK_FAR for PXE. - * Separated code pathes not used for SLIM driver. - * Some further separations for YUKON and GENESIS. - * Editorial changes. - * - * Revision 1.95 2003/05/06 13:09:53 rschmidt - * Changed init sequence for auto-negotiation disabled in SkGmInitMac(). - * Added defines around GENESIS resp. YUKON branches to reduce - * code size for PXE. - * Editorial changes. - * - * Revision 1.94 2003/04/10 14:36:40 rschmidt - * Fixed define for debug code in SkGmInitPhyMarv(). - * - * Revision 1.93 2003/04/08 16:58:16 rschmidt - * Changed initialisation of GMAC and GPHY for disabling - * Flow-Control with parameter 'none' (Bug Id #10769). - * Changed init for blinking active LED and normal duplex LED - * depending on value from GILedBlinkCtrl (LED Blink Control). - * Added control for Link100 LED. - * Changed handling for different PhyTypes for source code - * portability to PXE, UNDI. - * Editorial changes. - * - * Revision 1.92 2003/03/31 07:12:33 mkarl - * Restore PHY_MARV_AUNE_ADV after writing to GM_GP_CTRL in order to make - * auto-negotiation of limited flow-control possible. - * Corrected Copyright. - * Editorial changes. - * - * Revision 1.91 2003/02/05 15:09:34 rschmidt - * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv(). - * Disabled auto-update for speed, duplex and flow-control when - * auto-negotiation is not enabled (Bug Id #10766). - * Editorial changes. - * - * Revision 1.90 2003/01/29 13:35:19 rschmidt - * Increment Rx FIFO Overflow counter only in DEBUG-mode. - * Corrected define for blinking active LED. - * - * Revision 1.89 2003/01/28 16:37:45 rschmidt - * Changed init for blinking active LED - * - * Revision 1.88 2003/01/28 10:09:38 rschmidt - * Added debug outputs in SkGmInitMac(). - * Added customized init of LED registers in SkGmInitPhyMarv(), - * for blinking active LED (#ifdef ACT_LED_BLINK) and - * for normal duplex LED (#ifdef DUP_LED_NORMAL). - * Editorial changes. - * - * Revision 1.87 2002/12/10 14:39:05 rschmidt - * Improved initialization of GPHY in SkGmInitPhyMarv(). - * Editorial changes. - * - * Revision 1.86 2002/12/09 15:01:12 rschmidt - * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature). - * - * Revision 1.85 2002/12/05 14:09:16 rschmidt - * Improved avoiding endless loop in SkGmPhyRead(), SkGmPhyWrite(). - * Added additional advertising for 10Base-T when 100Base-T is selected. - * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter. - * Editorial changes. - * - * Revision 1.84 2002/11/15 12:50:09 rschmidt - * Changed SkGmCableDiagStatus() when getting results. - * - * Revision 1.83 2002/11/13 10:28:29 rschmidt - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.82 2002/11/13 09:20:46 rschmidt - * Replaced for(..) with do {} while (...) in SkXmUpdateStats(). - * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic(). - * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT). - * Editorial changes. - * - * Revision 1.81 2002/10/28 14:28:08 rschmidt - * Changed MAC address setup for GMAC in SkGmInitMac(). - * Optimized handling of counter overflow IRQ in SkGmOverflowStatus(). - * Editorial changes. - * - * Revision 1.80 2002/10/14 15:29:44 rschmidt - * Corrected disabling of all PHY IRQs. - * Added WA for deviation #16 (address used for pause packets). - * Set Pause Mode in SkMacRxTxEnable() only for Genesis. - * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode. - * SkXmTimeStamp() replaced by SkMacTimeStamp(). - * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq(). - * Editorial changes. - * - * Revision 1.79 2002/10/10 15:55:36 mkarl - * changes for PLinkSpeedUsed - * - * Revision 1.78 2002/09/12 09:39:51 rwahl - * Removed deactivate code for SIRQ overflow event separate for TX/RX. - * - * Revision 1.77 2002/09/09 12:26:37 mkarl - * added handling for Yukon to SkXmTimeStamp - * - * Revision 1.76 2002/08/21 16:41:16 rschmidt - * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE. - * Added forced speed settings in SkGmInitPhyMarv(). - * Added settings of full/half duplex capabilities for YUKON Fiber. - * Editorial changes. - * - * Revision 1.75 2002/08/16 15:12:01 rschmidt - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Added function SkMacHashing() for ADDR-Module. - * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced - * with macros). - * Removed functions SkGmGetMuxConfig(). - * Added HWCFG_MODE init for YUKON Fiber. - * Changed initialization of GPHY in SkGmInitPhyMarv(). - * Changed check of parameter in SkXmMacStatistic(). - * Editorial changes. - * - * Revision 1.74 2002/08/12 14:00:17 rschmidt - * Replaced usage of Broadcom PHY Ids with defines. - * Corrected error messages in SkGmMacStatistic(). - * Made SkMacPromiscMode() public for ADDR-Module. - * Editorial changes. - * - * Revision 1.73 2002/08/08 16:26:24 rschmidt - * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac(). - * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM. - * Editorial changes. - * - * Revision 1.72 2002/07/24 15:11:19 rschmidt - * Fixed wrong placement of parenthesis. - * Editorial changes. - * - * Revision 1.71 2002/07/23 16:05:18 rschmidt - * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite(). - * Fixed Tx Counter Overflow IRQ (Bug ID #10730). - * Editorial changes. - * - * Revision 1.70 2002/07/18 14:27:27 rwahl - * Fixed syntax error. - * - * Revision 1.69 2002/07/17 17:08:47 rwahl - * Fixed check in SkXmMacStatistic(). - * - * Revision 1.68 2002/07/16 07:35:24 rwahl - * Removed check for cleared mib counter in SkGmResetCounter(). - * - * Revision 1.67 2002/07/15 18:35:56 rwahl - * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(), - * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(), - * SkXmOverflowStatus(), SkGmOverflowStatus(). - * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both - * RX & TX. - * Changes to SkGmInitMac(): call to SkGmResetCounter(). - * Editorial changes. - * - * Revision 1.66 2002/07/15 15:59:30 rschmidt - * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite(). - * Added MIB Clear Counter in SkGmInitMac(). - * Added Duplex and Flow-Control settings. - * Reset all Multicast filtering Hash reg. in SkGmInitMac(). - * Added new function: SkGmGetMuxConfig(). - * Editorial changes. - * - * Revision 1.65 2002/06/10 09:35:39 rschmidt - * Replaced C++ comments (//). - * Added #define VCPU around VCPUwaitTime. - * Editorial changes. - * - * Revision 1.64 2002/06/05 08:41:10 rschmidt - * Added function for XMAC2: SkXmTimeStamp(). - * Added function for YUKON: SkGmSetRxCmd(). - * Changed SkGmInitMac() resp. SkGmHardRst(). - * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode). - * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). - * Editorial changes. - * - * Revision 1.63 2002/04/25 13:04:44 rschmidt - * Changes for handling YUKON. - * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. - * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced - * by functions SkXmPhyRead(), SkXmPhyWrite(); - * Removed use of PRxCmd to setup XMAC. - * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. - * Added setting of XM_RX_DIS_CEXT in SkXmInitMac(). - * Removed status parameter from MAC IRQ handler SkMacIrq(), - * SkXmIrq() and SkGmIrq(). - * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy(). - * Added SkMac...() functions to handle both XMAC and GMAC. - * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(), - * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(), - * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite(). - * Changes for V-CPU support. - * Editorial changes. - * - * Revision 1.62 2001/08/06 09:50:14 rschmidt - * Workaround BCOM Errata #1 for the C5 type. - * Editorial changes. - * - * Revision 1.61 2001/02/09 15:40:59 rassmann - * Editorial changes. - * - * Revision 1.60 2001/02/07 15:02:01 cgoos - * Added workaround for Fujitsu switch link down. - * - * Revision 1.59 2001/01/10 09:38:06 cgoos - * Fixed Broadcom C0/A1 Id check for workaround. - * - * Revision 1.58 2000/11/29 11:30:38 cgoos - * Changed DEBUG sections with NW output to xDEBUG - * - * Revision 1.57 2000/11/27 12:40:40 rassmann - * Suppressing preamble after first access to BCom, not before (#10556). - * - * Revision 1.56 2000/11/09 12:32:48 rassmann - * Renamed variables. - * - * Revision 1.55 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.54 2000/10/02 14:10:27 rassmann - * Reading BCOM PHY after releasing reset until it returns a valid value. - * - * Revision 1.53 2000/07/27 12:22:11 gklug - * fix: possible endless loop in XmHardRst. - * - * Revision 1.52 2000/05/22 08:48:31 malthoff - * Fix: #10523 errata valid for all BCOM PHYs. - * - * Revision 1.51 2000/05/17 12:52:18 malthoff - * Fixes BCom link errata (#10523). - * - * Revision 1.50 1999/11/22 13:40:14 cgoos - * Changed license header to GPL. - * - * Revision 1.49 1999/11/22 08:12:13 malthoff - * Add workaround for power consumption feature of BCom C0 chip. - * - * Revision 1.48 1999/11/16 08:39:01 malthoff - * Fix: MDIO preamble suppression is port dependent. - * - * Revision 1.47 1999/08/27 08:55:35 malthoff - * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble. - * - * Revision 1.46 1999/08/13 11:01:12 malthoff - * Fix for 1000BT: pFlowCtrlMode was not set correctly. - * - * Revision 1.45 1999/08/12 19:18:28 malthoff - * 1000BT Fixes: Do not owerwrite XM_MMU_CMD. - * Do not execute BCOM A1 workaround for B1 chips. - * Fix pause frame setting. - * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL. - * - * Revision 1.44 1999/08/03 15:23:48 cgoos - * Fixed setting of PHY interrupt mask in half duplex mode. - * - * Revision 1.43 1999/08/03 15:22:17 cgoos - * Added some debug output. - * Disabled XMac GP0 interrupt for external PHYs. - * - * Revision 1.42 1999/08/02 08:39:23 malthoff - * BCOM PHY: TX LED: To get the mono flop behaviour it is required - * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL. - * - * Revision 1.41 1999/07/30 06:54:31 malthoff - * Add temp. workarounds for the BCOM Phy revision A1. - * - * Revision 1.40 1999/06/01 07:43:26 cgoos - * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to - * AUTOFULL/AUTOHALF. - * - * Revision 1.39 1999/05/19 07:29:51 cgoos - * Changes for 1000Base-T. - * - * Revision 1.38 1999/04/08 14:35:10 malthoff - * Add code for enabling signal detect. Enabling signal detect is disabled. - * - * Revision 1.37 1999/03/12 13:42:54 malthoff - * Add: Jumbo Frame Support. - * Add: Receive modes SK_LENERR_OK_ON/OFF and - * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd(). - * - * Revision 1.36 1999/03/08 10:10:55 gklug - * fix: AutoSensing did switch to next mode even if LiPa indicated offline - * - * Revision 1.35 1999/02/22 15:16:41 malthoff - * Remove some compiler warnings. - * - * Revision 1.34 1999/01/22 09:19:59 gklug - * fix: Init DupMode and InitPauseMd are now called in RxTxEnable - * - * Revision 1.33 1998/12/11 15:19:11 gklug - * chg: lipa autoneg stati - * chg: debug messages - * chg: do NOT use spurious XmIrq - * - * Revision 1.32 1998/12/10 11:08:44 malthoff - * bug fix: pAC has been used for IOs in SkXmHardRst(). - * SkXmInitPhy() is also called for the Diag in SkXmInitMac(). - * - * Revision 1.31 1998/12/10 10:39:11 gklug - * fix: do 4 RESETS of the XMAC at the beginning - * fix: dummy read interrupt source register BEFORE initializing the Phy - * add: debug messages - * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt - * - * Revision 1.30 1998/12/07 12:18:32 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.29 1998/12/07 07:12:29 gklug - * fix: if page is received the link is down. - * - * Revision 1.28 1998/12/01 10:12:47 gklug - * chg: if spurious IRQ from XMAC encountered, save it - * - * Revision 1.27 1998/11/26 07:33:38 gklug - * add: InitPhy call is now in XmInit function - * - * Revision 1.26 1998/11/18 13:38:24 malthoff - * 'Imsk' is also unused in SkXmAutoNegDone. - * - * Revision 1.25 1998/11/18 13:28:01 malthoff - * Remove unused variable 'Reg' in SkXmAutoNegDone(). - * - * Revision 1.24 1998/11/18 13:18:45 gklug - * add: workaround for xmac errata #1 - * add: detect Link Down also when Link partner requested config - * chg: XMIrq is only used when link is up - * - * Revision 1.23 1998/11/04 07:07:04 cgoos - * Added function SkXmRxTxEnable. - * - * Revision 1.22 1998/10/30 07:35:54 gklug - * fix: serve LinkDown interrupt when link is already down - * - * Revision 1.21 1998/10/29 15:32:03 gklug - * fix: Link Down signaling - * - * Revision 1.20 1998/10/29 11:17:27 gklug - * fix: AutoNegDone bug - * - * Revision 1.19 1998/10/29 10:14:43 malthoff - * Add endainesss comment for reading/writing MAC addresses. - * - * Revision 1.18 1998/10/28 07:48:55 cgoos - * Fix: ASS somtimes signaled although link is up. - * - * Revision 1.17 1998/10/26 07:55:39 malthoff - * Fix in SkXmInitPauseMd(): Pause Mode - * was disabled and not enabled. - * Fix in SkXmAutoNegDone(): Checking Mode bits - * always failed, becaues of some missing braces. - * - * Revision 1.16 1998/10/22 09:46:52 gklug - * fix SysKonnectFileId typo - * - * Revision 1.15 1998/10/21 05:51:37 gklug - * add: para DoLoop to InitPhy function for loopback set-up - * - * Revision 1.14 1998/10/16 10:59:23 malthoff - * Remove Lint warning for dummy reads. - * - * Revision 1.13 1998/10/15 14:01:20 malthoff - * Fix: SkXmAutoNegDone() is (int) but does not return a value. - * - * Revision 1.12 1998/10/14 14:45:04 malthoff - * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by - * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent - * from the Sirq module. - * - * Revision 1.11 1998/10/14 13:59:01 gklug - * add: InitPhy function - * - * Revision 1.10 1998/10/14 11:20:57 malthoff - * Make SkXmAutoNegDone() public, because it's - * used in diagnostics, too. - * The Link Up event to the RLMT is issued in SkXmIrq(). - * SkXmIrq() is not available in diagnostics. - * Use PHY_READ when reading PHY registers. - * - * Revision 1.9 1998/10/14 05:50:10 cgoos - * Added definition for Para. - * - * Revision 1.8 1998/10/14 05:41:28 gklug - * add: Xmac IRQ - * add: auto-negotiation done function - * - * Revision 1.7 1998/10/09 06:55:20 malthoff - * The configuration of the XMACs Tx Request Threshold - * depends from the drivers port usage now. The port - * usage is configured in GIPortUsage. - * - * Revision 1.6 1998/10/05 07:48:00 malthoff - * minor changes - * - * Revision 1.5 1998/10/01 07:03:54 gklug - * add: dummy function for XMAC ISR - * - * Revision 1.4 1998/09/30 12:37:44 malthoff - * Add SkXmSetRxCmd() and related code. - * - * Revision 1.3 1998/09/28 13:26:40 malthoff - * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd() - * - * Revision 1.2 1998/09/16 14:34:21 malthoff - * Add SkXmClrExactAddr(), SkXmClrSrcCheck(), - * SkXmClrHashAddr(), SkXmFlushTxFifo(), - * SkXmFlushRxFifo(), and SkXmHardRst(). - * Finish Coding of SkXmSoftRst(). - * The sources may be compiled now. - * - * Revision 1.1 1998/09/04 10:05:56 malthoff - * Created. - * - * - ******************************************************************************/ - #include "h/skdrv1st.h" #include "h/skdrv2nd.h" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/sungem.c linux-2.4.26-pre1/drivers/net/sungem.c --- linux-2.4.25/drivers/net/sungem.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/sungem.c 2004-02-25 15:45:11.000000000 +0000 @@ -651,6 +651,7 @@ static __inline__ void gem_post_rxds(str cluster_start = curr = (gp->rx_new & ~(4 - 1)); count = 0; kick = -1; + wmb(); while (curr != limit) { curr = NEXT_RX(curr); if (++count == 4) { @@ -667,8 +668,10 @@ 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) @@ -877,6 +880,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 +920,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 +930,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 +942,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 +1437,7 @@ static void gem_clean_rings(struct gem * gp->rx_skbs[i] = NULL; } rxd->status_word = 0; + wmb(); rxd->buffer = 0; } @@ -1491,6 +1499,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 +1508,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-pre1/drivers/net/tg3.c --- linux-2.4.25/drivers/net/tg3.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/tg3.c 2004-02-25 15:42:51.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.8" +#define DRV_MODULE_RELDATE "February 23, 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,30 @@ static void tg3_write_indirect_reg32(str } } + +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 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)) @@ -655,6 +679,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; } @@ -1210,9 +1246,13 @@ static int tg3_setup_copper_phy(struct t u8 current_duplex; int i, err; + tw32(MAC_EVENT, 0); + tw32(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_MI_COMPLETION | + MAC_STATUS_LNKSTATE_CHANGED)); tr32(MAC_STATUS); udelay(40); @@ -2324,25 +2364,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; @@ -2794,32 +2828,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 +2983,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 +2993,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; @@ -3419,7 +3430,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; @@ -4793,9 +4807,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 +4834,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 +4843,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); @@ -6916,6 +6920,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. * @@ -7415,17 +7425,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 +7751,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-pre1/drivers/net/tg3.h --- linux-2.4.25/drivers/net/tg3.h 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/tg3.h 2004-02-25 15:43:45.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/typhoon-firmware.h linux-2.4.26-pre1/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-pre1/drivers/net/typhoon-firmware.h 2004-02-25 15:44:30.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-pre1/drivers/net/typhoon.c --- linux-2.4.25/drivers/net/typhoon.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/typhoon.c 2004-02-25 15:44:30.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-pre1/drivers/net/typhoon.h --- linux-2.4.25/drivers/net/typhoon.h 2003-06-13 14:51:35.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/typhoon.h 2004-02-25 15:44:37.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-pre1/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-pre1/drivers/net/wireless/Config.in 2004-02-25 15:42:15.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-pre1/drivers/net/wireless/Makefile --- linux-2.4.25/drivers/net/wireless/Makefile 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.26-pre1/drivers/net/wireless/Makefile 2004-02-25 15:45:31.000000000 +0000 @@ -12,7 +12,7 @@ obj-n := obj- := # Things that need to export symbols -export-objs := airo.o orinoco.o hermes.o +export-objs := airo.o orinoco.o hermes.o atmel.o obj-$(CONFIG_HERMES) += orinoco.o hermes.o obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o @@ -23,5 +23,6 @@ obj-$(CONFIG_PCI_HERMES) += orinoco_pci. obj-$(CONFIG_AIRO) += airo.o obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o +obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o atmel.o include $(TOPDIR)/Rules.make diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/net/wireless/airo.c linux-2.4.26-pre1/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-pre1/drivers/net/wireless/airo.c 2004-02-25 15:41:15.000000000 +0000 @@ -18,7 +18,6 @@ ======================================================================*/ #include -#include #include #include @@ -41,12 +40,11 @@ #include #include #include -#include #include #include #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-pre1/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-pre1/drivers/net/wireless/atmel.c 2004-02-25 15:43:33.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 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 = ""; + } + + 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 = ""; + } + 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 = ""; + } + + 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; iBSS_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; iBSS_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; iBSS_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; iBSS_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-pre1/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-pre1/drivers/net/wireless/atmel_cs.c 2004-02-25 15:42:47.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 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 +#ifdef __IN_PCMCIA_PACKAGE__ +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* + 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<conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; + else if (dflt.vcc.present & (1<conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; + + if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; + else if (dflt.vpp1.present & (1<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/scsi/scsi_scan.c linux-2.4.26-pre1/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-pre1/drivers/scsi/scsi_scan.c 2004-02-25 15:44:31.000000000 +0000 @@ -189,6 +189,7 @@ static struct dev_info device_list[] = {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HITACHI", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HITACHI XP Arrays */ + {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HITACHI 9960 */ {"WINSYS","FLASHDISK G6", "*", BLIST_SPARSELUN}, {"DotHill","SANnet RAID X300", "*", BLIST_SPARSELUN}, {"SUN", "T300", "*", BLIST_SPARSELUN}, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/drivers/video/amifb.c linux-2.4.26-pre1/drivers/video/amifb.c --- linux-2.4.25/drivers/video/amifb.c 2003-06-13 14:51:37.000000000 +0000 +++ linux-2.4.26-pre1/drivers/video/amifb.c 2004-02-25 15:44:44.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/fs/hfsplus/wrapper.c linux-2.4.26-pre1/fs/hfsplus/wrapper.c --- linux-2.4.25/fs/hfsplus/wrapper.c 2003-08-25 11:44:43.000000000 +0000 +++ linux-2.4.26-pre1/fs/hfsplus/wrapper.c 2004-02-25 15:42:33.000000000 +0000 @@ -14,6 +14,7 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #include #endif +#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" @@ -45,7 +46,7 @@ static int hfsplus_read_mdb(unsigned cha return 0; wd->ablk_start = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART)); - extent = be32_to_cpu(*(u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)); + extent = be32_to_cpu(get_unaligned((u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT))); wd->embed_start = (extent >> 16) & 0xFFFF; wd->embed_count = extent & 0xFFFF; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/acpi/acconfig.h linux-2.4.26-pre1/include/acpi/acconfig.h --- linux-2.4.25/include/acpi/acconfig.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/acpi/acconfig.h 2004-02-25 15:41:48.000000000 +0000 @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20040116 +#define ACPI_CA_VERSION 0x20040211 /* Maximum objects in the various object caches */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/asm-i386/highmem.h linux-2.4.26-pre1/include/asm-i386/highmem.h --- linux-2.4.25/include/asm-i386/highmem.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.26-pre1/include/asm-i386/highmem.h 2004-02-25 15:41:11.000000000 +0000 @@ -46,7 +46,7 @@ extern void kmap_init(void) __init; * easily, subsequent pte tables have to be allocated in one physical * chunk of RAM. */ -#define PKMAP_BASE (0xfe000000UL) +#define PKMAP_BASE (0xff800000UL) #ifdef CONFIG_X86_PAE #define LAST_PKMAP 512 #else diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/ide.h linux-2.4.26-pre1/include/linux/ide.h --- linux-2.4.25/include/linux/ide.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/ide.h 2004-02-25 15:41:45.000000000 +0000 @@ -1102,7 +1102,6 @@ typedef struct { #ifdef CONFIG_PROC_FS extern void proc_ide_create(void); extern void proc_ide_destroy(void); -extern void recreate_proc_ide_device(ide_hwif_t *, ide_drive_t *); extern void destroy_proc_ide_device(ide_hwif_t *, ide_drive_t *); extern void destroy_proc_ide_drives(ide_hwif_t *); extern void create_proc_ide_interfaces(void); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/if_bonding.h linux-2.4.26-pre1/include/linux/if_bonding.h --- linux-2.4.25/include/linux/if_bonding.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/if_bonding.h 2004-02-25 15:44:36.000000000 +0000 @@ -1,7 +1,7 @@ /* * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'. * - * + * * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes * NCM: Network and Communications Management, Inc. * @@ -10,11 +10,11 @@ * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. - * + * * 2003/03/18 - Amir Noam * - Added support for getting slave's speed and duplex via ethtool. * Needed for 802.3ad and other future modes. - * + * * 2003/03/18 - Tsippy Mendelson and * Shmulik Hen * - Enable support of modes that need to use the unique mac address of @@ -32,6 +32,9 @@ * 2003/05/01 - Amir Noam * - Added ABI version control to restore compatibility between * new/old ifenslave and new/old bonding. + * + * 2003/12/01 - Shmulik Hen + * - Code cleanup and style changes */ #ifndef _LINUX_IF_BONDING_H @@ -42,7 +45,7 @@ #include /* userland - kernel ABI version (2003/05/08) */ -#define BOND_ABI_VERSION 1 +#define BOND_ABI_VERSION 2 /* * We can remove these ioctl definitions in 2.5. People should use the @@ -77,10 +80,6 @@ #define BOND_DEFAULT_MAX_BONDS 1 /* Default maximum number of devices to support */ -#define BOND_MULTICAST_DISABLED 0 -#define BOND_MULTICAST_ACTIVE 1 -#define BOND_MULTICAST_ALL 2 - typedef struct ifbond { __s32 bond_mode; __s32 num_slaves; @@ -91,8 +90,8 @@ typedef struct ifslave { __s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */ char slave_name[IFNAMSIZ]; - char link; - char state; + __s8 link; + __s8 state; __u32 link_failure_count; } ifslave; @@ -115,3 +114,4 @@ struct ad_info { * tab-width: 8 * End: */ + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/if_vlan.h linux-2.4.26-pre1/include/linux/if_vlan.h --- linux-2.4.25/include/linux/if_vlan.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/if_vlan.h 2004-02-25 15:41:45.000000000 +0000 @@ -200,6 +200,148 @@ static inline int vlan_hwaccel_receive_s { return __vlan_hwaccel_rx(skb, grp, vlan_tag, 1); } + +/** + * __vlan_put_tag - regular VLAN tag inserting + * @skb: skbuff to tag + * @tag: VLAN tag to insert + * + * Inserts the VLAN tag into @skb as part of the payload + * Returns a VLAN tagged skb. If a new skb is created, @skb is freed. + * + * Following the skb_unshare() example, in case of error, the calling function + * doesn't have to worry about freeing the original skb. + */ +static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, unsigned short tag) +{ + struct vlan_ethhdr *veth; + + if (skb_headroom(skb) < VLAN_HLEN) { + struct sk_buff *sk_tmp = skb; + skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); + kfree_skb(sk_tmp); + if (!skb) { + printk(KERN_ERR "vlan: failed to realloc headroom\n"); + return NULL; + } + } else { + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + printk(KERN_ERR "vlan: failed to unshare skbuff\n"); + return NULL; + } + } + + veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); + + /* Move the mac addresses to the beginning of the new header. */ + memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN); + + /* first, the ethernet type */ + veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); + + /* now, the tag */ + veth->h_vlan_TCI = htons(tag); + + return skb; +} + +/** + * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting + * @skb: skbuff to tag + * @tag: VLAN tag to insert + * + * Puts the VLAN tag in @skb->cb[] and lets the device do the rest + */ +static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, unsigned short tag) +{ + struct vlan_skb_tx_cookie *cookie; + + cookie = VLAN_TX_SKB_CB(skb); + cookie->magic = VLAN_TX_COOKIE_MAGIC; + cookie->vlan_tag = tag; + + return skb; +} + +#define HAVE_VLAN_PUT_TAG + +/** + * vlan_put_tag - inserts VLAN tag according to device features + * @skb: skbuff to tag + * @tag: VLAN tag to insert + * + * Assumes skb->dev is the target that will xmit this frame. + * Returns a VLAN tagged skb. + */ +static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, unsigned short tag) +{ + if (skb->dev->features & NETIF_F_HW_VLAN_TX) { + return __vlan_hwaccel_put_tag(skb, tag); + } else { + return __vlan_put_tag(skb, tag); + } +} + +/** + * __vlan_get_tag - get the VLAN ID that is part of the payload + * @skb: skbuff to query + * @tag: buffer to store vlaue + * + * Returns error if the skb is not of VLAN type + */ +static inline int __vlan_get_tag(struct sk_buff *skb, unsigned short *tag) +{ + struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data; + + if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) { + return -EINVAL; + } + + *tag = ntohs(veth->h_vlan_TCI); + + return 0; +} + +/** + * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[] + * @skb: skbuff to query + * @tag: buffer to store vlaue + * + * Returns error if @skb->cb[] is not set correctly + */ +static inline int __vlan_hwaccel_get_tag(struct sk_buff *skb, unsigned short *tag) +{ + struct vlan_skb_tx_cookie *cookie; + + cookie = VLAN_TX_SKB_CB(skb); + if (cookie->magic == VLAN_TX_COOKIE_MAGIC) { + *tag = cookie->vlan_tag; + return 0; + } else { + *tag = 0; + return -EINVAL; + } +} + +#define HAVE_VLAN_GET_TAG + +/** + * vlan_get_tag - get the VLAN ID from the skb + * @skb: skbuff to query + * @tag: buffer to store vlaue + * + * Returns error if the skb is not VLAN tagged + */ +static inline int vlan_get_tag(struct sk_buff *skb, unsigned short *tag) +{ + if (skb->dev->features & NETIF_F_HW_VLAN_TX) { + return __vlan_hwaccel_get_tag(skb, tag); + } else { + return __vlan_get_tag(skb, tag); + } +} + #endif /* __KERNEL__ */ /* VLAN IOCTLs are found in sockios.h */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/inetdevice.h linux-2.4.26-pre1/include/linux/inetdevice.h --- linux-2.4.25/include/linux/inetdevice.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/inetdevice.h 2004-02-25 15:44:02.000000000 +0000 @@ -18,6 +18,8 @@ struct ipv4_devconf int mc_forwarding; int tag; int arp_filter; + int arp_announce; + int arp_ignore; int medium_id; int force_igmp_version; void *sysctl; @@ -69,6 +71,8 @@ struct in_device (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects))) #define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter) +#define IN_DEV_ARP_ANNOUNCE(in_dev) (max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce)) +#define IN_DEV_ARP_IGNORE(in_dev) (max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore)) struct in_ifaddr { @@ -95,8 +99,9 @@ extern void devinet_init(void); extern struct in_device *inetdev_init(struct net_device *dev); extern struct in_device *inetdev_by_index(int); extern u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope); +extern u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope); extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask); -extern void inet_forward_change(void); +extern void inet_forward_change(int); static __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/pci_ids.h linux-2.4.26-pre1/include/linux/pci_ids.h --- linux-2.4.25/include/linux/pci_ids.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/pci_ids.h 2004-02-25 15:42:47.000000000 +0000 @@ -750,6 +750,7 @@ #define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P 0x0027 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP15 0x002d #define PCI_DEVICE_ID_APPLE_UNI_N_FW2 0x0030 +#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 #define PCI_VENDOR_ID_YAMAHA 0x1073 #define PCI_DEVICE_ID_YAMAHA_724 0x0004 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/sctp.h linux-2.4.26-pre1/include/linux/sctp.h --- linux-2.4.25/include/linux/sctp.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/sctp.h 2004-02-25 15:43:26.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -42,6 +42,8 @@ * randall@sctp.chicago.il.us * kmorneau@cisco.com * qxie1@email.mot.com + * Sridhar Samudrala + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -437,12 +439,13 @@ typedef enum { * 0x0101 Operation Refused Due to Resource Shortage. * 0x0102 Request to Delete Source IP Address. * 0x0103 Association Aborted due to illegal ASCONF-ACK + * 0x0104 Request refused - no authorization. */ SCTP_ERROR_DEL_LAST_IP = __constant_htons(0x0100), SCTP_ERROR_RSRC_LOW = __constant_htons(0x0101), SCTP_ERROR_DEL_SRC_IP = __constant_htons(0x0102), SCTP_ERROR_ASCONF_ACK = __constant_htons(0x0103), - + SCTP_ERROR_REQ_REFUSED = __constant_htons(0x0104) } sctp_error_t; @@ -471,118 +474,55 @@ typedef struct sctp_cwr_chunk { sctp_cwrhdr_t cwr_hdr; } sctp_cwr_chunk_t __attribute__((packed)); - -/* FIXME: Cleanup needs to continue below this line. */ - /* * ADDIP Section 3.1 New Chunk Types */ - -/* ADDIP Section 3.1.1 - * - * ASCONF-Request Correlation ID: 32 bits (unsigned integer) - * - * This is an opaque integer assigned by the sender to identify each - * request parameter. It is in host byte order and is only meaningful - * to the sender. The receiver of the ASCONF Chunk will copy this 32 - * bit value into the ASCONF Correlation ID field of the - * ASCONF-ACK. The sender of the ASCONF can use this same value in the - * ASCONF-ACK to find which request the response is for. - * - * ASCONF Parameter: TLV format - * - * Each Address configuration change is represented by a TLV parameter - * as defined in Section 3.2. One or more requests may be present in - * an ASCONF Chunk. - */ -typedef struct { - __u32 correlation; - sctp_paramhdr_t p; - __u8 payload[0]; -} sctpAsconfReq_t; - /* ADDIP - * 3.1.1 Address/Stream Configuration Change Chunk (ASCONF) + * Section 3.1.1 Address Configuration Change Chunk (ASCONF) * - * This chunk is used to communicate to the remote endpoint one of the - * configuration change requests that MUST be acknowledged. The - * information carried in the ASCONF Chunk uses the form of a - * Tag-Length-Value (TLV), as described in "3.2.1 - * Optional/Variable-length Parameter Format" in [RFC2960], for all - * variable parameters. - */ -typedef struct { - __u32 serial; - __u8 reserved[3]; - __u8 addr_type; - __u32 addr[4]; - sctpAsconfReq_t requests[0]; -} sctpAsconf_t; + * Serial Number: 32 bits (unsigned integer) + * This value represents a Serial Number for the ASCONF Chunk. The + * valid range of Serial Number is from 0 to 2^32-1. + * Serial Numbers wrap back to 0 after reaching 2^32 -1. + * + * Address Parameter: 8 or 20 bytes (depending on type) + * The address is an address of the sender of the ASCONF chunk, + * the address MUST be considered part of the association by the + * peer endpoint. This field may be used by the receiver of the + * ASCONF to help in finding the association. This parameter MUST + * be present in every ASCONF message i.e. it is a mandatory TLV + * parameter. + * + * ASCONF Parameter: TLV format + * Each Address configuration change is represented by a TLV + * parameter as defined in Section 3.2. One or more requests may + * be present in an ASCONF Chunk. + * + * Section 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK) + * + * Serial Number: 32 bits (unsigned integer) + * This value represents the Serial Number for the received ASCONF + * Chunk that is acknowledged by this chunk. This value is copied + * from the received ASCONF Chunk. + * + * ASCONF Parameter Response: TLV format + * The ASCONF Parameter Response is used in the ASCONF-ACK to + * report status of ASCONF processing. + */ +typedef struct sctp_addip_param { + sctp_paramhdr_t param_hdr; + __u32 crr_id; +}sctp_addip_param_t __attribute__((packed)); -/* ADDIP - * 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK) - * - * ASCONF-Request Correlation ID: 32 bits (unsigned integer) - * - * This value is copied from the ASCONF Correlation ID received in the - * ASCONF Chunk. It is used by the receiver of the ASCONF-ACK to identify - * which ASCONF parameter this response is associated with. - * - * ASCONF Parameter Response : TLV format - * - * The ASCONF Parameter Response is used in the ASCONF-ACK to report - * status of ASCONF processing. By default, if a responding endpoint - * does not include any Error Cause, a success is indicated. Thus a - * sender of an ASCONF-ACK MAY indicate complete success of all TLVs in - * an ASCONF by returning only the Chunk Type, Chunk Flags, Chunk Length - * (set to 8) and the Serial Number. - */ -typedef union { - struct { - __u32 correlation; - sctp_paramhdr_t header; /* success report */ - } success; - struct { - __u32 correlation; - sctp_paramhdr_t header; /* error cause indication */ - sctp_paramhdr_t errcause; - uint8_t request[0]; /* original request from ASCONF */ - } error; -#define __correlation success.correlation -#define __header success.header -#define __cause error.errcause -#define __request error.request -} sctpAsconfAckRsp_t; - -/* ADDIP - * 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK) - * - * This chunk is used by the receiver of an ASCONF Chunk to - * acknowledge the reception. It carries zero or more results for any - * ASCONF Parameters that were processed by the receiver. - */ -typedef struct { +typedef struct sctp_addiphdr { __u32 serial; - sctpAsconfAckRsp_t responses[0]; -} sctpAsconfAck_t; + __u8 params[0]; +} sctp_addiphdr_t __attribute__((packed)); -/********************************************************************* - * Internal structures - * - * These are data structures which never go out on the wire. - *********************************************************************/ - -/* What is this data structure for? The TLV isn't one--it is just a - * value. Perhaps this data structure ought to have a type--otherwise - * it is not unambigiously parseable. --piggy - */ -typedef struct { - struct list_head hook; - int length; /* length of the TLV */ - - /* the actually TLV to be copied into ASCONF_ACK */ - sctpAsconfAckRsp_t TLV; -} sctpAsconfAckRspNode_t; +typedef struct sctp_addip_chunk { + sctp_chunkhdr_t chunk_hdr; + sctp_addiphdr_t addip_hdr; +} sctp_addip_chunk_t __attribute__((packed)); #endif /* __LINUX_SCTP_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/linux/sysctl.h linux-2.4.26-pre1/include/linux/sysctl.h --- linux-2.4.25/include/linux/sysctl.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/linux/sysctl.h 2004-02-25 15:40:40.000000000 +0000 @@ -312,6 +312,7 @@ enum NET_TCP_FRTO=92, NET_TCP_LOW_LATENCY=93, NET_IPV4_IPFRAG_SECRET_INTERVAL=94, + NET_TCP_WESTWOOD=95, }; enum { @@ -360,6 +361,8 @@ enum NET_IPV4_CONF_ARPFILTER=13, NET_IPV4_CONF_MEDIUM_ID=14, NET_IPV4_CONF_FORCE_IGMP_VERSION=17, + NET_IPV4_CONF_ARP_ANNOUNCE=18, + NET_IPV4_CONF_ARP_IGNORE=19, }; /* /proc/sys/net/ipv4/netfilter */ @@ -548,6 +551,7 @@ enum { NET_SCTP_HB_INTERVAL = 10, NET_SCTP_PRESERVE_ENABLE = 11, NET_SCTP_MAX_BURST = 12, + NET_SCTP_ADDIP_ENABLE = 13, }; /* /proc/sys/net/khttpd/ */ enum { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/arp.h linux-2.4.26-pre1/include/net/arp.h --- linux-2.4.25/include/net/arp.h 2001-11-22 19:47:14.000000000 +0000 +++ linux-2.4.26-pre1/include/net/arp.h 2004-02-25 15:41:50.000000000 +0000 @@ -5,6 +5,8 @@ #include #include +#define HAVE_ARP_CREATE + extern struct neigh_table arp_tbl; extern void arp_init(void); @@ -19,6 +21,12 @@ extern int arp_bind_neighbour(struct dst extern int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir); extern void arp_ifdown(struct net_device *dev); +extern struct sk_buff *arp_create(int type, int ptype, u32 dest_ip, + struct net_device *dev, u32 src_ip, + unsigned char *dest_hw, unsigned char *src_hw, + unsigned char *target_hw); +extern void arp_xmit(struct sk_buff *skb); + extern struct neigh_ops arp_broken_ops; #endif /* _ARP_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/ip_vs.h linux-2.4.26-pre1/include/net/ip_vs.h --- linux-2.4.25/include/net/ip_vs.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/ip_vs.h 2004-02-25 15:41:30.000000000 +0000 @@ -8,7 +8,7 @@ #include /* For __uXX types */ -#define IP_VS_VERSION_CODE 0x01000A +#define IP_VS_VERSION_CODE 0x01000B #define NVERSION(version) \ (version >> 16) & 0xFF, \ (version >> 8) & 0xFF, \ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/command.h linux-2.4.26-pre1/include/net/sctp/command.h --- linux-2.4.25/include/net/sctp/command.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/command.h 2004-02-25 15:44:33.000000000 +0000 @@ -1,5 +1,6 @@ -/* SCTP kernel reference Implementation Copyright (C) 1999-2001 - * Cisco, Motorola, and IBM +/* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 + * Copyright (C) 1999-2001 Cisco, Motorola * * This file is part of the SCTP kernel reference Implementation * @@ -87,6 +88,8 @@ typedef enum { SCTP_CMD_RTO_PENDING, /* Set transport's rto_pending. */ SCTP_CMD_PART_DELIVER, /* Partial data delivery considerations. */ SCTP_CMD_RENEGE, /* Renege data on an association. */ + SCTP_CMD_SETUP_T4, /* ADDIP, setup T4 RTO timer parms. */ + SCTP_CMD_PROCESS_OPERR, /* Process an ERROR chunk. */ SCTP_CMD_LAST } sctp_verb_t; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/compat.h linux-2.4.26-pre1/include/net/sctp/compat.h --- linux-2.4.25/include/net/sctp/compat.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/compat.h 2004-02-25 15:40:35.000000000 +0000 @@ -1,5 +1,6 @@ /* SCTP kernel reference Implementation * + * (C) Copyright IBM Corp. 2004 * Copyright (c) 2003 Hewlett-Packard Company * * This file is part of the SCTP kernel reference Implementation @@ -36,7 +37,7 @@ #include /* - * The following defines are for compatibility with 2.5 + * The following defines are for compatibility with 2.6 */ /* * container_of - cast a member of a structure out to the containing structure @@ -54,7 +55,6 @@ extern type name[] #define SNMP_DEC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_softirq()].field--) -#define sctp_sk(__sk) (&(((struct sock *)__sk)->tp_pinfo.af_sctp)) #define inet_sk(__sk) (&(((struct sock *)__sk)->protinfo.af_inet)) #define inet6_sk(__sk) (&(((struct sock *)__sk)->net_pinfo.af_inet6)) @@ -64,9 +64,37 @@ #define __unsafe(x) MOD_INC_USE_COUNT #define dst_pmtu(x) ((x)->pmtu) -void sctp_hash_digest(const char *key, const int in_key_len, - const char *text, const int text_len, - __u8 *digest); +#define sk_family family +#define sk_state state +#define sk_type type +#define sk_socket socket +#define sk_prot prot +#define sk_rcvbuf rcvbuf +#define sk_sndbuf sndbuf +#define sk_ack_backlog ack_backlog +#define sk_max_ack_backlog max_ack_backlog +#define sk_write_space write_space +#define sk_use_write_queue use_write_queue +#define sk_err err +#define sk_err_soft err_soft +#define sk_error_report error_report +#define sk_error_queue error_queue +#define sk_shutdown shutdown +#define sk_state_change state_change +#define sk_receive_queue receive_queue +#define sk_data_ready data_ready +#define sk_no_check no_check +#define sk_reuse reuse +#define sk_destruct destruct +#define sk_zapped zapped +#define sk_protocol protocol +#define sk_backlog_rcv backlog_rcv +#define sk_allocation allocation +#define sk_lingertime lingertime +#define sk_sleep sleep +#define sk_wmem_queued wmem_queued +#define sk_bound_dev_if bound_dev_if + /* * find last bit set. */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/constants.h linux-2.4.26-pre1/include/net/sctp/constants.h --- linux-2.4.25/include/net/sctp/constants.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/constants.h 2004-02-25 15:40:40.000000000 +0000 @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -75,6 +75,7 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX #define SCTP_NUM_BASE_CHUNK_TYPES (SCTP_CID_BASE_MAX + 1) #define SCTP_NUM_CHUNK_TYPES (SCTP_NUM_BASE_CHUNKTYPES + 2) +#define SCTP_NUM_ADDIP_CHUNK_TYPES 2 /* These are the different flavours of event. */ typedef enum { @@ -99,6 +100,7 @@ typedef enum { SCTP_EVENT_TIMEOUT_T1_INIT, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN, SCTP_EVENT_TIMEOUT_T3_RTX, + SCTP_EVENT_TIMEOUT_T4_RTO, SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD, SCTP_EVENT_TIMEOUT_HEARTBEAT, SCTP_EVENT_TIMEOUT_SACK, @@ -122,9 +124,10 @@ typedef enum { SCTP_PRIMITIVE_ABORT, SCTP_PRIMITIVE_SEND, SCTP_PRIMITIVE_REQUESTHEARTBEAT, + SCTP_PRIMITIVE_ASCONF, } sctp_event_primitive_t; -#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_REQUESTHEARTBEAT +#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_ASCONF #define SCTP_NUM_PRIMITIVE_TYPES (SCTP_EVENT_PRIMITIVE_MAX + 1) /* We define here a utility type for manipulating subtypes. @@ -267,7 +270,8 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = * nearest power of 2. */ enum { SCTP_MIN_PMTU = 576 }; -enum { SCTP_MAX_DUP_TSNS = 128 }; +enum { SCTP_MAX_DUP_TSNS = 16 }; +enum { SCTP_MAX_GABS = 16 }; typedef enum { SCTP_COUNTER_INIT_ERROR, @@ -319,7 +323,7 @@ typedef enum { #define SCTP_DEFAULT_COOKIE_LIFE_USEC 0 /* microseconds */ #define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */ -#define SCTP_DEFAULT_MAXWINDOW 32768 /* default rwnd size */ +#define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */ #define SCTP_DEFAULT_MAXSEGMENT 1500 /* MTU size, this is the limit * to which we will raise the P-MTU. */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/sctp.h linux-2.4.26-pre1/include/net/sctp/sctp.h --- linux-2.4.25/include/net/sctp/sctp.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/sctp.h 2004-02-25 15:42:21.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * * This file is part of the SCTP kernel reference Implementation @@ -39,6 +39,8 @@ * Daisy Chang * Sridhar Samudrala * Ardelle Fan + * Ryan Layer + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -75,7 +77,6 @@ #include #include #include -#include #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include @@ -114,17 +115,20 @@ #define SCTP_STATIC static #endif +#define MSECS_TO_JIFFIES(msec) \ + (((msec / 1000) * HZ) + ((msec % 1000) * HZ) / 1000) +#define JIFFIES_TO_MSECS(jiff) \ + (((jiff / HZ) * 1000) + ((jiff % HZ) * 1000) / HZ) + /* * Function declarations. */ /* - * sctp_protocol.c + * sctp/protocol.c */ -extern struct sctp_protocol sctp_proto; extern struct sock *sctp_get_ctl_sock(void); -extern int sctp_copy_local_addr_list(struct sctp_protocol *, - struct sctp_bind_addr *, +extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, sctp_scope_t, int gfp, int flags); extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); extern int sctp_register_pf(struct sctp_pf *, sa_family_t); @@ -132,54 +136,55 @@ extern int sctp_register_pf(struct sctp_ /* * sctp/socket.c */ -extern int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb); -extern int sctp_inet_listen(struct socket *sock, int backlog); -extern void sctp_write_space(struct sock *sk); -extern unsigned int sctp_poll(struct file *file, struct socket *sock, +int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb); +int sctp_inet_listen(struct socket *sock, int backlog); +void sctp_write_space(struct sock *sk); +unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait); /* * sctp/primitive.c */ -extern int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg); -extern int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); -extern int sctp_primitive_ABORT(struct sctp_association *, void *arg); -extern int sctp_primitive_SEND(struct sctp_association *, void *arg); -extern int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); +int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg); +int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); +int sctp_primitive_ABORT(struct sctp_association *, void *arg); +int sctp_primitive_SEND(struct sctp_association *, void *arg); +int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); +int sctp_primitive_ASCONF(struct sctp_association *, void *arg); /* * sctp/crc32c.c */ -extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count); -extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum); -extern __u32 sctp_end_cksum(__u32 cksum); -extern __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum); +__u32 sctp_start_cksum(__u8 *ptr, __u16 count); +__u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum); +__u32 sctp_end_cksum(__u32 cksum); +__u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum); /* * sctp/input.c */ -extern int sctp_rcv(struct sk_buff *skb); -extern void sctp_v4_err(struct sk_buff *skb, u32 info); -extern void sctp_hash_established(struct sctp_association *); -extern void __sctp_hash_established(struct sctp_association *); -extern void sctp_unhash_established(struct sctp_association *); -extern void __sctp_unhash_established(struct sctp_association *); -extern void sctp_hash_endpoint(struct sctp_endpoint *); -extern void __sctp_hash_endpoint(struct sctp_endpoint *); -extern void sctp_unhash_endpoint(struct sctp_endpoint *); -extern void __sctp_unhash_endpoint(struct sctp_endpoint *); -extern struct sctp_association *__sctp_lookup_association( +int sctp_rcv(struct sk_buff *skb); +void sctp_v4_err(struct sk_buff *skb, u32 info); +void sctp_hash_established(struct sctp_association *); +void __sctp_hash_established(struct sctp_association *); +void sctp_unhash_established(struct sctp_association *); +void __sctp_unhash_established(struct sctp_association *); +void sctp_hash_endpoint(struct sctp_endpoint *); +void __sctp_hash_endpoint(struct sctp_endpoint *); +void sctp_unhash_endpoint(struct sctp_endpoint *); +void __sctp_unhash_endpoint(struct sctp_endpoint *); +struct sctp_association *__sctp_lookup_association( const union sctp_addr *, const union sctp_addr *, struct sctp_transport **); -extern struct sock *sctp_err_lookup(int family, struct sk_buff *, - struct sctphdr *, struct sctp_endpoint **, - struct sctp_association **, - struct sctp_transport **); -extern void sctp_err_finish(struct sock *, struct sctp_endpoint *, +struct sock *sctp_err_lookup(int family, struct sk_buff *, + struct sctphdr *, struct sctp_endpoint **, + struct sctp_association **, + struct sctp_transport **); +void sctp_err_finish(struct sock *, struct sctp_endpoint *, struct sctp_association *); -extern void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, - struct sctp_transport *t, __u32 pmtu); +void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, + struct sctp_transport *t, __u32 pmtu); /* * Section: Macros, externs, and inlines @@ -227,10 +232,10 @@ static inline int sctp_is_valid_kaddr(un if (addr < PAGE_OFFSET) return 0; - page = virt_to_page((void*)addr); + page = virt_to_page(addr); /* Is this page valid? */ - if (!virt_addr_valid((void*)addr) || PageReserved(page)) + if (!virt_addr_valid(addr) || PageReserved(page)) return 0; return 1; @@ -277,6 +282,7 @@ extern atomic_t sctp_dbg_objcnt_chunk; extern atomic_t sctp_dbg_objcnt_bind_addr; extern atomic_t sctp_dbg_objcnt_addr; extern atomic_t sctp_dbg_objcnt_ssnmap; +extern atomic_t sctp_dbg_objcnt_datamsg; /* Macros to atomically increment/decrement objcnt counters. */ #define SCTP_DBG_OBJCNT_INC(name) \ @@ -292,8 +298,8 @@ atomic_t sctp_dbg_objcnt_## name = ATOMI #define SCTP_DBG_OBJCNT_ENTRY(name) \ {.label= #name, .counter= &sctp_dbg_objcnt_## name} -extern void sctp_dbg_objcnt_init(void); -extern void sctp_dbg_objcnt_exit(void); +void sctp_dbg_objcnt_init(void); +void sctp_dbg_objcnt_exit(void); #else @@ -306,11 +312,17 @@ static inline void sctp_dbg_objcnt_exit( #endif /* CONFIG_SCTP_DBG_OBJCOUNT */ #if defined CONFIG_SYSCTL -extern void sctp_sysctl_register(void); -extern void sctp_sysctl_unregister(void); +void sctp_sysctl_register(void); +void sctp_sysctl_unregister(void); #else static inline void sctp_sysctl_register(void) { return; } static inline void sctp_sysctl_unregister(void) { return; } +static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, void *newval, + size_t newlen, void **context) +{ + return -ENOSYS; +} #endif /* Size of Supported Address Parameter for 'x' address types. */ @@ -318,9 +330,9 @@ static inline void sctp_sysctl_unregiste #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -extern int sctp_v6_init(void); -extern void sctp_v6_exit(void); -extern void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, +int sctp_v6_init(void); +void sctp_v6_exit(void); +void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, __u32 info); #else /* #ifdef defined(CONFIG_IPV6) */ @@ -348,7 +360,6 @@ static inline sctp_assoc_t sctp_assoc2id return (sctp_assoc_t) asoc; } - /* Look up the association by its id. */ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id); @@ -399,6 +410,12 @@ static inline struct list_head *sctp_lis return result; } +/* Tests if the list has one and only one entry. */ +static inline int sctp_list_single_entry(struct list_head *head) +{ + return ((head->next != head) && (head->next == head->prev)); +} + /* Calculate the size (in bytes) occupied by the data of an iovec. */ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) { @@ -418,6 +435,10 @@ static inline __s32 sctp_jitter(__u32 rt static __u32 sctp_rand; __s32 ret; + /* Avoid divide by zero. */ + if (!rto) + rto = 1; + sctp_rand += jiffies; sctp_rand ^= (sctp_rand << 12); sctp_rand ^= (sctp_rand >> 20); @@ -430,12 +451,16 @@ static inline __s32 sctp_jitter(__u32 rt } /* Break down data chunks at this point. */ -static inline int sctp_frag_point(int pmtu) +static inline int sctp_frag_point(const struct sctp_opt *sp, int pmtu) { - pmtu -= SCTP_IP_OVERHEAD + sizeof(struct sctp_data_chunk); - pmtu -= sizeof(struct sctp_sack_chunk); + int frag = pmtu; + frag -= SCTP_IP_OVERHEAD + sizeof(struct sctp_data_chunk); + frag -= sizeof(struct sctp_sack_chunk); + + if (sp->user_frag) + frag = min_t(int, frag, sp->user_frag); - return pmtu; + return frag; } /* Walk through a list of TLV parameters. Don't trust the @@ -444,7 +469,7 @@ static inline int sctp_frag_point(int pm * there is room for a param header too. */ #define sctp_walk_params(pos, chunk, member)\ -_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) +_sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member) #define _sctp_walk_params(pos, chunk, end, member)\ for (pos.v = chunk->member;\ @@ -452,6 +477,18 @@ for (pos.v = chunk->member;\ pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \ pos.v += WORD_ROUND(ntohs(pos.p->length))) +#define sctp_walk_errors(err, chunk_hdr)\ +_sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) + +#define _sctp_walk_errors(err, chunk_hdr, end)\ +for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ + sizeof(sctp_chunkhdr_t));\ + (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ + (void *)err <= (void *)chunk_hdr + end - \ + WORD_ROUND(ntohs(err->length));\ + err = (sctp_errhdr_t *)((void *)err + \ + WORD_ROUND(ntohs(err->length)))) + /* Round an int up to the next multiple of 4. */ #define WORD_ROUND(s) (((s)+3)&~3) @@ -462,37 +499,28 @@ for (pos.v = chunk->member;\ #define tv_lt(s, t) \ (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec)) -/* Stolen from net/profile.h. Using it from there is more grief than - * it is worth. - */ -static inline void tv_add(const struct timeval *entered, struct timeval *leaved) -{ - time_t usecs = leaved->tv_usec + entered->tv_usec; - time_t secs = leaved->tv_sec + entered->tv_sec; - - if (usecs >= 1000000) { - usecs -= 1000000; - secs++; - } - leaved->tv_sec = secs; - leaved->tv_usec = usecs; -} - +/* Add tv1 to tv2. */ +#define TIMEVAL_ADD(tv1, tv2) \ +({ \ + suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \ + time_t secs = (tv2).tv_sec + (tv1).tv_sec; \ +\ + if (usecs >= 1000000) { \ + usecs -= 1000000; \ + secs++; \ + } \ + (tv2).tv_sec = secs; \ + (tv2).tv_usec = usecs; \ +}) /* External references. */ extern struct proto sctp_prot; extern struct proc_dir_entry *proc_net_sctp; -extern void sctp_put_port(struct sock *sk); +void sctp_put_port(struct sock *sk); /* Static inline functions. */ -/* Return the SCTP protocol structure. */ -static inline struct sctp_protocol *sctp_get_protocol(void) -{ - return &sctp_proto; -} - /* Convert from an IP version number to an Address Family symbol. */ static inline int ipver2af(__u8 ipver) { @@ -506,6 +534,19 @@ static inline int ipver2af(__u8 ipver) }; } +/* Convert from an address parameter type to an address family. */ +static inline int param_type2af(__u16 type) +{ + switch (type) { + case SCTP_PARAM_IPV4_ADDRESS: + return AF_INET; + case SCTP_PARAM_IPV6_ADDRESS: + return AF_INET6; + default: + return 0; + }; +} + /* Perform some sanity checks. */ static inline int sctp_sanity_check(void) { @@ -520,24 +561,21 @@ static inline int sctp_sanity_check(void /* This is the hash function for the SCTP port hash table. */ static inline int sctp_phashfn(__u16 lport) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); - return (lport & (sctp_proto->port_hashsize - 1)); + return (lport & (sctp_port_hashsize - 1)); } /* This is the hash function for the endpoint hash table. */ static inline int sctp_ep_hashfn(__u16 lport) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); - return (lport & (sctp_proto->ep_hashsize - 1)); + return (lport & (sctp_ep_hashsize - 1)); } /* This is the hash function for the association hash table. */ static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); int h = (lport << 16) + rport; h ^= h>>8; - return (h & (sctp_proto->assoc_hashsize - 1)); + return (h & (sctp_assoc_hashsize - 1)); } /* This is the hash function for the association hash table. This is @@ -546,10 +584,53 @@ static inline int sctp_assoc_hashfn(__u1 */ static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); int h = (lport << 16) + rport; h ^= vtag; - return (h & (sctp_proto->assoc_hashsize-1)); + return (h & (sctp_assoc_hashsize-1)); +} + +#define sctp_sk(__sk) (&(((struct sock *)__sk)->tp_pinfo.af_sctp)) +#define sctp_opt2sk(__sp) container_of(__sp, struct sock, tp_pinfo.af_sctp) + +/* Is a socket of this style? */ +#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) +int static inline __sctp_style(const struct sock *sk, sctp_socket_type_t style) +{ + return sctp_sk(sk)->type == style; +} + +/* Is the association in this state? */ +#define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state)) +int static inline __sctp_state(const struct sctp_association *asoc, + sctp_state_t state) +{ + return asoc->state == state; +} + +/* Is the socket in this state? */ +#define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state)) +int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state) +{ + return sk->sk_state == state; +} + +/* Map v4-mapped v6 address back to v4 address */ +static inline void sctp_v6_map_v4(union sctp_addr *addr) +{ + addr->v4.sin_family = AF_INET; + addr->v4.sin_port = addr->v6.sin6_port; + addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3]; +} + +/* Map v4 address to v4-mapped v6 address */ +static inline void sctp_v4_map_v6(union sctp_addr *addr) +{ + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = addr->v4.sin_port; + addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr; + addr->v6.sin6_addr.s6_addr32[0] = 0; + addr->v6.sin6_addr.s6_addr32[1] = 0; + addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff); } #endif /* __net_sctp_h__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/sm.h linux-2.4.26-pre1/include/net/sctp/sm.h --- linux-2.4.25/include/net/sctp/sm.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/sm.h 2004-02-25 15:42:27.000000000 +0000 @@ -1,15 +1,11 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * - * This file is part of the implementation of the add-IP extension, - * based on June 29, 2001, - * for the SCTP kernel reference Implementation. - * * These are definitions needed by the state machine. * * The SCTP reference implementation is free software; @@ -45,12 +41,12 @@ * Sridhar Samudrala * Daisy Chang * Ardelle Fan + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ - #include #include #include @@ -89,7 +85,7 @@ typedef sctp_disposition_t (sctp_state_f typedef void (sctp_timer_event_t) (unsigned long); typedef struct { sctp_state_fn_t *fn; - char *name; + const char *name; } sctp_sm_table_entry_t; /* A naming convention of "sctp_sf_xxx" applies to all the state functions @@ -122,6 +118,7 @@ sctp_state_fn_t sctp_sf_tabort_8_4_8; sctp_state_fn_t sctp_sf_operr_notify; sctp_state_fn_t sctp_sf_t1_timer_expire; sctp_state_fn_t sctp_sf_t2_timer_expire; +sctp_state_fn_t sctp_sf_t4_timer_expire; sctp_state_fn_t sctp_sf_t5_timer_expire; sctp_state_fn_t sctp_sf_sendbeat_8_3; sctp_state_fn_t sctp_sf_beat_8_3; @@ -142,6 +139,8 @@ sctp_state_fn_t sctp_sf_unk_chunk; sctp_state_fn_t sctp_sf_do_8_5_1_E_sa; sctp_state_fn_t sctp_sf_cookie_echoed_err; sctp_state_fn_t sctp_sf_do_5_2_6_stale; +sctp_state_fn_t sctp_sf_do_asconf; +sctp_state_fn_t sctp_sf_do_asconf_ack; /* Prototypes for primitive event state functions. */ sctp_state_fn_t sctp_sf_do_prm_asoc; @@ -159,6 +158,7 @@ sctp_state_fn_t sctp_sf_error_closed; sctp_state_fn_t sctp_sf_error_shutdown; sctp_state_fn_t sctp_sf_ignore_primitive; sctp_state_fn_t sctp_sf_do_prm_requestheartbeat; +sctp_state_fn_t sctp_sf_do_prm_asconf; /* Prototypes for other event state functions. */ sctp_state_fn_t sctp_sf_do_9_2_start_shutdown; @@ -181,9 +181,6 @@ sctp_state_fn_t sctp_sf_do_9_2_reshutack sctp_state_fn_t sctp_sf_do_9_2_reshut; sctp_state_fn_t sctp_sf_do_9_2_shutack; -sctp_state_fn_t lucky; -sctp_state_fn_t other_stupid; - /* Prototypes for timeout event state functions. Not in use. */ sctp_state_fn_t sctp_do_4_2_reinit; sctp_state_fn_t sctp_do_4_3_reecho; @@ -192,15 +189,11 @@ sctp_state_fn_t sctp_do_9_2_reshutack; sctp_state_fn_t sctp_do_8_3_hb_err; sctp_state_fn_t sctp_heartoff; -/* Prototypes for addip related state functions. Not in use. */ -sctp_state_fn_t sctp_addip_do_asconf; -sctp_state_fn_t sctp_addip_do_asconf_ack; - /* Prototypes for utility support functions. */ __u8 sctp_get_chunk_type(struct sctp_chunk *chunk); -sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, - sctp_state_t state, - sctp_subtype_t event_subtype); +const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t, + sctp_state_t, + sctp_subtype_t); int sctp_chunk_iif(const struct sctp_chunk *); struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *, struct sctp_chunk *, @@ -209,71 +202,84 @@ __u32 sctp_generate_verification_tag(voi void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag); /* Prototypes for chunk-building functions. */ -sctp_chunk_t *sctp_make_init(const struct sctp_association *, - const sctp_bind_addr_t *, +struct sctp_chunk *sctp_make_init(const struct sctp_association *, + const struct sctp_bind_addr *, int gfp, int vparam_len); -sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *, - const sctp_chunk_t *, +struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *, + const struct sctp_chunk *, const int gfp, const int unkparam_len); -sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *, - const sctp_chunk_t *); -sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *, - const sctp_chunk_t *); -sctp_chunk_t *sctp_make_cwr(const struct sctp_association *, +struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *, + const struct sctp_chunk *); +struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *, + const struct sctp_chunk *); +struct sctp_chunk *sctp_make_cwr(const struct sctp_association *, const __u32 lowest_tsn, - const sctp_chunk_t *); -sctp_chunk_t *sctp_make_datafrag(struct sctp_association *, + const struct sctp_chunk *); +struct sctp_chunk *sctp_make_datafrag(struct sctp_association *, const struct sctp_sndrcvinfo *sinfo, int len, const __u8 *data, __u8 flags, __u16 ssn); -sctp_chunk_t * sctp_make_datafrag_empty(struct sctp_association *, +struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *, const struct sctp_sndrcvinfo *sinfo, int len, const __u8 flags, __u16 ssn); -sctp_chunk_t *sctp_make_data(struct sctp_association *, +struct sctp_chunk *sctp_make_data(struct sctp_association *, const struct sctp_sndrcvinfo *sinfo, int len, const __u8 *data); -sctp_chunk_t *sctp_make_data_empty(struct sctp_association *, +struct sctp_chunk *sctp_make_data_empty(struct sctp_association *, const struct sctp_sndrcvinfo *, int len); -sctp_chunk_t *sctp_make_ecne(const struct sctp_association *, +struct sctp_chunk *sctp_make_ecne(const struct sctp_association *, const __u32); -sctp_chunk_t *sctp_make_sack(const struct sctp_association *); -sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc); -sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc, - const sctp_chunk_t *); -sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *, - const sctp_chunk_t *); -void sctp_init_cause(sctp_chunk_t *, __u16 cause, const void *, size_t); -sctp_chunk_t *sctp_make_abort(const struct sctp_association *, - const sctp_chunk_t *, +struct sctp_chunk *sctp_make_sack(const struct sctp_association *); +struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc, + const struct sctp_chunk *chunk); +struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc, + const struct sctp_chunk *); +struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, + const struct sctp_chunk *); +void sctp_init_cause(struct sctp_chunk *, __u16 cause, const void *, size_t); +struct sctp_chunk *sctp_make_abort(const struct sctp_association *, + const struct sctp_chunk *, const size_t hint); -sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *, - const sctp_chunk_t *, +struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *, + const struct sctp_chunk *, __u32 tsn); -sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *, - const sctp_chunk_t *, +struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *, + const struct sctp_chunk *, const struct msghdr *); -sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *, +struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *, const struct sctp_transport *, const void *payload, const size_t paylen); -sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *, - const sctp_chunk_t *, +struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *, + const struct sctp_chunk *, const void *payload, const size_t paylen); -sctp_chunk_t *sctp_make_op_error(const struct sctp_association *, - const sctp_chunk_t *chunk, +struct sctp_chunk *sctp_make_op_error(const struct sctp_association *, + const struct sctp_chunk *chunk, __u16 cause_code, const void *payload, size_t paylen); -void sctp_chunk_assign_tsn(sctp_chunk_t *); -void sctp_chunk_assign_ssn(sctp_chunk_t *); -int sctp_datachunks_from_user(struct sctp_association *, - const struct sctp_sndrcvinfo *, - struct msghdr *, int len, - struct sk_buff_head *); +struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, + union sctp_addr *addr, + int vparam_len); +struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, + union sctp_addr *, + struct sockaddr *, + int, __u16); +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr); +struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc, + __u32 serial, int vparam_len); +struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + struct sctp_chunk *asconf); +int sctp_process_asconf_ack(struct sctp_association *asoc, + struct sctp_chunk *asconf_ack); + +void sctp_chunk_assign_tsn(struct sctp_chunk *); +void sctp_chunk_assign_ssn(struct sctp_chunk *); /* Prototypes for statetable processing. */ @@ -294,24 +300,17 @@ int sctp_side_effects(sctp_event_t event int gfp); /* 2nd level prototypes */ -int -sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, - sctp_state_t state, - struct sctp_endpoint *ep, - struct sctp_association *asoc, - void *event_arg, - sctp_disposition_t status, - sctp_cmd_seq_t *retval, - int gfp); +int sctp_cmd_interpreter(sctp_event_t, sctp_subtype_t, sctp_state_t, + struct sctp_endpoint *, struct sctp_association *, + void *event_arg, sctp_disposition_t, + sctp_cmd_seq_t *retval, int gfp); int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *); -void sctp_do_TSNdup(struct sctp_association *, sctp_chunk_t *, long gap); - void sctp_generate_t3_rtx_event(unsigned long peer); void sctp_generate_heartbeat_event(unsigned long peer); -sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *); +sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *); struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *, const struct sctp_association *, struct sctp_chunk *chunk, @@ -321,39 +320,33 @@ struct sctp_packet *sctp_ootb_pkt_new(co const struct sctp_chunk *); void sctp_ootb_pkt_free(struct sctp_packet *); -sctp_cookie_param_t * +struct sctp_cookie_param * sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *, const struct sctp_chunk *, int *cookie_len, const __u8 *, int addrs_len); struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *, const struct sctp_association *, - sctp_chunk_t *, int gfp, int *err, - sctp_chunk_t **err_chk_p); + struct sctp_chunk *, int gfp, int *err, + struct sctp_chunk **err_chk_p); int sctp_addip_addr_config(struct sctp_association *, sctp_param_t, struct sockaddr_storage*, int); void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, const struct sctp_association *asoc, - const sctp_chunk_t *chunk, + const struct sctp_chunk *chunk, sctp_cmd_seq_t *commands, - sctp_chunk_t *err_chunk); + struct sctp_chunk *err_chunk); /* 3rd level prototypes */ __u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *); -/* 4th level prototypes */ -void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *, - __u16 port, int iif); -int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *); -int sockaddr2sctp_addr(const union sctp_addr *, sctp_addr_param_t *); - /* Extern declarations for major data structures. */ -sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); -extern sctp_sm_table_entry_t +const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); +extern const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES]; -extern sctp_sm_table_entry_t +extern const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES]; -extern sctp_sm_table_entry_t +extern const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES]; extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES]; @@ -361,7 +354,7 @@ extern sctp_timer_event_t *sctp_timer_ev /* Get the size of a DATA chunk payload. */ -static inline __u16 sctp_data_size(sctp_chunk_t *chunk) +static inline __u16 sctp_data_size(struct sctp_chunk *chunk) { __u16 size; @@ -438,6 +431,21 @@ static inline int SSN_lte(__u16 s, __u16 return (((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT)); } +/* + * ADDIP 3.1.1 + * The valid range of Serial Number is from 0 to 4294967295 (2**32 - 1). Serial + * Numbers wrap back to 0 after reaching 4294967295. + */ +enum { + ADDIP_SERIAL_SIGN_BIT = (1<<31) +}; + +static inline int ADDIP_SERIAL_gte(__u16 s, __u16 t) +{ + return (((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT)); +} + + /* Run sctp_add_cmd() generating a BUG() if there is a failure. */ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj) { @@ -449,7 +457,7 @@ static inline void sctp_add_cmd_sf(sctp_ * tag and the T bit is set in the Chunk Flags. */ static inline int -sctp_vtag_verify_either(const sctp_chunk_t *chunk, +sctp_vtag_verify_either(const struct sctp_chunk *chunk, const struct sctp_association *asoc) { /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/structs.h linux-2.4.26-pre1/include/net/sctp/structs.h --- linux-2.4.25/include/net/sctp/structs.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/structs.h 2004-02-25 15:44:10.000000000 +0000 @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2003 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -14,7 +14,7 @@ * * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied - * ************************ + * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * @@ -31,18 +31,21 @@ * http://www.sf.net/projects/lksctp * * Written or modified by: - * Randall Stewart - * Ken Morneau - * Qiaobing Xie + * Randall Stewart + * Ken Morneau + * Qiaobing Xie * La Monte H.P. Yarroll - * Karl Knutson - * Jon Grimm - * Xingang Guo - * Hui Huang - * Sridhar Samudrala + * Karl Knutson + * Jon Grimm + * Xingang Guo + * Hui Huang + * Sridhar Samudrala * Daisy Chang - * Dajiang Zhang - * Ardelle Fan + * Dajiang Zhang + * Ardelle Fan + * Ryan Layer + * Anup Pemmaiah + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -54,12 +57,12 @@ #include /* We get struct timespec. */ #include /* linux/in.h needs this!! */ #include /* We get struct sockaddr_in. */ -#include /* We get struct in6_addr */ +#include /* We get struct in6_addr */ #include /* We get MAXHOSTNAMELEN. */ #include /* This gets us atomic counters. */ #include /* We need sk_buff_head. */ -#include /* We need sctp* header structs. */ -#include +#include /* We need tq_struct. */ +#include /* We need sctp* header structs. */ /* A convenience structure for handling sockaddr structures. * We should wean ourselves off this. @@ -70,9 +73,8 @@ union sctp_addr { struct sockaddr sa; }; - /* Forward declarations for data structures. */ -struct sctp_protocol; +struct sctp_globals; struct sctp_endpoint; struct sctp_association; struct sctp_transport; @@ -86,46 +88,45 @@ struct sctp_opt; struct sctp_ep_common; struct sctp_ssnmap; -typedef struct sctp_chunk sctp_chunk_t; -typedef struct sctp_bind_addr sctp_bind_addr_t; +#include #include #include #include /* Structures useful for managing bind/connect. */ -typedef struct sctp_bind_bucket { - unsigned short port; +struct sctp_bind_bucket { + unsigned short port; unsigned short fastreuse; struct sctp_bind_bucket *next; struct sctp_bind_bucket **pprev; struct sock *sk; -} sctp_bind_bucket_t; +}; -typedef struct sctp_bind_hashbucket { +struct sctp_bind_hashbucket { spinlock_t lock; struct sctp_bind_bucket *chain; -} sctp_bind_hashbucket_t; +}; /* Used for hashing all associations. */ -typedef struct sctp_hashbucket { +struct sctp_hashbucket { rwlock_t lock; struct sctp_ep_common *chain; -} sctp_hashbucket_t __attribute__((__aligned__(8))); +} __attribute__((__aligned__(8))); -/* The SCTP protocol structure. */ -struct sctp_protocol { +/* The SCTP globals structure. */ +extern struct sctp_globals { /* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values * * The following protocol parameters are RECOMMENDED: * - * RTO.Initial - 3 seconds - * RTO.Min - 1 second - * RTO.Max - 60 seconds - * RTO.Alpha - 1/8 (3 when converted to right shifts.) - * RTO.Beta - 1/4 (2 when converted to right shifts.) + * RTO.Initial - 3 seconds + * RTO.Min - 1 second + * RTO.Max - 60 seconds + * RTO.Alpha - 1/8 (3 when converted to right shifts.) + * RTO.Beta - 1/4 (2 when converted to right shifts.) */ __u32 rto_initial; __u32 rto_min; @@ -140,24 +141,24 @@ struct sctp_protocol { /* Max.Burst - 4 */ int max_burst; - /* Valid.Cookie.Life - 60 seconds */ + /* Valid.Cookie.Life - 60 seconds */ int valid_cookie_life; /* Whether Cookie Preservative is enabled(1) or not(0) */ int cookie_preserve_enable; /* Association.Max.Retrans - 10 attempts - * Path.Max.Retrans - 5 attempts (per destination address) - * Max.Init.Retransmits - 8 attempts + * Path.Max.Retrans - 5 attempts (per destination address) + * Max.Init.Retransmits - 8 attempts */ int max_retrans_association; int max_retrans_path; int max_retrans_init; - /* HB.interval - 30 seconds */ + /* HB.interval - 30 seconds */ int hb_interval; - /* The following variables are implementation specific. */ + /* The following variables are implementation specific. */ /* Default initialization values to be applied to new associations. */ __u16 max_instreams; @@ -170,102 +171,57 @@ struct sctp_protocol { /* This is the hash of all endpoints. */ int ep_hashsize; - sctp_hashbucket_t *ep_hashbucket; + struct sctp_hashbucket *ep_hashtable; /* This is the hash of all associations. */ int assoc_hashsize; - sctp_hashbucket_t *assoc_hashbucket; + struct sctp_hashbucket *assoc_hashtable; - /* This is the sctp port control hash. */ + /* This is the sctp port control hash. */ int port_hashsize; int port_rover; spinlock_t port_alloc_lock; /* Protects port_rover. */ - sctp_bind_hashbucket_t *port_hashtable; + struct sctp_bind_hashbucket *port_hashtable; /* This is the global local address list. * We actively maintain this complete list of interfaces on * the system by catching routing events. * - * It is a list of struct sockaddr_storage_list. + * It is a list of sctp_sockaddr_entry. */ struct list_head local_addr_list; spinlock_t local_addr_lock; -}; - - -/* - * Pointers to address related SCTP functions. - * (i.e. things that depend on the address family.) - */ -struct sctp_af { - int (*sctp_xmit) (struct sk_buff *skb, - struct sctp_transport *, - int ipfragok); - int (*setsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int optlen); - int (*getsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int *optlen); - struct dst_entry *(*get_dst) (struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*get_saddr) (struct sctp_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*copy_addrlist) (struct list_head *, - struct net_device *); - void (*dst_saddr) (union sctp_addr *saddr, - struct dst_entry *dst, - unsigned short port); - int (*cmp_addr) (const union sctp_addr *addr1, - const union sctp_addr *addr2); - void (*addr_copy) (union sctp_addr *dst, - union sctp_addr *src); - void (*from_skb) (union sctp_addr *, - struct sk_buff *skb, - int saddr); - void (*from_sk) (union sctp_addr *, - struct sock *sk); - void (*to_sk_saddr) (union sctp_addr *, - struct sock *sk); - void (*to_sk_daddr) (union sctp_addr *, - struct sock *sk); - int (*addr_valid) (union sctp_addr *); - sctp_scope_t (*scope) (union sctp_addr *); - void (*inaddr_any) (union sctp_addr *, unsigned short); - int (*is_any) (const union sctp_addr *); - int (*available) (const union sctp_addr *); - int (*skb_iif) (const struct sk_buff *sk); - __u16 net_header_len; - int sockaddr_len; - sa_family_t sa_family; - struct list_head list; -}; - -struct sctp_af *sctp_get_af_specific(sa_family_t); -int sctp_register_af(struct sctp_af *); + + /* Flag to indicate if addip is enabled. */ + int addip_enable; +} sctp_globals; -/* Protocol family functions. */ -struct sctp_pf { - void (*event_msgname)(struct sctp_ulpevent *, char *, int *); - void (*skb_msgname) (struct sk_buff *, char *, int *); - int (*af_supported) (sa_family_t); - int (*cmp_addr) (const union sctp_addr *, - const union sctp_addr *, - struct sctp_opt *); - int (*bind_verify) (struct sctp_opt *, union sctp_addr *); - int (*send_verify) (struct sctp_opt *, union sctp_addr *); - int (*supported_addrs)(const struct sctp_opt *, __u16 *); - struct sock *(*create_accept_sk) (struct sock *sk, - struct sctp_association *asoc); - struct sctp_af *af; -}; +#define sctp_rto_initial (sctp_globals.rto_initial) +#define sctp_rto_min (sctp_globals.rto_min) +#define sctp_rto_max (sctp_globals.rto_max) +#define sctp_rto_alpha (sctp_globals.rto_alpha) +#define sctp_rto_beta (sctp_globals.rto_beta) +#define sctp_max_burst (sctp_globals.max_burst) +#define sctp_valid_cookie_life (sctp_globals.valid_cookie_life) +#define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable) +#define sctp_max_retrans_association (sctp_globals.max_retrans_association) +#define sctp_max_retrans_path (sctp_globals.max_retrans_path) +#define sctp_max_retrans_init (sctp_globals.max_retrans_init) +#define sctp_hb_interval (sctp_globals.hb_interval) +#define sctp_max_instreams (sctp_globals.max_instreams) +#define sctp_max_outstreams (sctp_globals.max_outstreams) +#define sctp_address_families (sctp_globals.address_families) +#define sctp_ep_hashsize (sctp_globals.ep_hashsize) +#define sctp_ep_hashtable (sctp_globals.ep_hashtable) +#define sctp_assoc_hashsize (sctp_globals.assoc_hashsize) +#define sctp_assoc_hashtable (sctp_globals.assoc_hashtable) +#define sctp_port_hashsize (sctp_globals.port_hashsize) +#define sctp_port_rover (sctp_globals.port_rover) +#define sctp_port_alloc_lock (sctp_globals.port_alloc_lock) +#define sctp_port_hashtable (sctp_globals.port_hashtable) +#define sctp_local_addr_list (sctp_globals.local_addr_list) +#define sctp_local_addr_lock (sctp_globals.local_addr_lock) +#define sctp_addip_enable (sctp_globals.addip_enable) /* SCTP Socket type: UDP or TCP style. */ typedef enum { @@ -291,14 +247,21 @@ struct sctp_opt { /* Various Socket Options. */ __u16 default_stream; __u32 default_ppid; + __u16 default_flags; + __u32 default_context; + __u32 default_timetolive; + struct sctp_initmsg initmsg; struct sctp_rtoinfo rtoinfo; struct sctp_paddrparams paddrparam; struct sctp_event_subscribe subscribe; + struct sctp_assocparams assocparams; + int user_frag; __u32 autoclose; __u8 nodelay; __u8 disable_fragments; __u8 pd_mode; + __u8 v4mapped; /* Receive to here while partial delivery is in effect. */ struct sk_buff_head pd_lobby; @@ -315,22 +278,23 @@ struct sctp_opt { * */ -typedef struct sctp_cookie { - /* My : Tag expected in every inbound packet and sent - * Verification: in the INIT or INIT ACK chunk. - * Tag : - */ - __u32 my_vtag; - - /* Peer's : Tag expected in every outbound packet except - * Verification: in the INIT chunk. - * Tag : - */ - __u32 peer_vtag; - - /* The rest of these are not from the spec, but really need to - * be in the cookie. - */ +struct sctp_cookie { + + /* My : Tag expected in every inbound packet and sent + * Verification: in the INIT or INIT ACK chunk. + * Tag : + */ + __u32 my_vtag; + + /* Peer's : Tag expected in every outbound packet except + * Verification: in the INIT chunk. + * Tag : + */ + __u32 peer_vtag; + + /* The rest of these are not from the spec, but really need to + * be in the cookie. + */ /* My Tie Tag : Assist in discovering a restarting association. */ __u32 my_ttag; @@ -338,16 +302,16 @@ typedef struct sctp_cookie { /* Peer's Tie Tag: Assist in discovering a restarting association. */ __u32 peer_ttag; + /* When does this cookie expire? */ + struct timeval expiration; + /* Number of inbound/outbound streams which are set * and negotiated during the INIT process. */ __u16 sinit_num_ostreams; __u16 sinit_max_instreams; - /* When does this cookie expire? */ - struct timeval expiration __attribute__((packed)); - - /* This is the first sequence number I used. */ + /* This is the first sequence number I used. */ __u32 initial_tsn; /* This holds the originating address of the INIT packet. */ @@ -360,38 +324,38 @@ typedef struct sctp_cookie { * the association TCB is re-constructed from the cookie. */ __u32 raw_addr_list_len; - sctp_init_chunk_t peer_init[0]; -} sctp_cookie_t __attribute__((aligned(4))); + struct sctp_init_chunk peer_init[0]; +}; /* The format of our cookie that we send to our peer. */ -typedef struct sctp_signed_cookie { +struct sctp_signed_cookie { __u8 signature[SCTP_SECRET_SIZE]; - sctp_cookie_t c; -} sctp_signed_cookie_t; + struct sctp_cookie c; +}; /* This is another convenience type to allocate memory for address * params for the maximum size and pass such structures around * internally. */ -typedef union { - sctp_ipv4addr_param_t v4; - sctp_ipv6addr_param_t v6; -} sctp_addr_param_t; +union sctp_addr_param { + struct sctp_ipv4addr_param v4; + struct sctp_ipv6addr_param v6; +}; /* A convenience type to allow walking through the various * parameters and avoid casting all over the place. */ union sctp_params { void *v; - sctp_paramhdr_t *p; - sctp_cookie_preserve_param_t *life; - sctp_hostname_param_t *dns; - sctp_cookie_param_t *cookie; - sctp_supported_addrs_param_t *sat; - sctp_ipv4addr_param_t *v4; - sctp_ipv6addr_param_t *v6; - sctp_addr_param_t *addr; + struct sctp_paramhdr *p; + struct sctp_cookie_preserve_param *life; + struct sctp_hostname_param *dns; + struct sctp_cookie_param *cookie; + struct sctp_supported_addrs_param *sat; + struct sctp_ipv4addr_param *v4; + struct sctp_ipv6addr_param *v6; + union sctp_addr_param *addr; }; /* RFC 2960. Section 3.3.5 Heartbeat. @@ -402,10 +366,10 @@ union sctp_params { * HEARTBEAT is sent (see Section 8.3). */ typedef struct sctp_sender_hb_info { - sctp_paramhdr_t param_hdr; + struct sctp_paramhdr param_hdr; union sctp_addr daddr; unsigned long sent_at; -} sctp_sender_hb_info_t __attribute__((packed, aligned(4))); +} sctp_sender_hb_info_t __attribute__((packed)); /* * RFC 2960 1.3.2 Sequenced Delivery within Streams @@ -443,12 +407,129 @@ static inline __u16 sctp_ssn_peek(struct return stream->ssn[id]; } -/* Return the next SSN number for this stream. */ +/* Return the next SSN number for this stream. */ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) { return stream->ssn[id]++; } +/* + * Pointers to address related SCTP functions. + * (i.e. things that depend on the address family.) + */ +struct sctp_af { + int (*sctp_xmit) (struct sk_buff *skb, + struct sctp_transport *, + int ipfragok); + int (*setsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int optlen); + int (*getsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int *optlen); + struct dst_entry *(*get_dst) (struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*get_saddr) (struct sctp_association *asoc, + struct dst_entry *dst, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*copy_addrlist) (struct list_head *, + struct net_device *); + void (*dst_saddr) (union sctp_addr *saddr, + struct dst_entry *dst, + unsigned short port); + int (*cmp_addr) (const union sctp_addr *addr1, + const union sctp_addr *addr2); + void (*addr_copy) (union sctp_addr *dst, + union sctp_addr *src); + void (*from_skb) (union sctp_addr *, + struct sk_buff *skb, + int saddr); + void (*from_sk) (union sctp_addr *, + struct sock *sk); + void (*to_sk_saddr) (union sctp_addr *, + struct sock *sk); + void (*to_sk_daddr) (union sctp_addr *, + struct sock *sk); + void (*from_addr_param) (union sctp_addr *, + union sctp_addr_param *, + __u16 port, int iif); + int (*to_addr_param) (const union sctp_addr *, + union sctp_addr_param *); + int (*addr_valid) (union sctp_addr *, + struct sctp_opt *); + sctp_scope_t (*scope) (union sctp_addr *); + void (*inaddr_any) (union sctp_addr *, unsigned short); + int (*is_any) (const union sctp_addr *); + int (*available) (union sctp_addr *, + struct sctp_opt *); + int (*skb_iif) (const struct sk_buff *sk); + int (*is_ce) (const struct sk_buff *sk); + void (*seq_dump_addr)(struct seq_file *seq, + union sctp_addr *addr); + __u16 net_header_len; + int sockaddr_len; + sa_family_t sa_family; + struct list_head list; +}; + +struct sctp_af *sctp_get_af_specific(sa_family_t); +int sctp_register_af(struct sctp_af *); + +/* Protocol family functions. */ +struct sctp_pf { + void (*event_msgname)(struct sctp_ulpevent *, char *, int *); + void (*skb_msgname) (struct sk_buff *, char *, int *); + int (*af_supported) (sa_family_t, struct sctp_opt *); + int (*cmp_addr) (const union sctp_addr *, + const union sctp_addr *, + struct sctp_opt *); + int (*bind_verify) (struct sctp_opt *, union sctp_addr *); + int (*send_verify) (struct sctp_opt *, union sctp_addr *); + int (*supported_addrs)(const struct sctp_opt *, __u16 *); + struct sock *(*create_accept_sk) (struct sock *sk, + struct sctp_association *asoc); + void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); + struct sctp_af *af; +}; + + +/* Structure to track chunk fragments that have been acked, but peer + * fragments of the same message have not. + */ +struct sctp_datamsg { + /* Chunks waiting to be submitted to lower layer. */ + struct list_head chunks; + /* Chunks that have been transmitted. */ + struct list_head track; + /* Reference counting. */ + atomic_t refcnt; + /* When is this message no longer interesting to the peer? */ + unsigned long expires_at; + /* Did the messenge fail to send? */ + int send_error; + char send_failed; + /* Control whether fragments from this message can expire. */ + char can_expire; +}; + +struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *, + struct sctp_sndrcvinfo *, + struct msghdr *, int len); +struct sctp_datamsg *sctp_datamsg_new(int gfp); +void sctp_datamsg_put(struct sctp_datamsg *); +void sctp_datamsg_hold(struct sctp_datamsg *); +void sctp_datamsg_free(struct sctp_datamsg *); +void sctp_datamsg_track(struct sctp_chunk *); +void sctp_datamsg_assign(struct sctp_datamsg *, struct sctp_chunk *); +void sctp_datamsg_fail(struct sctp_chunk *, int error); +int sctp_datamsg_expires(struct sctp_chunk *); + /* RFC2960 1.4 Key Terms * @@ -463,9 +544,10 @@ struct sctp_chunk { * three elements of struct sk_buff. This allows us to reuse * all the skb_* queue management functions. */ - sctp_chunk_t *next; - sctp_chunk_t *prev; + struct sctp_chunk *next; + struct sctp_chunk *prev; struct sk_buff_head *list; + atomic_t refcnt; /* This is our link to the per-transport transmitted list. */ struct list_head transmitted_list; @@ -490,23 +572,23 @@ struct sctp_chunk { union sctp_params param_hdr; union { __u8 *v; - sctp_datahdr_t *data_hdr; - sctp_inithdr_t *init_hdr; - sctp_sackhdr_t *sack_hdr; - sctp_heartbeathdr_t *hb_hdr; - sctp_sender_hb_info_t *hbs_hdr; - sctp_shutdownhdr_t *shutdown_hdr; - sctp_signed_cookie_t *cookie_hdr; - sctp_ecnehdr_t *ecne_hdr; - sctp_cwrhdr_t *ecn_cwr_hdr; - sctp_errhdr_t *err_hdr; + struct sctp_datahdr *data_hdr; + struct sctp_inithdr *init_hdr; + struct sctp_sackhdr *sack_hdr; + struct sctp_heartbeathdr *hb_hdr; + struct sctp_sender_hb_info *hbs_hdr; + struct sctp_shutdownhdr *shutdown_hdr; + struct sctp_signed_cookie *cookie_hdr; + struct sctp_ecnehdr *ecne_hdr; + struct sctp_cwrhdr *ecn_cwr_hdr; + struct sctp_errhdr *err_hdr; + struct sctp_addiphdr *addip_hdr; } subh; __u8 *chunk_end; - sctp_chunkhdr_t *chunk_hdr; - - sctp_sctphdr_t *sctp_hdr; + struct sctp_chunkhdr *chunk_hdr; + struct sctphdr *sctp_hdr; /* This needs to be recoverable for SCTP_SEND_FAILED events. */ struct sctp_sndrcvinfo sinfo; @@ -520,50 +602,59 @@ struct sctp_chunk { /* We fill this in if we are calculating RTT. */ unsigned long sent_at; - __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */ - __u8 num_times_sent; /* How man times did we send this? */ - __u8 has_tsn; /* Does this chunk have a TSN yet? */ - __u8 has_ssn; /* Does this chunk have a SSN yet? */ - __u8 singleton; /* Was this the only chunk in the packet? */ - __u8 end_of_packet; /* Was this the last chunk in the packet? */ - __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ - __u8 pdiscard; /* Discard the whole packet now? */ - __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ - __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ - __u8 tsn_missing_report; /* Data chunk missing counter. */ - /* What is the origin IP address for this chunk? */ union sctp_addr source; /* Destination address for this chunk. */ union sctp_addr dest; + /* For outbound message, track all fragments for SEND_FAILED. */ + struct sctp_datamsg *msg; + /* For an inbound chunk, this tells us where it came from. * For an outbound chunk, it tells us where we'd like it to - * go. It is NULL if we have no preference. + * go. It is NULL if we have no preference. */ struct sctp_transport *transport; + + __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */ + __u8 resent; /* Has this chunk ever been retransmitted. */ + __u8 has_tsn; /* Does this chunk have a TSN yet? */ + __u8 has_ssn; /* Does this chunk have a SSN yet? */ + __u8 singleton; /* Was this the only chunk in the packet? */ + __u8 end_of_packet; /* Was this the last chunk in the packet? */ + __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ + __u8 pdiscard; /* Discard the whole packet now? */ + __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ + __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ + __u8 tsn_missing_report; /* Data chunk missing counter. */ }; -sctp_chunk_t *sctp_make_chunk(const struct sctp_association *, __u8 type, - __u8 flags, int size); -void sctp_free_chunk(sctp_chunk_t *); -void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data); -sctp_chunk_t *sctp_chunkify(struct sk_buff *, const struct sctp_association *, - struct sock *); -void sctp_init_addrs(sctp_chunk_t *, union sctp_addr *, union sctp_addr *); -const union sctp_addr *sctp_source(const sctp_chunk_t *chunk); +void sctp_chunk_hold(struct sctp_chunk *); +void sctp_chunk_put(struct sctp_chunk *); +int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len, + struct iovec *data); +struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type, + __u8 flags, int size); +void sctp_chunk_free(struct sctp_chunk *); +void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data); +struct sctp_chunk *sctp_chunkify(struct sk_buff *, + const struct sctp_association *, + struct sock *); +void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *, + union sctp_addr *); +const union sctp_addr *sctp_source(const struct sctp_chunk *chunk); /* This is a structure for holding either an IPv6 or an IPv4 address. */ /* sin_family -- AF_INET or AF_INET6 * sin_port -- ordinary port number * sin_addr -- cast to either (struct in_addr) or (struct in6_addr) */ -struct sockaddr_storage_list { +struct sctp_sockaddr_entry { struct list_head list; union sctp_addr a; }; -typedef sctp_chunk_t *(sctp_packet_phandler_t)(struct sctp_association *); +typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *); /* This structure holds lists of chunks as we are assembling for * transmission. @@ -611,22 +702,22 @@ typedef int (sctp_outq_thandler_t)(struc typedef int (sctp_outq_ehandler_t)(struct sctp_outq *); typedef struct sctp_packet *(sctp_outq_ohandler_init_t) (struct sctp_packet *, - struct sctp_transport *, - __u16 sport, - __u16 dport); + struct sctp_transport *, + __u16 sport, + __u16 dport); typedef struct sctp_packet *(sctp_outq_ohandler_config_t) - (struct sctp_packet *, + (struct sctp_packet *, __u32 vtag, int ecn_capable, sctp_packet_phandler_t *get_prepend_chunk); typedef sctp_xmit_t (sctp_outq_ohandler_t)(struct sctp_packet *, - sctp_chunk_t *); + struct sctp_chunk *); typedef int (sctp_outq_ohandler_force_t)(struct sctp_packet *); sctp_outq_ohandler_init_t sctp_packet_init; sctp_outq_ohandler_config_t sctp_packet_config; -sctp_outq_ohandler_t sctp_packet_append_chunk; -sctp_outq_ohandler_t sctp_packet_transmit_chunk; +sctp_outq_ohandler_t sctp_packet_append_chunk; +sctp_outq_ohandler_t sctp_packet_transmit_chunk; sctp_outq_ohandler_force_t sctp_packet_transmit; void sctp_packet_free(struct sctp_packet *); @@ -636,19 +727,19 @@ void sctp_packet_free(struct sctp_packet * * RFC2960 Section 1.4 Key Terms * - * o Transport address: A Transport Address is traditionally defined - * by Network Layer address, Transport Layer protocol and Transport - * Layer port number. In the case of SCTP running over IP, a - * transport address is defined by the combination of an IP address - * and an SCTP port number (where SCTP is the Transport protocol). + * o Transport address: A Transport Address is traditionally defined + * by Network Layer address, Transport Layer protocol and Transport + * Layer port number. In the case of SCTP running over IP, a + * transport address is defined by the combination of an IP address + * and an SCTP port number (where SCTP is the Transport protocol). * * RFC2960 Section 7.1 SCTP Differences from TCP Congestion control * - * o The sender keeps a separate congestion control parameter set for - * each of the destination addresses it can send to (not each - * source-destination pair but for each destination). The parameters - * should decay if the address is not used for a long enough time - * period. + * o The sender keeps a separate congestion control parameter set for + * each of the destination addresses it can send to (not each + * source-destination pair but for each destination). The parameters + * should decay if the address is not used for a long enough time + * period. * */ struct sctp_transport { @@ -657,12 +748,12 @@ struct sctp_transport { /* Reference counting. */ atomic_t refcnt; - int dead; + int dead; /* This is the peer's IP address and port. */ union sctp_addr ipaddr; - /* These are the functions we call to handle LLP stuff. */ + /* These are the functions we call to handle LLP stuff. */ struct sctp_af *af_specific; /* Which association do we belong to? */ @@ -676,33 +767,33 @@ struct sctp_transport { * address list derived from the INIT or INIT ACK chunk, a * number of data elements needs to be maintained including: */ - __u32 rtt; /* This is the most recent RTT. */ + __u32 rtt; /* This is the most recent RTT. */ - /* RTO : The current retransmission timeout value. */ + /* RTO : The current retransmission timeout value. */ __u32 rto; /* RTTVAR : The current RTT variation. */ __u32 rttvar; - /* SRTT : The current smoothed round trip time. */ + /* SRTT : The current smoothed round trip time. */ __u32 srtt; /* RTO-Pending : A flag used to track if one of the DATA - * chunks sent to this address is currently being - * used to compute a RTT. If this flag is 0, - * the next DATA chunk sent to this destination - * should be used to compute a RTT and this flag - * should be set. Every time the RTT - * calculation completes (i.e. the DATA chunk - * is SACK'd) clear this flag. - */ + * chunks sent to this address is currently being + * used to compute a RTT. If this flag is 0, + * the next DATA chunk sent to this destination + * should be used to compute a RTT and this flag + * should be set. Every time the RTT + * calculation completes (i.e. the DATA chunk + * is SACK'd) clear this flag. + */ int rto_pending; /* * These are the congestion stats. */ - /* cwnd : The current congestion window. */ - __u32 cwnd; /* This is the actual cwnd. */ + /* cwnd : The current congestion window. */ + __u32 cwnd; /* This is the actual cwnd. */ /* ssthresh : The current slow start threshold value. */ __u32 ssthresh; @@ -715,7 +806,7 @@ struct sctp_transport { /* Data that has been sent, but not acknowledged. */ __u32 flight_size; - /* PMTU : The current known path MTU. */ + /* PMTU : The current known path MTU. */ __u32 pmtu; /* Destination */ @@ -745,23 +836,23 @@ struct sctp_transport { unsigned long last_time_ecne_reduced; /* active : The current active state of this destination, - * : i.e. DOWN, UP, etc. + * : i.e. DOWN, UP, etc. */ int active; /* hb_allowed : The current heartbeat state of this destination, - * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. + * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. */ int hb_allowed; /* These are the error stats for this destination. */ - /* Error count : The current error count for this destination. */ + /* Error count : The current error count for this destination. */ unsigned short error_count; /* Error : Current error threshold for this destination * Threshold : i.e. what value marks the destination down if - * : errorCount reaches this value. + * : errorCount reaches this value. */ unsigned short error_threshold; @@ -771,10 +862,7 @@ struct sctp_transport { */ int max_retrans; - /* We use this name for debugging output... */ - char *debug_name; - - /* Per : A timer used by each destination. + /* Per : A timer used by each destination. * Destination : * Timer : * @@ -799,6 +887,35 @@ struct sctp_transport { struct list_head send_ready; int malloced; /* Is this structure kfree()able? */ + + /* State information saved for SFR_CACC algorithm. The key + * idea in SFR_CACC is to maintain state at the sender on a + * per-destination basis when a changeover happens. + * char changeover_active; + * char cycling_changeover; + * __u32 next_tsn_at_change; + * char cacc_saw_newack; + */ + struct { + /* An unsigned integer, which stores the next TSN to be + * used by the sender, at the moment of changeover. + */ + __u32 next_tsn_at_change; + + /* A flag which indicates the occurrence of a changeover */ + char changeover_active; + + /* A glag which indicates whether the change of primary is + * the first switch to this destination address during an + * active switch. + */ + char cycling_changeover; + + /* A temporary flag, which is used during the processing of + * a SACK to estimate the causative TSN(s)'s group. + */ + char cacc_saw_newack; + } cacc; }; struct sctp_transport *sctp_transport_new(const union sctp_addr *, int); @@ -831,20 +948,20 @@ struct sctp_inq { /* This is the packet which is currently off the in queue and is * being worked on through the inbound chunk processing. */ - sctp_chunk_t *in_progress; + struct sctp_chunk *in_progress; /* This is the delayed task to finish delivering inbound * messages. */ struct tq_struct immediate; - int malloced; /* Is this structure kfree()able? */ + int malloced; /* Is this structure kfree()able? */ }; struct sctp_inq *sctp_inq_new(void); void sctp_inq_init(struct sctp_inq *); void sctp_inq_free(struct sctp_inq *); -void sctp_inq_push(struct sctp_inq *, sctp_chunk_t *packet); +void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet); struct sctp_chunk *sctp_inq_pop(struct sctp_inq *); void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *); @@ -855,7 +972,7 @@ void sctp_inq_set_th_handler(struct sctp * This structure covers sections 6.3, 6.4, 6.7, 6.8, 6.10, 7., 8.1, * and 8.2 of the v13 draft. * - * It handles retransmissions. The connection to the timeout portion + * It handles retransmissions. The connection to the timeout portion * of the state machine is through sctp_..._timeout() and timeout_handler. * * If you feed it SACKs, it will eat them. @@ -901,23 +1018,26 @@ struct sctp_outq { sctp_outq_ohandler_t *build_output; sctp_outq_ohandler_force_t *force_output; - /* How many unackd bytes do we have in-flight? */ + /* How many unackd bytes do we have in-flight? */ __u32 outstanding_bytes; + /* Corked? */ + char cork; + /* Is this structure empty? */ - int empty; + char empty; /* Are we kfree()able? */ - int malloced; + char malloced; }; struct sctp_outq *sctp_outq_new(struct sctp_association *); void sctp_outq_init(struct sctp_association *, struct sctp_outq *); void sctp_outq_teardown(struct sctp_outq *); void sctp_outq_free(struct sctp_outq*); -int sctp_outq_tail(struct sctp_outq *, sctp_chunk_t *chunk); +int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk); int sctp_outq_flush(struct sctp_outq *, int); -int sctp_outq_sack(struct sctp_outq *, sctp_sackhdr_t *); +int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *); int sctp_outq_is_empty(const struct sctp_outq *); int sctp_outq_set_output_handlers(struct sctp_outq *, sctp_outq_ohandler_init_t init, @@ -926,18 +1046,24 @@ int sctp_outq_set_output_handlers(struct sctp_outq_ohandler_t build, sctp_outq_ohandler_force_t force); void sctp_outq_restart(struct sctp_outq *); + void sctp_retransmit(struct sctp_outq *, struct sctp_transport *, sctp_retransmit_reason_t); void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8); - +int sctp_outq_uncork(struct sctp_outq *); +/* Uncork and flush an outqueue. */ +static inline void sctp_outq_cork(struct sctp_outq *q) +{ + q->cork = 1; +} /* These bind address data fields common between endpoints and associations */ struct sctp_bind_addr { /* RFC 2960 12.1 Parameters necessary for the SCTP instance * - * SCTP Port: The local SCTP port number the endpoint is - * bound to. + * SCTP Port: The local SCTP port number the endpoint is + * bound to. */ __u16 port; @@ -949,19 +1075,24 @@ struct sctp_bind_addr { */ struct list_head address_list; - int malloced; /* Are we kfree()able? */ + int malloced; /* Are we kfree()able? */ }; -sctp_bind_addr_t *sctp_bind_addr_new(int gfp_mask); -void sctp_bind_addr_init(sctp_bind_addr_t *, __u16 port); -void sctp_bind_addr_free(sctp_bind_addr_t *); -int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, +struct sctp_bind_addr *sctp_bind_addr_new(int gfp_mask); +void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port); +void sctp_bind_addr_free(struct sctp_bind_addr *); +int sctp_bind_addr_copy(struct sctp_bind_addr *dest, + const struct sctp_bind_addr *src, sctp_scope_t scope, int gfp,int flags); -int sctp_add_bind_addr(sctp_bind_addr_t *, union sctp_addr *, +int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, int gfp); -int sctp_del_bind_addr(sctp_bind_addr_t *, union sctp_addr *); -int sctp_bind_addr_match(sctp_bind_addr_t *, const union sctp_addr *, +int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); +int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_opt *); +union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, + const union sctp_addr *addrs, + int addrcnt, + struct sctp_opt *opt); union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int *addrs_len, int gfp); int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len, @@ -985,13 +1116,13 @@ typedef enum { * local endpoint. * This common structure is useful for several purposes: * 1) Common interface for lookup routines. - * a) Subfunctions work for either endpoint or association - * b) Single interface to lookup allows hiding the lookup lock rather - * than acquiring it externally. + * a) Subfunctions work for either endpoint or association + * b) Single interface to lookup allows hiding the lookup lock rather + * than acquiring it externally. * 2) Common interface for the inbound chunk handling/state machine. * 3) Common object handling routines for reference counting, etc. * 4) Disentangle association lookup from endpoint lookup, where we - * do not have to find our endpoint to find our association. + * do not have to find our endpoint to find our association. * */ @@ -1010,21 +1141,21 @@ struct sctp_ep_common { * malloced - Do we need to kfree this object? */ atomic_t refcnt; - char dead; - char malloced; + char dead; + char malloced; /* What socket does this endpoint belong to? */ struct sock *sk; /* This is where we receive inbound chunks. */ - struct sctp_inq inqueue; + struct sctp_inq inqueue; /* This substructure includes the defining parameters of the * endpoint: * bind_addr.port is our shared port number. * bind_addr.address_list is our set of local IP addresses. */ - sctp_bind_addr_t bind_addr; + struct sctp_bind_addr bind_addr; /* Protection during address list comparisons. */ rwlock_t addr_lock; @@ -1055,22 +1186,22 @@ struct sctp_endpoint { struct sctp_ep_common base; /* Associations: A list of current associations and mappings - * to the data consumers for each association. This - * may be in the form of a hash table or other - * implementation dependent structure. The data - * consumers may be process identification - * information such as file descriptors, named pipe - * pointer, or table pointers dependent on how SCTP - * is implemented. + * to the data consumers for each association. This + * may be in the form of a hash table or other + * implementation dependent structure. The data + * consumers may be process identification + * information such as file descriptors, named pipe + * pointer, or table pointers dependent on how SCTP + * is implemented. */ /* This is really a list of struct sctp_association entries. */ struct list_head asocs; /* Secret Key: A secret key used by this endpoint to compute - * the MAC. This SHOULD be a cryptographic quality - * random number with a sufficient length. + * the MAC. This SHOULD be a cryptographic quality + * random number with a sufficient length. * Discussion in [RFC1750] can be helpful in - * selection of the key. + * selection of the key. */ __u8 secret_key[SCTP_HOW_MANY_SECRETS][SCTP_SECRET_SIZE]; int current_key; @@ -1080,7 +1211,7 @@ struct sctp_endpoint { /* Default timeouts. */ int timeouts[SCTP_NUM_TIMEOUT_TYPES]; - /* Various thresholds. */ + /* Various thresholds. */ /* Name for debugging output... */ char *debug_name; @@ -1157,11 +1288,11 @@ struct sctp_association { */ __u32 eyecatcher; - /* This is our parent endpoint. */ + /* This is our parent endpoint. */ struct sctp_endpoint *ep; /* These are those association elements needed in the cookie. */ - sctp_cookie_t c; + struct sctp_cookie c; /* This is all information about our peer. */ struct { @@ -1173,11 +1304,11 @@ struct sctp_association { /* transport_addr_list * - * Peer : A list of SCTP transport addresses that the + * Peer : A list of SCTP transport addresses that the * Transport : peer is bound to. This information is derived * Address : from the INIT or INIT ACK and is used to - * List : associate an inbound packet with a given - * : association. Normally this information is + * List : associate an inbound packet with a given + * : association. Normally this information is * : hashed or keyed for quick lookup and access * : of the TCB. * @@ -1193,8 +1324,8 @@ struct sctp_association { /* primary_path * * Primary : This is the current primary destination - * Path : transport address of the peer endpoint. It - * : may also specify a source transport address + * Path : transport address of the peer endpoint. It + * : may also specify a source transport address * : on this endpoint. * * All of these paths live on transport_addr_list. @@ -1233,25 +1364,25 @@ struct sctp_association { /* Pointer to last transport I have sent on. */ struct sctp_transport *last_sent_to; - /* This is the last transport I have received DATA on. */ + /* This is the last transport I have received DATA on. */ struct sctp_transport *last_data_from; /* * Mapping An array of bits or bytes indicating which out of * Array order TSN's have been received (relative to the - * Last Rcvd TSN). If no gaps exist, i.e. no out of - * order packets have been received, this array - * will be set to all zero. This structure may be - * in the form of a circular buffer or bit array. + * Last Rcvd TSN). If no gaps exist, i.e. no out of + * order packets have been received, this array + * will be set to all zero. This structure may be + * in the form of a circular buffer or bit array. * * Last Rcvd : This is the last TSN received in * TSN : sequence. This value is set initially by - * : taking the peer's Initial TSN, received in - * : the INIT or INIT ACK chunk, and subtracting - * : one from it. + * : taking the peer's Initial TSN, received in + * : the INIT or INIT ACK chunk, and subtracting + * : one from it. * * Throughout most of the specification this is called the - * "Cumulative TSN ACK Point". In this case, we + * "Cumulative TSN ACK Point". In this case, we * ignore the advice in 12.2 in favour of the term * used in the bulk of the text. This value is hidden * in tsn_map--we get it by calling sctp_tsnmap_get_ctsn(). @@ -1260,39 +1391,47 @@ struct sctp_association { __u8 _map[sctp_tsnmap_storage_size(SCTP_TSN_MAP_SIZE)]; /* Do we need to sack the peer? */ - __u8 sack_needed; + __u8 sack_needed; /* These are capabilities which our peer advertised. */ - __u8 ecn_capable; /* Can peer do ECN? */ - __u8 ipv4_address; /* Peer understands IPv4 addresses? */ - __u8 ipv6_address; /* Peer understands IPv6 addresses? */ + __u8 ecn_capable; /* Can peer do ECN? */ + __u8 ipv4_address; /* Peer understands IPv4 addresses? */ + __u8 ipv6_address; /* Peer understands IPv6 addresses? */ __u8 hostname_address;/* Peer understands DNS addresses? */ - sctp_inithdr_t i; + + /* Does peer support ADDIP? */ + __u8 asconf_capable; + + /* This mask is used to disable sending the ASCONF chunk + * with specified parameter to peer. + */ + __u16 addip_disabled_mask; + + struct sctp_inithdr i; int cookie_len; void *cookie; - /* ADDIP Extention (ADDIP) --xguo */ - /* minus 1 (ADDIP sec. 4.2 C1) */ + /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. + * C1) ... "Peer-Serial-Number'. This value MUST be initialized to the + * Initial TSN Value minus 1 + */ __u32 addip_serial; } peer; /* State : A state variable indicating what state the * : association is in, i.e. COOKIE-WAIT, - * : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING, - * : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT. + * : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING, + * : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT. * - * Note: No "CLOSED" state is illustrated since if a - * association is "CLOSED" its TCB SHOULD be removed. + * Note: No "CLOSED" state is illustrated since if a + * association is "CLOSED" its TCB SHOULD be removed. * - * In this implementation we DO have a CLOSED + * In this implementation we DO have a CLOSED * state which is used during initiation and shutdown. * - * State takes values from SCTP_STATE_*. + * State takes values from SCTP_STATE_*. */ sctp_state_t state; - /* When did we enter this state? */ - int state_timestamp; - /* The cookie life I award for any cookie. */ struct timeval cookie_life; @@ -1301,12 +1440,6 @@ struct sctp_association { */ int overall_error_count; - /* Overall : The threshold for this association that if - * Error : the Overall Error Count reaches will cause - * Threshold : this association to be torn down. - */ - int overall_error_threshold; - /* These are the association's initial, max, and min RTO values. * These values will be initialized by system defaults, but can * be modified via the SCTP_RTOINFO socket option. @@ -1333,7 +1466,6 @@ struct sctp_association { /* The largest timeout or RTO value to use in attempting an INIT */ __u16 max_init_timeo; - int timeouts[SCTP_NUM_TIMEOUT_TYPES]; struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES]; @@ -1341,19 +1473,19 @@ struct sctp_association { struct sctp_transport *shutdown_last_sent_to; /* Next TSN : The next TSN number to be assigned to a new - * : DATA chunk. This is sent in the INIT or INIT - * : ACK chunk to the peer and incremented each - * : time a DATA chunk is assigned a TSN - * : (normally just prior to transmit or during + * : DATA chunk. This is sent in the INIT or INIT + * : ACK chunk to the peer and incremented each + * : time a DATA chunk is assigned a TSN + * : (normally just prior to transmit or during * : fragmentation). */ __u32 next_tsn; /* * Last Rcvd : This is the last TSN received in sequence. This value - * TSN : is set initially by taking the peer's Initial TSN, - * : received in the INIT or INIT ACK chunk, and - * : subtracting one from it. + * TSN : is set initially by taking the peer's Initial TSN, + * : received in the INIT or INIT ACK chunk, and + * : subtracting one from it. * * Most of RFC 2960 refers to this as the Cumulative TSN Ack Point. */ @@ -1393,7 +1525,7 @@ struct sctp_association { wait_queue_head_t wait; /* Association : The smallest PMTU discovered for all of the - * PMTU : peer's transport addresses. + * PMTU : peer's transport addresses. */ __u32 pmtu; @@ -1401,29 +1533,28 @@ struct sctp_association { __u32 frag_point; /* Ack State : This flag indicates if the next received - * : packet is to be responded to with a - * : SACK. This is initializedto 0. When a packet - * : is received it is incremented. If this value - * : reaches 2 or more, a SACK is sent and the - * : value is reset to 0. Note: This is used only - * : when no DATA chunks are received out of - * : order. When DATA chunks are out of order, - * : SACK's are not delayed (see Section 6). + * : packet is to be responded to with a + * : SACK. This is initializedto 0. When a packet + * : is received it is incremented. If this value + * : reaches 2 or more, a SACK is sent and the + * : value is reset to 0. Note: This is used only + * : when no DATA chunks are received out of + * : order. When DATA chunks are out of order, + * : SACK's are not delayed (see Section 6). */ /* Do we need to send an ack? * When counters[SctpCounterAckState] is above 1 we do! */ int counters[SCTP_NUMBER_COUNTERS]; - struct { - __u16 stream; - __u16 flags; - __u32 ppid; - __u32 context; - __u32 timetolive; - } defaults; + /* Default send parameters. */ + __u16 default_stream; + __u16 default_flags; + __u32 default_ppid; + __u32 default_context; + __u32 default_timetolive; - /* This tracks outbound ssn for a given stream. */ + /* This tracks outbound ssn for a given stream. */ struct sctp_ssnmap *ssnmap; /* All outbound chunks go through this structure. */ @@ -1434,13 +1565,10 @@ struct sctp_association { */ struct sctp_ulpq ulpq; - /* Need to send an ECNE Chunk? */ - int need_ecne; - /* Last TSN that caused an ECNE Chunk to be sent. */ __u32 last_ecne_tsn; - /* Last TSN that caused a CWR Chunk to be sent. */ + /* Last TSN that caused a CWR Chunk to be sent. */ __u32 last_cwr_tsn; /* How many duplicated TSNs have we seen? */ @@ -1449,9 +1577,6 @@ struct sctp_association { /* Number of seconds of idle time before an association is closed. */ __u32 autoclose; - /* Name for debugging output... */ - char *debug_name; - /* These are to support * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses * and Enforcement of Flow and Message Limits" @@ -1459,8 +1584,7 @@ struct sctp_association { * or "ADDIP" for short. */ - /* Is the ADDIP extension enabled for this association? */ - int addip_enable; + /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks * @@ -1476,7 +1600,7 @@ struct sctp_association { * [This is our one-and-only-one ASCONF in flight. If we do * not have an ASCONF in flight, this is NULL.] */ - sctp_chunk_t *addip_last_asconf; + struct sctp_chunk *addip_last_asconf; /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. * @@ -1491,7 +1615,7 @@ struct sctp_association { * [This is our saved ASCONF-ACK. We invalidate it when a new * ASCONF serial number arrives.] */ - sctp_chunk_t *addip_last_asconf_ack; + struct sctp_chunk *addip_last_asconf_ack; /* These ASCONF chunks are waiting to be sent. * @@ -1504,7 +1628,7 @@ struct sctp_association { * * In defining the ASCONF Chunk transfer procedures, it is * essential that these transfers MUST NOT cause congestion - * within the network. To achieve this, we place these + * within the network. To achieve this, we place these * restrictions on the transfer of ASCONF Chunks: * * R1) One and only one ASCONF Chunk MAY be in transit and @@ -1518,20 +1642,20 @@ struct sctp_association { * * * [I really think this is EXACTLY the sort of intelligence - * which already resides in sctp_outq. Please move this - * queue and its supporting logic down there. --piggy] + * which already resides in sctp_outq. Please move this + * queue and its supporting logic down there. --piggy] */ struct sk_buff_head addip_chunks; /* ADDIP Section 4.1 ASCONF Chunk Procedures * * A2) A serial number should be assigned to the Chunk. The - * serial number should be a monotonically increasing - * number. All serial numbers are defined to be initialized at + * serial number SHOULD be a monotonically increasing + * number. The serial number SHOULD be initialized at * the start of the association to the same value as the - * Initial TSN. - * - * [and] + * Initial TSN and every time a new ASCONF chunk is created + * it is incremented by one after assigning the serial number + * to the newly created chunk. * * ADDIP * 3.1.1 Address/Stream Configuration Change Chunk (ASCONF) @@ -1540,13 +1664,16 @@ struct sctp_association { * * This value represents a Serial Number for the ASCONF * Chunk. The valid range of Serial Number is from 0 to - * 4294967295 (2**32 - 1). Serial Numbers wrap back to 0 + * 4294967295 (2^32 - 1). Serial Numbers wrap back to 0 * after reaching 4294967295. */ __u32 addip_serial; - /* Is it a temporary association? */ - __u8 temp; + /* Need to send an ECNE Chunk? */ + char need_ecne; + + /* Is it a temporary association? */ + char temp; }; @@ -1566,7 +1693,7 @@ static inline struct sctp_association *s return asoc; } -/* These are function signatures for manipulating associations. */ +/* These are function signatures for manipulating associations. */ struct sctp_association * @@ -1585,9 +1712,13 @@ struct sctp_transport *sctp_assoc_choose void sctp_assoc_update_retran_path(struct sctp_association *); struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, const union sctp_addr *); +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr); struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, const union sctp_addr *address, const int gfp); +void sctp_assoc_del_peer(struct sctp_association *asoc, + const union sctp_addr *addr); void sctp_assoc_control_transport(struct sctp_association *, struct sctp_transport *, sctp_transport_cmd_t, sctp_sn_error_t); @@ -1603,18 +1734,18 @@ __u32 sctp_association_get_next_tsn(stru __u32 sctp_association_get_tsn_block(struct sctp_association *, int); void sctp_assoc_sync_pmtu(struct sctp_association *); -void sctp_assoc_rwnd_increase(struct sctp_association *, int); -void sctp_assoc_rwnd_decrease(struct sctp_association *, int); +void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned); +void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned); void sctp_assoc_set_primary(struct sctp_association *, struct sctp_transport *); int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, int); int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *, - sctp_cookie_t *, int gfp); + struct sctp_cookie*, int gfp); int sctp_cmp_addr_exact(const union sctp_addr *ss1, - const union sctp_addr *ss2); -sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc); -sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc); + const union sctp_addr *ss2); +struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc); +struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc); /* A convenience structure to parse out SCTP specific CMSGs. */ typedef struct sctp_cmsgs { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/tsnmap.h linux-2.4.26-pre1/include/net/sctp/tsnmap.h --- linux-2.4.25/include/net/sctp/tsnmap.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/tsnmap.h 2004-02-25 15:44:24.000000000 +0000 @@ -1,5 +1,8 @@ -/* SCTP kernel reference Implementation Copyright (C) 1999-2001 - * Cisco, Motorola, Intel, and International Business Machines Corp. +/* SCTP kernel reference Implementation + * Copyright (c) 1999-2000 Cisco, Inc. + * Copyright (c) 1999-2001 Motorola, Inc. + * Copyright (c) 2001-2003 International Business Machines, Corp. + * Copyright (c) 2001 Intel Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -97,13 +100,16 @@ struct sctp_tsnmap { /* Data chunks pending receipt. used by SCTP_STATUS sockopt */ __u16 pending_data; - /* We record duplicate TSNs here. We clear this after + /* Record duplicate TSNs here. We clear this after * every SACK. Store up to SCTP_MAX_DUP_TSNS worth of * information. */ __u32 dup_tsns[SCTP_MAX_DUP_TSNS]; __u16 num_dup_tsns; + /* Record gap ack block information here. */ + struct sctp_gap_ack_block gabs[SCTP_MAX_GABS]; + int malloced; __u8 raw_map[0]; @@ -140,12 +146,18 @@ int sctp_tsnmap_check(const struct sctp_ void sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn); /* Retrieve the Cumulative TSN ACK Point. */ -__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *); +static inline __u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map) +{ + return map->cumulative_tsn_ack_point; +} /* Retrieve the highest TSN we've seen. */ -__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *); +static inline __u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map) +{ + return map->max_tsn_seen; +} -/* How many Duplicate TSNs are stored? */ +/* How many duplicate TSNs are stored? */ static inline __u16 sctp_tsnmap_num_dups(struct sctp_tsnmap *map) { return map->num_dup_tsns; @@ -158,6 +170,27 @@ static inline __u32 *sctp_tsnmap_get_dup return map->dup_tsns; } +/* How many gap ack blocks do we have recorded? */ +__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map); + +/* Refresh the count on pending data. */ +__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map); + +/* Return pointer to gap ack blocks as needed by SACK. */ +static inline struct sctp_gap_ack_block *sctp_tsnmap_get_gabs(struct sctp_tsnmap *map) +{ + return map->gabs; +} + +/* Is there a gap in the TSN map? */ +static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map) +{ + int has_gap; + + has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen); + return has_gap; +} + /* Mark a duplicate TSN. Note: limit the storage of duplicate TSN * information. */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/ulpevent.h linux-2.4.26-pre1/include/net/sctp/ulpevent.h --- linux-2.4.25/include/net/sctp/ulpevent.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/ulpevent.h 2004-02-25 15:45:07.000000000 +0000 @@ -40,6 +40,7 @@ * Jon Grimm * La Monte H.P. Yarroll * Karl Knutson + * Sridhar Samudrala * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -48,8 +49,6 @@ #ifndef __sctp_ulpevent_h__ #define __sctp_ulpevent_h__ -#include - /* A structure to carry information to the ULP (e.g. Sockets API) */ /* Warning: This sits inside an skb.cb[] area. Be very careful of * growing this structure as it is at the maximum limit now. @@ -59,7 +58,6 @@ struct sctp_ulpevent { int msg_flags; int iif; }; -#define event_asoc sndrcvinfo.sinfo_assoc_id /* Retrieve the skb this event sits inside of. */ static inline struct sk_buff *sctp_event2skb(struct sctp_ulpevent *ev) @@ -74,9 +72,10 @@ static inline struct sctp_ulpevent *sctp } struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp); -struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *, int flags); +void sctp_ulpevent_init(struct sctp_ulpevent *, int flags); void sctp_ulpevent_free(struct sctp_ulpevent *); int sctp_ulpevent_is_notification(const struct sctp_ulpevent *); +void sctp_queue_purge_ulpevents(struct sk_buff_head *list); struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( const struct sctp_association *asoc, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sctp/user.h linux-2.4.26-pre1/include/net/sctp/user.h --- linux-2.4.25/include/net/sctp/user.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sctp/user.h 2004-02-25 15:42:56.000000000 +0000 @@ -1,38 +1,39 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 International Business Machines, Corp. - * + * Copyright (c) 2001-2003 International Business Machines, Corp. + * Copyright (c) 2002 Intel Corp. + * * This file is part of the SCTP kernel reference Implementation - * + * * This header represents the structures and constants needed to support - * the SCTP Extension to the Sockets API. - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * the SCTP Extension to the Sockets API. + * + * The SCTP reference implementation is free software; + * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * La Monte H.P. Yarroll * R. Stewart * K. Morneau @@ -40,61 +41,63 @@ * Karl Knutson * Jon Grimm * Daisy Chang - * - * + * Ryan Layer + * Ardelle Fan + * Sridhar Samudrala + * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ -#include -#include #ifndef __net_sctp_user_h__ #define __net_sctp_user_h__ -struct sctp_association; -typedef struct sctp_association * sctp_assoc_t; +#include +#include + +typedef void * sctp_assoc_t; /* The following symbols come from the Sockets API Extensions for - * SCTP . + * SCTP . */ enum sctp_optname { SCTP_RTOINFO, #define SCTP_RTOINFO SCTP_RTOINFO - SCTP_ASSOCRTXINFO, -#define SCTP_ASSOCRTXINFO SCTP_ASSOCRTXINFO + SCTP_ASSOCINFO, +#define SCTP_ASSOCINFO SCTP_ASSOCINFO SCTP_INITMSG, #define SCTP_INITMSG SCTP_INITMSG - SCTP_AUTO_CLOSE, -#define SCTP_AUTO_CLOSE SCTP_AUTO_CLOSE - SCTP_SET_PRIMARY_ADDR, -#define SCTP_SET_PRIMARY_ADDR SCTP_SET_PRIMARY_ADDR + SCTP_NODELAY, /* Get/set nodelay option. */ +#define SCTP_NODELAY SCTP_NODELAY + SCTP_AUTOCLOSE, +#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE SCTP_SET_PEER_PRIMARY_ADDR, #define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR - SCTP_SET_ADAPTATION_LAYER, -#define SCTP_SET_ADAPTATION_LAYER SCTP_SET_ADAPTATION_LAYER - SCTP_SET_STREAM_TIMEOUTS, -#define SCTP_SET_STREAM_TIMEOUTS SCTP_SET_STREAM_TIMEOUTS + SCTP_PRIMARY_ADDR, +#define SCTP_PRIMARY_ADDR SCTP_PRIMARY_ADDR + SCTP_ADAPTION_LAYER, +#define SCTP_ADAPTION_LAYER SCTP_ADAPTION_LAYER SCTP_DISABLE_FRAGMENTS, #define SCTP_DISABLE_FRAGMENTS SCTP_DISABLE_FRAGMENTS - SCTP_SET_PEER_ADDR_PARAMS, -#define SCTP_SET_PEER_ADDR_PARAMS SCTP_SET_PEER_ADDR_PARAMS - SCTP_GET_PEER_ADDR_PARAMS, -#define SCTP_GET_PEER_ADDR_PARAMS SCTP_GET_PEER_ADDR_PARAMS + SCTP_PEER_ADDR_PARAMS, +#define SCTP_PEER_ADDR_PARAMS SCTP_PEER_ADDR_PARAMS + SCTP_DEFAULT_SEND_PARAM, +#define SCTP_DEFAULT_SEND_PARAM SCTP_DEFAULT_SEND_PARAM + SCTP_EVENTS, +#define SCTP_EVENTS SCTP_EVENTS + SCTP_I_WANT_MAPPED_V4_ADDR, /* Turn on/off mapped v4 addresses */ +#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR + SCTP_MAXSEG, /* Get/set maximum fragment. */ +#define SCTP_MAXSEG SCTP_MAXSEG SCTP_STATUS, #define SCTP_STATUS SCTP_STATUS SCTP_GET_PEER_ADDR_INFO, #define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO - SCTP_SET_EVENTS, -#define SCTP_SET_EVENTS SCTP_SET_EVENTS - SCTP_AUTOCLOSE, -#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE - SCTP_SET_DEFAULT_SEND_PARAM, -#define SCTP_SET_DEFAULT_SEND_PARAM SCTP_SET_DEFAULT_SEND_PARAM - SCTP_SOCKOPT_DEBUG_NAME = 42, /* FIXME */ -#define SCTP_SOCKOPT_DEBUG_NAME SCTP_SOCKOPT_DEBUG_NAME - - SCTP_SOCKOPT_BINDX_ADD, /* BINDX requests for adding addresses. */ + /* Internal Socket Options. Some of the sctp library functions are + * implemented using these socket options. + */ + SCTP_SOCKOPT_BINDX_ADD = 100,/* BINDX requests for adding addresses. */ #define SCTP_SOCKOPT_BINDX_ADD SCTP_SOCKOPT_BINDX_ADD SCTP_SOCKOPT_BINDX_REM, /* BINDX requests for removing addresses. */ #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM @@ -108,25 +111,8 @@ enum sctp_optname { #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS - SCTP_NODELAY, /* Get/set nodelay option. */ -#define SCTP_NODELAY SCTP_NODELAY }; - -/* - * 5.2 SCTP msg_control Structures - * - * A key element of all SCTP-specific socket extensions is the use of - * ancillary data to specify and access SCTP-specific data via the - * struct msghdr's msg_control member used in sendmsg() and recvmsg(). - * Fine-grained control over initialization and sending parameters are - * handled with ancillary data. - * - * Each ancillary data item is preceeded by a struct cmsghdr (see - * Section 5.1), which defines the function and purpose of the data - * contained in in the cmsg_data[] member. - */ - /* * 5.2.1 SCTP Initiation Structure (SCTP_INIT) * @@ -147,7 +133,6 @@ struct sctp_initmsg { __u16 sinit_max_init_timeo; }; - /* * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) * @@ -209,7 +194,6 @@ typedef enum sctp_cmsg_type { * following format: * */ - struct sctp_assoc_change { __u16 sac_type; __u16 sac_flags; @@ -262,11 +246,11 @@ struct sctp_paddr_change { * event that happened to the address. They include: */ enum sctp_spc_state { - ADDRESS_AVAILABLE, - ADDRESS_UNREACHABLE, - ADDRESS_REMOVED, - ADDRESS_ADDED, - ADDRESS_MADE_PRIM, + SCTP_ADDR_REACHABLE, + SCTP_ADDR_UNREACHABLE, + SCTP_ADDR_REMOVED, + SCTP_ADDR_ADDED, + SCTP_ADDR_MADE_PRIM, }; @@ -285,7 +269,6 @@ struct sctp_remote_error { __u16 sre_flags; __u32 sre_length; __u16 sre_error; - __u16 sre_len; sctp_assoc_t sre_assoc_id; __u8 sre_data[0]; }; @@ -319,7 +302,6 @@ struct sctp_send_failed { * Note that this does not necessarily mean that the * data was (or was not) successfully delivered. */ - enum sctp_ssf_flags { SCTP_DATA_UNSENT, SCTP_DATA_SENT, @@ -331,7 +313,6 @@ enum sctp_ssf_flags { * When a peer sends a SHUTDOWN, SCTP delivers this notification to * inform the application that it should cease sending data. */ - struct sctp_shutdown_event { __u16 sse_type; __u16 sse_flags; @@ -350,8 +331,8 @@ struct sctp_adaption_event { __u16 sai_type; __u16 sai_flags; __u32 sai_length; - __u32 sai_adaptation_bits; - sctp_assoc_t sse_assoc_id; + __u32 sai_adaption_ind; + sctp_assoc_t sai_assoc_id; }; /* @@ -361,8 +342,7 @@ struct sctp_adaption_event { * message this notification will be used to inidicate * various events. */ - -struct sctp_rcv_pdapi_event { +struct sctp_pdapi_event { __u16 pdapi_type; __u16 pdapi_flags; __u32 pdapi_length; @@ -399,14 +379,14 @@ union sctp_notification { __u16 sn_type; /* Notification type. */ __u16 sn_flags; __u32 sn_length; - } h; + } sn_header; struct sctp_assoc_change sn_assoc_change; - struct sctp_paddr_change sn_padr_change; + struct sctp_paddr_change sn_paddr_change; struct sctp_remote_error sn_remote_error; struct sctp_send_failed sn_send_failed; struct sctp_shutdown_event sn_shutdown_event; struct sctp_adaption_event sn_adaption_event; - struct sctp_rcv_pdapi_event sn_rcv_pdapi_event; + struct sctp_pdapi_event sn_pdapi_event; }; /* Section 5.3.1 @@ -443,102 +423,110 @@ typedef enum sctp_sn_error { } sctp_sn_error_t; /* - * - * 7.1.14 Peer Address Parameters - * - * Applications can enable or disable heartbeats for any peer address - * of an association, modify an address's heartbeat interval, force a - * heartbeat to be sent immediately, and adjust the address's maximum - * number of retransmissions sent before an address is considered - * unreachable. The following structure is used to access and modify an - * address's parameters: - */ - -struct sctp_paddrparams { - struct sockaddr_storage spp_address; - __u32 spp_hbinterval; - __u16 spp_pathmaxrxt; - sctp_assoc_t spp_assoc_id; -}; - -/* - * 7.2.2 Peer Address Information - * - * Applications can retrieve information about a specific peer address - * of an association, including its reachability state, congestion - * window, and retransmission timer values. This information is - * read-only. The following structure is used to access this - * information: - */ - -struct sctp_paddrinfo { - sctp_assoc_t spinfo_assoc_id; - struct sockaddr_storage spinfo_address; - __s32 spinfo_state; - __u32 spinfo_cwnd; - __u32 spinfo_srtt; - __u32 spinfo_rto; - __u32 spinfo_mtu; -}; - - -/* * 7.1.1 Retransmission Timeout Parameters (SCTP_RTOINFO) * * The protocol parameters used to initialize and bound retransmission * timeout (RTO) are tunable. See [SCTP] for more information on how - * these parameters are used in RTO calculation. The peer address - * parameter is ignored for TCP style socket. + * these parameters are used in RTO calculation. */ - struct sctp_rtoinfo { + sctp_assoc_t srto_assoc_id; __u32 srto_initial; __u32 srto_max; __u32 srto_min; - sctp_assoc_t srto_assoc_id; }; /* - * 7.1.2 Association Retransmission Parameter (SCTP_ASSOCRTXINFO) + * 7.1.2 Association Parameters (SCTP_ASSOCINFO) * - * The protocol parameter used to set the number of retransmissions - * sent before an association is considered unreachable. - * See [SCTP] for more information on how this parameter is used. The - * peer address parameter is ignored for TCP style socket. + * This option is used to both examine and set various association and + * endpoint parameters. */ - struct sctp_assocparams { - __u16 sasoc_asocmaxrxt; sctp_assoc_t sasoc_assoc_id; + __u16 sasoc_asocmaxrxt; + __u16 sasoc_number_peer_destinations; + __u32 sasoc_peer_rwnd; + __u32 sasoc_local_rwnd; + __u32 sasoc_cookie_life; }; - /* - * 7.1.9 Set Primary Address (SCTP_SET_PRIMARY_ADDR) + * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) * * Requests that the peer mark the enclosed address as the association * primary. The enclosed address must be one of the association's * locally bound addresses. The following structure is used to make a * set primary request: */ - -struct sctp_setprim { - struct sockaddr_storage ssp_addr; - sctp_assoc_t ssp_assoc_id; +struct sctp_setpeerprim { + sctp_assoc_t sspp_assoc_id; + struct sockaddr_storage sspp_addr; }; /* - * 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) + * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary. The enclosed address must be one of the * association peer's addresses. The following structure is used to * make a set peer primary request: */ +struct sctp_prim { + sctp_assoc_t ssp_assoc_id; + struct sockaddr_storage ssp_addr; +}; -struct sctp_setpeerprim { - struct sockaddr_storage sspp_addr; - sctp_assoc_t sspp_assoc_id; +/* + * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER) + * + * Requests that the local endpoint set the specified Adaption Layer + * Indication parameter for all future INIT and INIT-ACK exchanges. + */ +struct sctp_setadaption { + __u32 ssb_adaption_ind; +}; + +/* + * 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS) + * + * Applications can enable or disable heartbeats for any peer address + * of an association, modify an address's heartbeat interval, force a + * heartbeat to be sent immediately, and adjust the address's maximum + * number of retransmissions sent before an address is considered + * unreachable. The following structure is used to access and modify an + * address's parameters: + */ +struct sctp_paddrparams { + sctp_assoc_t spp_assoc_id; + struct sockaddr_storage spp_address; + __u32 spp_hbinterval; + __u16 spp_pathmaxrxt; +}; + +/* + * 7.2.2 Peer Address Information + * + * Applications can retrieve information about a specific peer address + * of an association, including its reachability state, congestion + * window, and retransmission timer values. This information is + * read-only. The following structure is used to access this + * information: + */ +struct sctp_paddrinfo { + sctp_assoc_t spinfo_assoc_id; + struct sockaddr_storage spinfo_address; + __s32 spinfo_state; + __u32 spinfo_cwnd; + __u32 spinfo_srtt; + __u32 spinfo_rto; + __u32 spinfo_mtu; +}; + +/* Peer addresses's state. */ +enum sctp_spinfo_state { + SCTP_INACTIVE, + SCTP_ACTIVE, }; /* @@ -562,40 +550,16 @@ struct sctp_status { struct sctp_paddrinfo sstat_primary; }; - /* - * 7.1.12 Set Adaption Layer Indicator - * - * Requests that the local endpoint set the specified Adaption Layer - * Indication parameter for all future - * INIT and INIT-ACK exchanges. - */ - -struct sctp_setadaption { - __u32 ssb_adaption_ind; -}; - -/* - * 7.1.12 Set default message time outs (SCTP_SET_STREAM_TIMEOUTS) - * - * This option requests that the requested stream apply a - * default time-out for messages in queue. - */ -struct sctp_setstrm_timeout { - sctp_assoc_t ssto_assoc_id; - __u32 ssto_timeout; - __u16 ssto_streamid_start; - __u16 ssto_streamid_end; -}; - -/* - * 8.3 8.5 get all peer/local addresses on a socket - * This parameter struct is for getsockopt + * 8.3, 8.5 get all peer/local addresses in an association. + * This parameter struct is used by SCTP_GET_PEER_ADDRS and + * SCTP_GET_LOCAL_ADDRS socket options used internally to implement + * sctp_getpaddrs() and sctp_getladdrs() API. */ struct sctp_getaddrs { sctp_assoc_t assoc_id; int addr_num; - struct sockaddr_storage *addrs; + struct sockaddr *addrs; }; /* These are bit fields for msghdr->msg_flags. See section 5.1. */ @@ -611,8 +575,8 @@ enum sctp_msg_flags { * The flags parameter is formed from the bitwise OR of zero or more of the * following currently defined flags: */ -#define BINDX_ADD_ADDR 0x01 -#define BINDX_REM_ADDR 0x02 +#define SCTP_BINDX_ADD_ADDR 0x01 +#define SCTP_BINDX_REM_ADDR 0x02 /* This is the structure that is passed as an argument(optval) to * getsockopt(SCTP_SOCKOPT_PEELOFF). @@ -623,6 +587,3 @@ typedef struct { } sctp_peeloff_arg_t; #endif /* __net_sctp_user_h__ */ - - - diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/sock.h linux-2.4.26-pre1/include/net/sock.h --- linux-2.4.25/include/net/sock.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/include/net/sock.h 2004-02-25 15:44:14.000000000 +0000 @@ -432,6 +432,20 @@ struct tcp_opt { __u32 frto_highmark; /* snd_nxt when RTO occurred */ unsigned long last_synq_overflow; + +/* TCP Westwood structure */ + struct { + __u32 bw_sample; /* bandwidth sample */ + __u32 bw_ns_est; /* first bandwidth estimation..not too smoothed 8) */ + __u32 bw_est; /* bandwidth estimate */ + __u32 rtt_win_sx; /* here starts a new evaluation... */ + __u32 bk; + __u32 snd_una; /* used for evaluating the number of acked bytes */ + __u32 cumul_ack; + __u32 accounted; + __u32 rtt; + __u32 rtt_min; /* minimum observed RTT */ + } westwood; }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/include/net/tcp.h linux-2.4.26-pre1/include/net/tcp.h --- linux-2.4.25/include/net/tcp.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/include/net/tcp.h 2004-02-25 15:41:19.000000000 +0000 @@ -463,6 +463,7 @@ extern int sysctl_tcp_adv_win_scale; extern int sysctl_tcp_tw_reuse; extern int sysctl_tcp_frto; extern int sysctl_tcp_low_latency; +extern int sysctl_tcp_westwood; extern atomic_t tcp_memory_allocated; extern atomic_t tcp_sockets_allocated; @@ -1863,4 +1864,119 @@ static inline void tcp_mib_init(void) TCP_ADD_STATS_USER(TcpMaxConn, -1); } + +/* TCP Westwood functions and constants */ + +#define TCP_WESTWOOD_INIT_RTT 20*HZ /* maybe too conservative?! */ +#define TCP_WESTWOOD_RTT_MIN HZ/20 /* 50ms */ + +static inline void tcp_westwood_update_rtt(struct tcp_opt *tp, __u32 rtt_seq) +{ + if (sysctl_tcp_westwood) + tp->westwood.rtt = rtt_seq; +} + +void __tcp_westwood_fast_bw(struct sock *, struct sk_buff *); +void __tcp_westwood_slow_bw(struct sock *, struct sk_buff *); + +/* + * This function initializes fields used in TCP Westwood. + * We can't get no information about RTT at this time so + * we are forced to set it to 0. + */ + +static inline void __tcp_init_westwood(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + tp->westwood.bw_sample = 0; + tp->westwood.bw_ns_est = 0; + tp->westwood.bw_est = 0; + tp->westwood.accounted = 0; + tp->westwood.cumul_ack = 0; + tp->westwood.rtt_win_sx = tcp_time_stamp; + tp->westwood.rtt = TCP_WESTWOOD_INIT_RTT; + tp->westwood.rtt_min = TCP_WESTWOOD_INIT_RTT; + tp->westwood.snd_una = tp->snd_una; +} + +static inline void tcp_init_westwood(struct sock *sk) +{ + __tcp_init_westwood(sk); +} + +static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb) +{ + if (sysctl_tcp_westwood) + __tcp_westwood_fast_bw(sk, skb); +} + +static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb) +{ + if (sysctl_tcp_westwood) + __tcp_westwood_slow_bw(sk, skb); +} + +static inline __u32 __tcp_westwood_bw_rttmin(struct tcp_opt *tp) +{ + return (__u32) ((tp->westwood.bw_est) * (tp->westwood.rtt_min) / + (__u32) (tp->mss_cache)); +} + +static inline __u32 tcp_westwood_bw_rttmin(struct tcp_opt *tp) +{ + __u32 ret = 0; + + if (sysctl_tcp_westwood) + ret = (__u32) (max(__tcp_westwood_bw_rttmin(tp), 2U)); + + return ret; +} + +static inline int tcp_westwood_ssthresh(struct tcp_opt *tp) +{ + int ret = 0; + __u32 ssthresh; + + if (sysctl_tcp_westwood) { + if (!(ssthresh = tcp_westwood_bw_rttmin(tp))) + return ret; + + tp->snd_ssthresh = ssthresh; + ret = 1; + } + + return ret; +} + +static inline int tcp_westwood_cwnd(struct tcp_opt *tp) +{ + int ret = 0; + __u32 cwnd; + + if (sysctl_tcp_westwood) { + if (!(cwnd = tcp_westwood_bw_rttmin(tp))) + return ret; + + tp->snd_cwnd = cwnd; + ret = 1; + } + + return ret; +} + +static inline int tcp_westwood_complete_cwr(struct tcp_opt *tp) +{ + int ret = 0; + + if (sysctl_tcp_westwood) { + if (tcp_westwood_cwnd(tp)) { + tp->snd_ssthresh = tp->snd_cwnd; + ret = 1; + } + } + + return ret; +} + #endif /* _TCP_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/lib/Makefile linux-2.4.26-pre1/lib/Makefile --- linux-2.4.25/lib/Makefile 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/lib/Makefile 2004-02-25 15:40:58.000000000 +0000 @@ -42,7 +42,7 @@ include $(TOPDIR)/Rules.make crc32.o: crc32table.h gen_crc32table: gen_crc32table.c - $(HOSTCC) $(HOSTCCFLAGS) -o $@ $< + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< crc32table.h: gen_crc32table ./$< > $@ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/lib/crc32.c linux-2.4.26-pre1/lib/crc32.c --- linux-2.4.25/lib/crc32.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.26-pre1/lib/crc32.c 2004-02-25 15:40:32.000000000 +0000 @@ -1,6 +1,9 @@ -/* +/* * Oct 15, 2000 Matt Domsch * Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks! + * Code was from the public domain, copyright abandoned. Code was + * subsequently included in the kernel, thus was re-licensed under the + * GNU GPL v2. * * Oct 12, 2000 Matt Domsch * Same crc32 function was used in 5 other places in the kernel. @@ -12,7 +15,9 @@ * drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0. * fs/jffs2 uses seed 0, doesn't xor with ~0. * fs/partitions/efi.c uses seed ~0, xor's with ~0. - * + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. */ #include @@ -39,16 +44,10 @@ #define attribute(x) #endif -/* - * This code is in the public domain; copyright abandoned. - * Liability for non-performance of this code is limited to the amount - * you paid for it. Since it is distributed for free, your refund will - * be very very small. If it breaks, you get to keep both pieces. - */ MODULE_AUTHOR("Matt Domsch "); MODULE_DESCRIPTION("Ethernet CRC32 calculations"); -MODULE_LICENSE("GPL and additional rights"); +MODULE_LICENSE("GPL"); #if CRC_LE_BITS == 1 /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/8021q/vlan_dev.c linux-2.4.26-pre1/net/8021q/vlan_dev.c --- linux-2.4.25/net/8021q/vlan_dev.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/net/8021q/vlan_dev.c 2004-02-25 15:44:55.000000000 +0000 @@ -446,6 +446,7 @@ int vlan_dev_hard_start_xmit(struct sk_b */ if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) { + int orig_headroom = skb_headroom(skb); unsigned short veth_TCI; /* This is not a VLAN frame...but we can fix that! */ @@ -455,33 +456,7 @@ int vlan_dev_hard_start_xmit(struct sk_b printk(VLAN_DBG "%s: proto to encap: 0x%hx (hbo)\n", __FUNCTION__, htons(veth->h_vlan_proto)); #endif - - if (skb_headroom(skb) < VLAN_HLEN) { - struct sk_buff *sk_tmp = skb; - skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); - kfree_skb(sk_tmp); - if (skb == NULL) { - stats->tx_dropped++; - return 0; - } - VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++; - } else { - if (!(skb = skb_unshare(skb, GFP_ATOMIC))) { - printk(KERN_ERR "vlan: failed to unshare skbuff\n"); - stats->tx_dropped++; - return 0; - } - } - veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); - - /* Move the mac addresses to the beginning of the new header. */ - memmove(skb->data, skb->data + VLAN_HLEN, 12); - - /* first, the ethernet type */ - /* put_unaligned(__constant_htons(ETH_P_8021Q), &veth->h_vlan_proto); */ - veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); - - /* Now, construct the second two bytes. This field looks something + /* Construct the second two bytes. This field looks something * like: * usr_priority: 3 bits (high bits) * CFI 1 bit @@ -490,10 +465,16 @@ int vlan_dev_hard_start_xmit(struct sk_b veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); - veth->h_vlan_TCI = htons(veth_TCI); - } + skb = __vlan_put_tag(skb, veth_TCI); + if (!skb) { + stats->tx_dropped++; + return 0; + } - skb->dev = VLAN_DEV_INFO(dev)->real_dev; + if (orig_headroom < VLAN_HLEN) { + VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++; + } + } #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: about to send skb: %p to dev: %s\n", @@ -507,6 +488,7 @@ int vlan_dev_hard_start_xmit(struct sk_b stats->tx_packets++; /* for statics only */ stats->tx_bytes += skb->len; + skb->dev = VLAN_DEV_INFO(dev)->real_dev; dev_queue_xmit(skb); return 0; @@ -515,17 +497,22 @@ int vlan_dev_hard_start_xmit(struct sk_b int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = vlan_dev_get_stats(dev); - struct vlan_skb_tx_cookie *cookie; + unsigned short veth_TCI; + + /* Construct the second two bytes. This field looks something + * like: + * usr_priority: 3 bits (high bits) + * CFI 1 bit + * VLAN ID 12 bits (low bits) + */ + veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; + veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); + skb = __vlan_hwaccel_put_tag(skb, veth_TCI); stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev = VLAN_DEV_INFO(dev)->real_dev; - cookie = VLAN_TX_SKB_CB(skb); - cookie->magic = VLAN_TX_COOKIE_MAGIC; - cookie->vlan_tag = (VLAN_DEV_INFO(dev)->vlan_id | - vlan_dev_get_egress_qos_mask(dev, skb)); - dev_queue_xmit(skb); return 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/arp.c linux-2.4.26-pre1/net/ipv4/arp.c --- linux-2.4.25/net/ipv4/arp.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/arp.c 2004-02-25 15:44:44.000000000 +0000 @@ -66,6 +66,10 @@ * Alexey Kuznetsov: new arp state machine; * now it is in net/core/neighbour.c. * Krzysztof Halasa: Added Frame Relay ARP support. + * Shmulik Hen: Split arp_send to arp_create and + * arp_xmit so intermediate drivers like + * bonding can change the skb before + * sending (e.g. insert 8021q tag). */ #include @@ -317,15 +321,40 @@ static void arp_error_report(struct neig static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) { - u32 saddr; + u32 saddr = 0; u8 *dst_ha = NULL; struct net_device *dev = neigh->dev; u32 target = *(u32*)neigh->primary_key; int probes = atomic_read(&neigh->probes); + struct in_device *in_dev = in_dev_get(dev); + + if (!in_dev) + return; - if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL) + switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { + default: + case 0: /* By default announce any local IP */ + if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL) + saddr = skb->nh.iph->saddr; + break; + case 1: /* Restrict announcements of saddr in same subnet */ + if (!skb) + break; saddr = skb->nh.iph->saddr; - else + if (inet_addr_type(saddr) == RTN_LOCAL) { + /* saddr should be known to target */ + if (inet_addr_onlink(in_dev, target, saddr)) + break; + } + saddr = 0; + break; + case 2: /* Avoid secondary IPs, get a primary/preferred one */ + break; + } + + if (in_dev) + in_dev_put(in_dev); + if (!saddr) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); if ((probes -= neigh->parms->ucast_probes) < 0) { @@ -346,6 +375,42 @@ static void arp_solicit(struct neighbour read_unlock_bh(&neigh->lock); } +static int arp_ignore(struct in_device *in_dev, struct net_device *dev, + u32 sip, u32 tip) +{ + int scope; + + switch (IN_DEV_ARP_IGNORE(in_dev)) { + case 0: /* Reply, the tip is already validated */ + return 0; + case 1: /* Reply only if tip is configured on the incoming interface */ + sip = 0; + scope = RT_SCOPE_HOST; + break; + case 2: /* + * Reply only if tip is configured on the incoming interface + * and is in same subnet as sip + */ + scope = RT_SCOPE_HOST; + break; + case 3: /* Do not reply for scope host addresses */ + sip = 0; + scope = RT_SCOPE_LINK; + dev = NULL; + break; + case 4: /* Reserved */ + case 5: + case 6: + case 7: + return 0; + case 8: /* Do not reply */ + return 1; + default: + return 0; + } + return !inet_confirm_addr(dev, sip, tip, scope); +} + static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) { struct rtable *rt; @@ -481,34 +546,26 @@ static inline int arp_fwd_proxy(struct i */ /* - * Create and send an arp packet. If (dest_hw == NULL), we create a broadcast + * Create an arp packet. If (dest_hw == NULL), we create a broadcast * message. */ - -void arp_send(int type, int ptype, u32 dest_ip, - struct net_device *dev, u32 src_ip, - unsigned char *dest_hw, unsigned char *src_hw, - unsigned char *target_hw) +struct sk_buff *arp_create(int type, int ptype, u32 dest_ip, + struct net_device *dev, u32 src_ip, + unsigned char *dest_hw, unsigned char *src_hw, + unsigned char *target_hw) { struct sk_buff *skb; struct arphdr *arp; unsigned char *arp_ptr; /* - * No arp on this interface. - */ - - if (dev->flags&IFF_NOARP) - return; - - /* * Allocate a buffer */ skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4) + dev->hard_header_len + 15, GFP_ATOMIC); if (skb == NULL) - return; + return NULL; skb_reserve(skb, (dev->hard_header_len+15)&~15); skb->nh.raw = skb->data; @@ -588,12 +645,46 @@ void arp_send(int type, int ptype, u32 d arp_ptr+=dev->addr_len; memcpy(arp_ptr, &dest_ip, 4); - /* Send it off, maybe filter it using firewalling first. */ - NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, dev, dev_queue_xmit); - return; + return skb; out: kfree_skb(skb); + return NULL; +} + +/* + * Send an arp packet. + */ +void arp_xmit(struct sk_buff *skb) +{ + /* Send it off, maybe filter it using firewalling first. */ + NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit); +} + +/* + * Create and send an arp packet. + */ +void arp_send(int type, int ptype, u32 dest_ip, + struct net_device *dev, u32 src_ip, + unsigned char *dest_hw, unsigned char *src_hw, + unsigned char *target_hw) +{ + struct sk_buff *skb; + + /* + * No arp on this interface. + */ + + if (dev->flags&IFF_NOARP) + return; + + skb = arp_create(type, ptype, dest_ip, dev, src_ip, + dest_hw, src_hw, target_hw); + if (skb == NULL) { + return; + } + + arp_xmit(skb); } static void parp_redo(struct sk_buff *skb) @@ -756,7 +847,8 @@ int arp_process(struct sk_buff *skb) /* Special case: IPv4 duplicate address detection packet (RFC2131) */ if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && - inet_addr_type(tip) == RTN_LOCAL) + inet_addr_type(tip) == RTN_LOCAL && + !arp_ignore(in_dev,dev,sip,tip)) arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr); goto out; } @@ -771,7 +863,10 @@ int arp_process(struct sk_buff *skb) n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) { int dont_send = 0; - if (IN_DEV_ARPFILTER(in_dev)) + + if (!dont_send) + dont_send |= arp_ignore(in_dev,dev,sip,tip); + if (!dont_send && IN_DEV_ARPFILTER(in_dev)) dont_send |= arp_filter(sip,tip,dev); if (!dont_send) arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/devinet.c linux-2.4.26-pre1/net/ipv4/devinet.c --- linux-2.4.25/net/ipv4/devinet.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/devinet.c 2004-02-25 15:41:56.000000000 +0000 @@ -772,6 +772,84 @@ u32 inet_select_addr(const struct net_de return 0; } +static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst, + u32 local, int scope) +{ + int same = 0; + u32 addr = 0; + + for_ifa(in_dev) { + if (!addr && + (local == ifa->ifa_local || !local) && + ifa->ifa_scope <= scope) { + addr = ifa->ifa_local; + if (same) + break; + } + if (!same) { + same = (!local || inet_ifa_match(local, ifa)) && + (!dst || inet_ifa_match(dst, ifa)); + if (same && addr) { + if (local || !dst) + break; + /* Is the selected addr into dst subnet? */ + if (inet_ifa_match(addr, ifa)) + break; + /* No, then can we use new local src? */ + if (ifa->ifa_scope <= scope) { + addr = ifa->ifa_local; + break; + } + /* search for large dst subnet for addr */ + same = 0; + } + } + } endfor_ifa(in_dev); + + return same? addr : 0; +} + +/* + * Confirm that local IP address exists using wildcards: + * - dev: only on this interface, 0=any interface + * - dst: only in the same subnet as dst, 0=any dst + * - local: address, 0=autoselect the local address + * - scope: maximum allowed scope value for the local address + */ +u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope) +{ + u32 addr = 0; + struct in_device *in_dev; + + if (dev) { + read_lock(&inetdev_lock); + if ((in_dev = __in_dev_get(dev))) { + read_lock(&in_dev->lock); + addr = confirm_addr_indev(in_dev, dst, local, scope); + read_unlock(&in_dev->lock); + } + read_unlock(&inetdev_lock); + + return addr; + } + + read_lock(&dev_base_lock); + read_lock(&inetdev_lock); + for (dev = dev_base; dev; dev = dev->next) { + if ((in_dev = __in_dev_get(dev))) { + read_lock(&in_dev->lock); + addr = confirm_addr_indev(in_dev, dst, local, scope); + read_unlock(&in_dev->lock); + if (addr) + break; + } + } + read_unlock(&inetdev_lock); + read_unlock(&dev_base_lock); + + return addr; +} + /* * Device notifier */ @@ -1012,10 +1090,9 @@ static struct rtnetlink_link inet_rtnetl #ifdef CONFIG_SYSCTL -void inet_forward_change() +void inet_forward_change(int on) { struct net_device *dev; - int on = ipv4_devconf.forwarding; ipv4_devconf.accept_redirects = !on; ipv4_devconf_dflt.forwarding = on; @@ -1046,7 +1123,7 @@ int devinet_sysctl_forward(ctl_table *ct if (write && *valp != val) { if (valp == &ipv4_devconf.forwarding) - inet_forward_change(); + inet_forward_change(*valp); else if (valp != &ipv4_devconf_dflt.forwarding) rt_cache_flush(0); } @@ -1057,7 +1134,7 @@ int devinet_sysctl_forward(ctl_table *ct static struct devinet_sysctl_table { struct ctl_table_header *sysctl_header; - ctl_table devinet_vars[18]; + ctl_table devinet_vars[20]; ctl_table devinet_dev[2]; ctl_table devinet_conf_dir[2]; ctl_table devinet_proto_dir[2]; @@ -1106,6 +1183,12 @@ static struct devinet_sysctl_table {NET_IPV4_CONF_ARPFILTER, "arp_filter", &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV4_CONF_ARP_ANNOUNCE, "arp_announce", + &ipv4_devconf.arp_announce, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_IPV4_CONF_ARP_IGNORE, "arp_ignore", + &ipv4_devconf.arp_ignore, sizeof(int), 0644, NULL, + &proc_dointvec}, {NET_IPV4_CONF_FORCE_IGMP_VERSION, "force_igmp_version", &ipv4_devconf.force_igmp_version, sizeof(int), 0644, NULL, &proc_dointvec}, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_app.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_app.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_app.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_app.c 2004-02-25 15:41:17.000000000 +0000 @@ -20,18 +20,12 @@ * */ -#include #include -#include #include -#include #include #include #include -#include #include -#include -#include #include #include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_conn.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_conn.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_conn.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_conn.c 2004-02-25 15:44:11.000000000 +0000 @@ -24,12 +24,8 @@ * */ -#include #include -#include #include -#include -#include #include #include #include /* for tcphdr */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_ctl.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_ctl.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_ctl.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_ctl.c 2004-02-25 15:42:33.000000000 +0000 @@ -20,12 +20,9 @@ * */ -#include -#include #include #include #include -#include #include #include #include @@ -1694,7 +1691,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cm * len > 128000 is a sanity check. */ if (len < sizeof(struct ip_vs_rule_user)) { - IP_VS_ERR("set_ctl: len %u < %u\n", + IP_VS_ERR("set_ctl: len %u < %Zu\n", len, sizeof(struct ip_vs_rule_user)); return -EINVAL; } else if (len > 128000) { @@ -1972,7 +1969,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm struct ip_vs_get_services get; if (*len < sizeof(get)) { - IP_VS_ERR("length: %u < %u\n", *len, sizeof(get)); + IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(get)); ret = -EINVAL; goto out; } @@ -1981,7 +1978,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm goto out; } if (*len != (sizeof(get)+sizeof(struct ip_vs_service_user)*get.num_services)) { - IP_VS_ERR("length: %u != %u\n", *len, + IP_VS_ERR("length: %u != %Zu\n", *len, sizeof(get)+sizeof(struct ip_vs_service_user)*get.num_services); ret = -EINVAL; goto out; @@ -1996,7 +1993,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm struct ip_vs_service *svc; if (*len != sizeof(get)) { - IP_VS_ERR("length: %u != %u\n", *len, sizeof(get)); + IP_VS_ERR("length: %u != %Zu\n", *len, sizeof(get)); ret = -EINVAL; goto out; } @@ -2030,7 +2027,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm struct ip_vs_get_dests get; if (*len < sizeof(get)) { - IP_VS_ERR("length: %u < %u\n", *len, sizeof(get)); + IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(get)); ret = -EINVAL; goto out; } @@ -2040,7 +2037,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm } if (*len != (sizeof(get) + sizeof(struct ip_vs_dest_user)*get.num_dests)) { - IP_VS_ERR("length: %u != %u\n", *len, + IP_VS_ERR("length: %u != %Zu\n", *len, sizeof(get)+sizeof(struct ip_vs_dest_user)*get.num_dests); ret = -EINVAL; goto out; @@ -2054,7 +2051,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm struct ip_vs_timeout_user u; if (*len < sizeof(u)) { - IP_VS_ERR("length: %u < %u\n", *len, sizeof(u)); + IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(u)); ret = -EINVAL; goto out; } @@ -2069,7 +2066,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cm struct ip_vs_daemon_user u; if (*len < sizeof(u)) { - IP_VS_ERR("length: %u < %u\n", *len, sizeof(u)); + IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(u)); ret = -EINVAL; goto out; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_dh.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_dh.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_dh.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_dh.c 2004-02-25 15:43:10.000000000 +0000 @@ -37,12 +37,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_ftp.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_ftp.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_ftp.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_ftp.c 2004-02-25 15:44:07.000000000 +0000 @@ -24,15 +24,11 @@ * */ -#include #include -#include -#include #include #include #include #include -#include #include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_lblc.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_lblc.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_lblc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_lblc.c 2004-02-25 15:43:22.000000000 +0000 @@ -41,14 +41,10 @@ * me to write this module. */ -#include #include -#include -#include #include -#include -/* for systcl */ +/* for sysctl */ #include #include @@ -69,7 +65,7 @@ * entries that haven't been touched for a day. */ #define COUNT_FOR_FULL_EXPIRATION 30 -int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ; +static int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ; /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_lblcr.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_lblcr.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_lblcr.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_lblcr.c 2004-02-25 15:43:56.000000000 +0000 @@ -39,14 +39,10 @@ * */ -#include #include -#include -#include #include -#include -/* for systcl */ +/* for sysctl */ #include #include /* for proc_net_create/proc_net_remove */ @@ -69,7 +65,7 @@ * entries that haven't been touched for a day. */ #define COUNT_FOR_FULL_EXPIRATION 30 -int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ; +static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ; /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_lc.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_lc.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_lc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_lc.c 2004-02-25 15:42:56.000000000 +0000 @@ -16,12 +16,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_nq.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_nq.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_nq.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_nq.c 2004-02-25 15:41:56.000000000 +0000 @@ -33,12 +33,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_rr.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_rr.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_rr.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_rr.c 2004-02-25 15:44:01.000000000 +0000 @@ -21,12 +21,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sched.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sched.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_sched.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sched.c 2004-02-25 15:42:11.000000000 +0000 @@ -19,10 +19,7 @@ * */ -#include #include -#include -#include #include #include #include /* for local_bh_* */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sed.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sed.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_sed.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sed.c 2004-02-25 15:41:50.000000000 +0000 @@ -37,12 +37,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sh.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sh.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_sh.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sh.c 2004-02-25 15:43:39.000000000 +0000 @@ -34,12 +34,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_sync.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sync.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_sync.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_sync.c 2004-02-25 15:43:55.000000000 +0000 @@ -13,17 +13,9 @@ * through multicast */ -#define __KERNEL_SYSCALLS__ /* for waitpid */ - -#include #include -#include -#include #include #include -#include -#include -#include #include #include @@ -559,8 +551,6 @@ ip_vs_receive(struct socket *sock, char } -static int errno; - static DECLARE_WAIT_QUEUE_HEAD(sync_wait); static pid_t sync_pid = 0; @@ -679,9 +669,9 @@ static int sync_thread(void *startup) set_fs(KERNEL_DS); if (ip_vs_sync_state == IP_VS_STATE_MASTER) - sprintf(current->comm, "ipvs syncmaster"); + sprintf(current->comm, "ipvs_syncmaster"); else if (ip_vs_sync_state == IP_VS_STATE_BACKUP) - sprintf(current->comm, "ipvs syncbackup"); + sprintf(current->comm, "ipvs_syncbackup"); else IP_VS_BUG(); spin_lock_irq(¤t->sigmask_lock); @@ -726,10 +716,19 @@ static int sync_thread(void *startup) static int fork_sync_thread(void *startup) { + pid_t pid; + /* fork the sync thread here, then the parent process of the sync thread is the init process after this thread exits. */ - if (kernel_thread(sync_thread, startup, 0) < 0) - IP_VS_BUG(); + repeat: + if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) { + IP_VS_ERR("could not create sync_thread due to %d... " + "retrying.\n", pid); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); + goto repeat; + } + return 0; } @@ -738,7 +737,6 @@ int start_sync_thread(int state, char *m { DECLARE_COMPLETION(startup); pid_t pid; - int waitpid_result; if (sync_pid) return -EEXIST; @@ -750,12 +748,13 @@ int start_sync_thread(int state, char *m ip_vs_sync_state = state; strcpy(ip_vs_mcast_ifn, mcast_ifn); - if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) - IP_VS_BUG(); - - if ((waitpid_result = waitpid(pid, NULL, __WCLONE)) != pid) { - IP_VS_ERR("%s: waitpid(%d,...) failed, errno %d\n", - __FUNCTION__, pid, -waitpid_result); + repeat: + if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) { + IP_VS_ERR("could not create fork_sync_thread due to %d... " + "retrying.\n", pid); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); + goto repeat; } wait_for_completion(&startup); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_wlc.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_wlc.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_wlc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_wlc.c 2004-02-25 15:45:14.000000000 +0000 @@ -21,12 +21,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/ipvs/ip_vs_wrr.c linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_wrr.c --- linux-2.4.25/net/ipv4/ipvs/ip_vs_wrr.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/ipvs/ip_vs_wrr.c 2004-02-25 15:44:31.000000000 +0000 @@ -20,12 +20,8 @@ * */ -#include #include -#include -#include #include -#include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/sysctl_net_ipv4.c linux-2.4.26-pre1/net/ipv4/sysctl_net_ipv4.c --- linux-2.4.25/net/ipv4/sysctl_net_ipv4.c 2003-06-13 14:51:39.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/sysctl_net_ipv4.c 2004-02-25 15:44:15.000000000 +0000 @@ -52,6 +52,9 @@ static int ip_local_port_range_min[] = { static int ip_local_port_range_max[] = { 65535, 65535 }; #endif +/* From tcp_input.c */ +extern int sysctl_tcp_westwood; + struct ipv4_config ipv4_config; extern ctl_table ipv4_route_table[]; @@ -68,7 +71,7 @@ int ipv4_sysctl_forward(ctl_table *ctl, ret = proc_dointvec(ctl, write, filp, buffer, lenp); if (write && ipv4_devconf.forwarding != val) - inet_forward_change(); + inet_forward_change(ipv4_devconf.forwarding); return ret; } @@ -84,7 +87,7 @@ static int ipv4_sysctl_forward_strategy( if (get_user(new,(int *)newval)) return -EFAULT; if (new != ipv4_devconf.forwarding) - inet_forward_change(); + inet_forward_change(new); return 0; /* caller does change again and handles handles oldval */ } @@ -229,6 +232,9 @@ ctl_table ipv4_table[] = { {NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval", &sysctl_ipfrag_secret_interval, sizeof(int), 0644, NULL, &proc_dointvec_jiffies, &sysctl_jiffies}, + {NET_TCP_WESTWOOD, "tcp_westwood", + &sysctl_tcp_westwood, sizeof(int), 0644, NULL, + &proc_dointvec}, {0} }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv4/tcp_input.c linux-2.4.26-pre1/net/ipv4/tcp_input.c --- linux-2.4.25/net/ipv4/tcp_input.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv4/tcp_input.c 2004-02-25 15:41:48.000000000 +0000 @@ -61,6 +61,7 @@ * Panu Kuhlberg: Experimental audit of TCP (re)transmission * engine. Lots of bugs are found. * Pasi Sarolahti: F-RTO for dealing with spurious RTOs + * Angelo Dell'Aera: TCP Westwood+ support */ #include @@ -89,6 +90,8 @@ int sysctl_tcp_rfc1337 = 0; int sysctl_tcp_max_orphans = NR_FILE; int sysctl_tcp_frto = 0; +int sysctl_tcp_westwood = 0; + #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ #define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */ @@ -470,6 +473,8 @@ static __inline__ void tcp_rtt_estimator tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN); tp->rtt_seq = tp->snd_nxt; } + + tcp_westwood_update_rtt(tp, tp->srtt >> 3); } /* Calculate rto without backoff. This is the second half of Van Jacobson's @@ -1068,7 +1073,9 @@ void tcp_enter_loss(struct sock *sk, int tp->snd_una == tp->high_seq || (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) { tp->prior_ssthresh = tcp_current_ssthresh(tp); - tp->snd_ssthresh = tcp_recalc_ssthresh(tp); + + if (!(tcp_westwood_ssthresh(tp))) + tp->snd_ssthresh = tcp_recalc_ssthresh(tp); } tp->snd_cwnd = 1; tp->snd_cwnd_cnt = 0; @@ -1380,11 +1387,24 @@ static __inline__ void tcp_moderate_cwnd static void tcp_cwnd_down(struct tcp_opt *tp) { int decr = tp->snd_cwnd_cnt + 1; + __u32 limit; + + /* + * TCP Westwood + * Here limit is evaluated as BWestimation*RTTmin (for obtaining it + * in packets we use mss_cache). If sysctl_tcp_westwood is off + * tcp_westwood_bw_rttmin() returns 0. In such case snd_ssthresh is + * still used as usual. It prevents other strange cases in which + * BWE*RTTmin could assume value 0. It should not happen but... + */ + + if (!(limit = tcp_westwood_bw_rttmin(tp))) + limit = tp->snd_ssthresh/2; tp->snd_cwnd_cnt = decr&1; decr >>= 1; - if (decr && tp->snd_cwnd > tp->snd_ssthresh/2) + if (decr && tp->snd_cwnd > limit) tp->snd_cwnd -= decr; tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1); @@ -1528,7 +1548,8 @@ static int tcp_try_undo_loss(struct sock static __inline__ void tcp_complete_cwr(struct tcp_opt *tp) { - tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); + if (!(tcp_westwood_complete_cwr(tp))) + tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); tp->snd_cwnd_stamp = tcp_time_stamp; } @@ -2016,6 +2037,240 @@ static void tcp_process_frto(struct sock tp->frto_counter = (tp->frto_counter + 1) % 3; } +/* + * TCP Westwood + * Functions needed for estimating bandwidth. + */ + +/* + * @westwood_do_filter + * Low-pass filter. Implemented using constant coeffients. + */ + +static inline __u32 westwood_do_filter(__u32 a, __u32 b) +{ + return (((7 * a) + b) >> 3); +} + +static void westwood_filter(struct sock *sk, __u32 delta) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + __u32 sample = (tp->westwood.bk) / delta; + + tp->westwood.bw_ns_est = + westwood_do_filter(tp->westwood.bw_ns_est, sample); + tp->westwood.bw_est = + westwood_do_filter(tp->westwood.bw_est, + tp->westwood.bw_ns_est); + tp->westwood.bw_sample = sample; +} + +/* @westwood_update_rttmin + * It is used to update RTTmin. In this case we MUST NOT use + * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN! + */ + +static inline __u32 westwood_update_rttmin(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + __u32 rttmin = tp->westwood.rtt_min; + + if (tp->westwood.rtt == 0) + return rttmin; + + if (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin) + rttmin = tp->westwood.rtt; + + return rttmin; +} + +/* + * @westwood_acked + * Evaluate increases for dk. It requires no lock since when it is + * called lock should already be held. Be careful about it! + */ + +static __u32 westwood_acked(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + return ((tp->snd_una) - (tp->westwood.snd_una)); +} + +/* + * @westwood_new_window + * It evaluates if we are receiving data inside the same RTT window as + * when we started. + * Return value: + * It returns 0 if we are still evaluating samples in the same RTT + * window, 1 if the sample has to be considered in the next window. + */ + +static int westwood_new_window(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + __u32 left_bound; + __u32 rtt; + int ret = 0; + + left_bound = tp->westwood.rtt_win_sx; + rtt = max(tp->westwood.rtt, (__u32)TCP_WESTWOOD_RTT_MIN); + + /* + * A RTT-window has passed. Be careful since if RTT is less than + * 50ms we don't filter but we continue 'building the sample'. + * This minimum limit was choosen since an estimation on small + * time intervals is better to avoid... + * Obvioulsy on a LAN we reasonably will always have + * right_bound = left_bound + WESTWOOD_RTT_MIN + */ + + if ((left_bound + rtt) < tcp_time_stamp) + ret = 1; + + return ret; +} + +/* + * @westwood_update_window + * It updates RTT evaluation window if it is the right moment to do + * it. If so it calls filter for evaluating bandwidth. Be careful + * about __westwood_update_window() since it is called without + * any form of lock. It should be used only for internal purposes. + * Call westwood_update_window() instead. + */ + +static void __westwood_update_window(struct sock *sk, __u32 now) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + __u32 delta = now - tp->westwood.rtt_win_sx; + + if (!delta) + return; + + if (tp->westwood.rtt) + westwood_filter(sk, delta); + + tp->westwood.bk = 0; + tp->westwood.rtt_win_sx = tcp_time_stamp; +} + +static void westwood_update_window(struct sock *sk, __u32 now) +{ + if (westwood_new_window(sk)) + __westwood_update_window(sk, now); +} + +/* + * @__westwood_fast_bw + * It is called when we are in fast path. In particular it is called when + * header prediction is successfull. In such case infact update is + * straight forward and doesn't need any particular care. + */ + +void __tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + westwood_update_window(sk, tcp_time_stamp); + + tp->westwood.bk += westwood_acked(sk); + tp->westwood.snd_una = tp->snd_una; + tp->westwood.rtt_min = westwood_update_rttmin(sk); +} + +/* + * @westwood_mss + * This function was inserted just to have the possibility to evaluate + * which value of MSS is better. Infact we can use neither mss_cache or + * mss_cache. Just testing we will know it! + */ + +static inline __u32 westwood_mss(struct tcp_opt *tp) +{ + return ((__u32)(tp->mss_cache)); +} + +/* + * @tcp_westwood_dupack_update + * It updates accounted and cumul_ack when receiving a dupack. + */ + +static void westwood_dupack_update(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + tp->westwood.accounted += westwood_mss(tp); + tp->westwood.cumul_ack = westwood_mss(tp); +} + +static inline int westwood_may_change_cumul(struct tcp_opt *tp) +{ + return ((tp->westwood.cumul_ack) > westwood_mss(tp)); +} + +static inline void westwood_partial_update(struct tcp_opt *tp) +{ + tp->westwood.accounted -= tp->westwood.cumul_ack; + tp->westwood.cumul_ack = westwood_mss(tp); +} + +static inline void westwood_complete_update(struct tcp_opt *tp) +{ + tp->westwood.cumul_ack -= tp->westwood.accounted; + tp->westwood.accounted = 0; +} + +/* + * @westwood_acked_count + * This function evaluates cumul_ack for evaluating dk in case of + * delayed or partial acks. + */ + +static __u32 westwood_acked_count(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + tp->westwood.cumul_ack = westwood_acked(sk); + + /* If cumul_ack is 0 this is a dupack since it's not moving + * tp->snd_una. + */ + if (!(tp->westwood.cumul_ack)) + westwood_dupack_update(sk); + + if (westwood_may_change_cumul(tp)) { + /* Partial or delayed ack */ + if ((tp->westwood.accounted) >= (tp->westwood.cumul_ack)) + westwood_partial_update(tp); + else + westwood_complete_update(tp); + } + + tp->westwood.snd_una = tp->snd_una; + + return tp->westwood.cumul_ack; +} + +/* + * @__westwood_slow_bw + * It is called when something is going wrong..even if there could + * be no problems! Infact a simple delayed packet may trigger a + * dupack. But we need to be careful in such case. + */ + +void __tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + westwood_update_window(sk, tcp_time_stamp); + + tp->westwood.bk += westwood_acked_count(sk); + tp->westwood.rtt_min = westwood_update_rttmin(sk); +} + +/* TCP Westwood routines end here */ + /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) { @@ -2042,6 +2297,7 @@ static int tcp_ack(struct sock *sk, stru */ tcp_update_wl(tp, ack, ack_seq); tp->snd_una = ack; + tcp_westwood_fast_bw(sk, skb); flag |= FLAG_WIN_UPDATE; NET_INC_STATS_BH(TCPHPAcks); @@ -2058,6 +2314,8 @@ static int tcp_ack(struct sock *sk, stru if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th)) flag |= FLAG_ECE; + + tcp_westwood_slow_bw(sk, skb); } /* We passed data and got it acked, remove any soft error @@ -3796,7 +4054,6 @@ reset_and_undo: return 1; } - /* * This function implements the receiving procedure of RFC 793 for * all states except ESTABLISHED and TIME_WAIT. @@ -3827,6 +4084,8 @@ int tcp_rcv_state_process(struct sock *s if(tp->af_specific->conn_request(sk, skb) < 0) return 1; + tcp_init_westwood(sk); + /* Now we have several options: In theory there is * nothing else in the frame. KA9Q has an option to * send data with the syn, BSD accepts data with the @@ -3848,6 +4107,8 @@ int tcp_rcv_state_process(struct sock *s goto discard; case TCP_SYN_SENT: + tcp_init_westwood(sk); + queued = tcp_rcv_synsent_state_process(sk, skb, th, len); if (queued >= 0) return queued; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/ipv6/ndisc.c linux-2.4.26-pre1/net/ipv6/ndisc.c --- linux-2.4.25/net/ipv6/ndisc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/ipv6/ndisc.c 2004-02-25 15:43:41.000000000 +0000 @@ -1002,7 +1002,7 @@ static void ndisc_router_discovery(struc */ if (in6_dev->nd_parms) { - __u32 rtime = ntohl(ra_msg->retrans_timer); + unsigned long rtime = ntohl(ra_msg->retrans_timer); if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) { rtime = (rtime*HZ)/1000; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/netsyms.c linux-2.4.26-pre1/net/netsyms.c --- linux-2.4.25/net/netsyms.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/netsyms.c 2004-02-25 15:42:47.000000000 +0000 @@ -261,6 +261,8 @@ EXPORT_SYMBOL(icmp_statistics); EXPORT_SYMBOL(icmp_err_convert); EXPORT_SYMBOL(ip_options_compile); EXPORT_SYMBOL(ip_options_undo); +EXPORT_SYMBOL(arp_create); +EXPORT_SYMBOL(arp_xmit); EXPORT_SYMBOL(arp_send); EXPORT_SYMBOL(arp_broken_ops); EXPORT_SYMBOL(__ip_select_ident); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/Config.in linux-2.4.26-pre1/net/sctp/Config.in --- linux-2.4.25/net/sctp/Config.in 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/Config.in 2004-02-25 15:44:29.000000000 +0000 @@ -12,9 +12,33 @@ fi dep_tristate ' The SCTP Protocol (EXPERIMENTAL)' CONFIG_IP_SCTP $CONFIG_IPV6_SCTP__ if [ "$CONFIG_IP_SCTP" != "n" ]; then - bool ' SCTP: Use old checksum (Adler-32)' CONFIG_SCTP_ADLER32 bool ' SCTP: Debug messages' CONFIG_SCTP_DBG_MSG bool ' SCTP: Debug object counts' CONFIG_SCTP_DBG_OBJCNT fi - +if [ "$CONFIG_CRYPTO_HMAC" = "n" ]; then + choice ' SCTP: Cookie HMAC Algorithm' \ + "HMAC-NONE CONFIG_SCTP_HMAC_NONE" HMAC-NONE +else + if [ "$CONFIG_CRYPTO_MD5" = "n" -a "$CONFIG_CRYPTO_SHA1" = "n" ]; then + choice ' SCTP: Cookie HMAC Algorithm' \ + "HMAC-NONE CONFIG_SCTP_HMAC_NONE" HMAC-NONE + else + if [ "$CONFIG_CRYPTO_MD5" != "n" -a "$CONFIG_CRYPTO_SHA1" != "n" ]; then + choice ' SCTP: Cookie HMAC Algorithm' \ + "HMAC-NONE CONFIG_SCTP_HMAC_NONE \ + HMAC-SHA1 CONFIG_SCTP_HMAC_SHA1 \ + HMAC-MD5 CONFIG_SCTP_HMAC_MD5" HMAC-SHA1 + else + if [ "$CONFIG_CRYPTO_MD5" != "n" ]; then + choice 'SCTP: Cookie HMAC Algorithm' \ + "HMAC-NONE CONFIG_SCTP_HMAC_NONE \ + HMAC-MD5 CONFIG_SCTP_HMAC_MD5" HMAC-MD5 + else + choice 'SCTP: Cookie HMAC Algorithm' \ + "HMAC-NONE CONFIG_SCTP_HMAC_NONE \ + HMAC-SHA1 CONFIG_SCTP_HMAC_SHA1" HMAC-SHA1 + fi + fi + fi +fi endmenu diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/Makefile linux-2.4.26-pre1/net/sctp/Makefile --- linux-2.4.25/net/sctp/Makefile 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/Makefile 2004-02-25 15:42:31.000000000 +0000 @@ -6,16 +6,11 @@ O_TARGET := sctp.o obj-$(CONFIG_IP_SCTP) += sctp.o -obj-y := endpointola.o output.o sm_make_chunk.o associola.o hashdriver.o \ +obj-y := endpointola.o output.o sm_make_chunk.o associola.o \ outqueue.o sm_sideeffect.o transport.o bind_addr.o input.o primitive.o \ sm_statefuns.o tsnmap.o command.o inqueue.o proc.o sm_statetable.o \ - ulpevent.o protocol.o socket.o ulpqueue.o debug.o sla1.o ssnmap.o - -ifeq ($(CONFIG_SCTP_ADLER32), y) -obj-y += adler32.o -else -obj-y += crc32c.o -endif + ulpevent.o protocol.o socket.o ulpqueue.o debug.o ssnmap.o \ + crc32c.o chunk.o obj-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o obj-$(CONFIG_SYSCTL) += sysctl.o diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/associola.c linux-2.4.26-pre1/net/sctp/associola.c --- linux-2.4.25/net/sctp/associola.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/associola.c 2004-02-25 15:42:43.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 La Monte H.P. Yarroll * @@ -41,6 +41,8 @@ * Hui Huang * Sridhar Samudrala * Daisy Chang + * Ryan Layer + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -97,7 +99,6 @@ struct sctp_association *sctp_associatio int gfp) { struct sctp_opt *sp; - struct sctp_protocol *proto = sctp_get_protocol(); int i; /* Retrieve the SCTP per socket area. */ @@ -127,29 +128,30 @@ struct sctp_association *sctp_associatio asoc->base.addr_lock = RW_LOCK_UNLOCKED; asoc->state = SCTP_STATE_CLOSED; - asoc->state_timestamp = jiffies; - - /* Set things that have constant value. */ - asoc->cookie_life.tv_sec = sctp_proto.valid_cookie_life / HZ; - asoc->cookie_life.tv_usec = (sctp_proto.valid_cookie_life % HZ) * - 1000000L / HZ; + /* Set these values from the socket values, a conversion between + * millsecons to seconds/microseconds must also be done. + */ + asoc->cookie_life.tv_sec = sp->assocparams.sasoc_cookie_life / 1000; + asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000) + * 1000; asoc->pmtu = 0; asoc->frag_point = 0; - /* Initialize the default association max_retrans and RTO values. */ - asoc->max_retrans = proto->max_retrans_association; - asoc->rto_initial = proto->rto_initial; - asoc->rto_max = proto->rto_max; - asoc->rto_min = proto->rto_min; + /* Set the association max_retrans and RTO values from the + * socket values. + */ + asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; + asoc->rto_initial = MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial); + asoc->rto_max = MSECS_TO_JIFFIES(sp->rtoinfo.srto_max); + asoc->rto_min = MSECS_TO_JIFFIES(sp->rtoinfo.srto_min); - asoc->overall_error_threshold = 0; asoc->overall_error_count = 0; /* Initialize the maximum mumber of new data packets that can be sent * in a burst. */ - asoc->max_burst = proto->max_burst; + asoc->max_burst = sctp_max_burst; /* Copy things from the endpoint. */ for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) { @@ -166,7 +168,9 @@ struct sctp_association *sctp_associatio asoc->c.sinit_max_instreams = sp->initmsg.sinit_max_instreams; asoc->c.sinit_num_ostreams = sp->initmsg.sinit_num_ostreams; asoc->max_init_attempts = sp->initmsg.sinit_max_attempts; - asoc->max_init_timeo = sp->initmsg.sinit_max_init_timeo * HZ; + + asoc->max_init_timeo = + MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo); /* Allocate storage for the ssnmap after the inbound and outbound * streams have been negotiated during Init. @@ -178,10 +182,10 @@ struct sctp_association *sctp_associatio * RFC 6 - A SCTP receiver MUST be able to receive a minimum of * 1500 bytes in one SCTP packet. */ - if (sk->rcvbuf < SCTP_DEFAULT_MINWINDOW) + if (sk->sk_rcvbuf < SCTP_DEFAULT_MINWINDOW) asoc->rwnd = SCTP_DEFAULT_MINWINDOW; else - asoc->rwnd = sk->rcvbuf; + asoc->rwnd = sk->sk_rcvbuf; asoc->a_rwnd = asoc->rwnd; @@ -220,12 +224,14 @@ struct sctp_association *sctp_associatio * remote endpoint it should do the following: * ... * A2) a serial number should be assigned to the chunk. The serial - * number should be a monotonically increasing number. All serial - * numbers are defined to be initialized at the start of the + * number SHOULD be a monotonically increasing number. The serial + * numbers SHOULD be initialized at the start of the * association to the same value as the initial TSN. */ asoc->addip_serial = asoc->c.initial_tsn; + skb_queue_head_init(&asoc->addip_chunks); + /* Make an empty list of remote transport addresses. */ INIT_LIST_HEAD(&asoc->peer.transport_addr_list); @@ -242,6 +248,11 @@ struct sctp_association *sctp_associatio */ asoc->peer.sack_needed = 1; + /* Assume that the peer recongizes ASCONF until reported otherwise + * via an ERROR chunk. + */ + asoc->peer.asconf_capable = 1; + /* Create an input queue. */ sctp_inq_init(&asoc->base.inqueue); sctp_inq_set_th_handler(&asoc->base.inqueue, @@ -257,17 +268,14 @@ struct sctp_association *sctp_associatio sctp_packet_transmit_chunk, sctp_packet_transmit); - if (NULL == sctp_ulpq_init(&asoc->ulpq, asoc)) + if (!sctp_ulpq_init(&asoc->ulpq, asoc)) goto fail_init; /* Set up the tsn tracking. */ sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, 0); - skb_queue_head_init(&asoc->addip_chunks); - asoc->need_ecne = 0; - asoc->debug_name = "unnamedasoc"; asoc->eyecatcher = SCTP_ASSOC_EYECATCHER; /* Assume that peer would support both address types unless we are @@ -279,6 +287,12 @@ struct sctp_association *sctp_associatio asoc->autoclose = sp->autoclose; + asoc->default_stream = sp->default_stream; + asoc->default_ppid = sp->default_ppid; + asoc->default_flags = sp->default_flags; + asoc->default_context = sp->default_context; + asoc->default_timetolive = sp->default_timetolive; + return asoc; fail_init: @@ -300,9 +314,8 @@ void sctp_association_free(struct sctp_a list_del(&asoc->asocs); /* Decrement the backlog value for a TCP-style listening socket. */ - if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) && - (SCTP_SS_LISTENING == sk->state)) - sk->ack_backlog--; + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) + sk->sk_ack_backlog--; /* Mark as dead, so other users can know this structure is * going away. @@ -349,6 +362,14 @@ void sctp_association_free(struct sctp_a asoc->eyecatcher = 0; + /* Free any cached ASCONF_ACK chunk. */ + if (asoc->addip_last_asconf_ack) + sctp_chunk_free(asoc->addip_last_asconf_ack); + + /* Free any cached ASCONF chunk. */ + if (asoc->addip_last_asconf) + sctp_chunk_free(asoc->addip_last_asconf); + sctp_association_put(asoc); } @@ -381,6 +402,30 @@ void sctp_assoc_set_primary(struct sctp_ */ if (transport->active) asoc->peer.active_path = transport; + + /* + * SFR-CACC algorithm: + * Upon the receipt of a request to change the primary + * destination address, on the data structure for the new + * primary destination, the sender MUST do the following: + * + * 1) If CHANGEOVER_ACTIVE is set, then there was a switch + * to this destination address earlier. The sender MUST set + * CYCLING_CHANGEOVER to indicate that this switch is a + * double switch to the same destination address. + */ + if (transport->cacc.changeover_active) + transport->cacc.cycling_changeover = 1; + + /* 2) The sender MUST set CHANGEOVER_ACTIVE to indicate that + * a changeover has occurred. + */ + transport->cacc.changeover_active = 1; + + /* 3) The sender MUST store the next TSN to be sent in + * next_tsn_at_change. + */ + transport->cacc.next_tsn_at_change = asoc->next_tsn; } /* Add a transport address to an association. */ @@ -392,13 +437,14 @@ struct sctp_transport *sctp_assoc_add_pe struct sctp_opt *sp; unsigned short port; + sp = sctp_sk(asoc->base.sk); + /* AF_INET and AF_INET6 share common port field. */ port = addr->v4.sin_port; /* Set the port if it has not been set yet. */ - if (0 == asoc->peer.port) { + if (0 == asoc->peer.port) asoc->peer.port = port; - } /* Check to see if this is a duplicate. */ peer = sctp_assoc_lookup_paddr(asoc, addr); @@ -427,7 +473,7 @@ struct sctp_transport *sctp_assoc_add_pe SCTP_DEBUG_PRINTK("sctp_assoc_add_peer:association %p PMTU set to " "%d\n", asoc, asoc->pmtu); - asoc->frag_point = sctp_frag_point(asoc->pmtu); + asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); /* The asoc->peer.port might not be meaningful yet, but * initialize the packet structure anyway. @@ -456,30 +502,27 @@ struct sctp_transport *sctp_assoc_add_pe peer->partial_bytes_acked = 0; peer->flight_size = 0; - peer->error_threshold = peer->max_retrans; - /* Update the overall error threshold value of the association - * taking the new peer's error threshold into account. - */ - asoc->overall_error_threshold = - min(asoc->overall_error_threshold + peer->error_threshold, - asoc->max_retrans); - /* By default, enable heartbeat for peer address. */ peer->hb_allowed = 1; /* Initialize the peer's heartbeat interval based on the * sock configured value. */ - sp = sctp_sk(asoc->base.sk); - peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ; + peer->hb_interval = MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval); + + /* Set the path max_retrans. */ + peer->max_retrans = asoc->max_retrans; + + /* Set the transport's RTO.initial value */ + peer->rto = asoc->rto_initial; /* Attach the remote transport to our asoc. */ list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); /* If we do not yet have a primary path, set one. */ - if (NULL == asoc->peer.primary_path) { + if (!asoc->peer.primary_path) { sctp_assoc_set_primary(asoc, peer); asoc->peer.retran_path = peer; } @@ -490,6 +533,45 @@ struct sctp_transport *sctp_assoc_add_pe return peer; } +/* Delete a transport address from an association. */ +void sctp_assoc_del_peer(struct sctp_association *asoc, + const union sctp_addr *addr) +{ + struct list_head *pos; + struct list_head *temp; + struct sctp_transport *peer = NULL; + struct sctp_transport *transport; + + list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { + transport = list_entry(pos, struct sctp_transport, transports); + if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { + peer = transport; + list_del(pos); + break; + } + } + + /* The address we want delete is not in the association. */ + if (!peer) + return; + + /* Get the first transport of asoc. */ + pos = asoc->peer.transport_addr_list.next; + transport = list_entry(pos, struct sctp_transport, transports); + + /* Update any entries that match the peer to be deleted. */ + if (asoc->peer.primary_path == peer) + sctp_assoc_set_primary(asoc, transport); + if (asoc->peer.active_path == peer) + asoc->peer.active_path = transport; + if (asoc->peer.retran_path == peer) + asoc->peer.retran_path = transport; + if (asoc->peer.last_data_from == peer) + asoc->peer.last_data_from = transport; + + sctp_transport_free(peer); +} + /* Lookup a transport by address. */ struct sctp_transport *sctp_assoc_lookup_paddr( const struct sctp_association *asoc, @@ -528,13 +610,13 @@ void sctp_assoc_control_transport(struct /* Record the transition on the transport. */ switch (command) { case SCTP_TRANSPORT_UP: - transport->active = 1; - spc_state = ADDRESS_AVAILABLE; + transport->active = SCTP_ACTIVE; + spc_state = SCTP_ADDR_REACHABLE; break; case SCTP_TRANSPORT_DOWN: - transport->active = 0; - spc_state = ADDRESS_UNREACHABLE; + transport->active = SCTP_INACTIVE; + spc_state = SCTP_ADDR_UNREACHABLE; break; default: @@ -592,7 +674,7 @@ void sctp_assoc_control_transport(struct /* If we failed to find a usable transport, just camp on the * primary, even if it is inactive. */ - if (NULL == first) { + if (!first) { first = asoc->peer.primary_path; second = asoc->peer.primary_path; } @@ -665,7 +747,7 @@ int sctp_cmp_addr_exact(const union sctp * Note: We are sly and return a shared, prealloced chunk. FIXME: * No we don't, but we could/should. */ -sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc) +struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc) { struct sctp_chunk *chunk; @@ -683,7 +765,7 @@ sctp_chunk_t *sctp_get_ecne_prepend(stru /* Use this function for the packet prepend callback when no ECNE * packet is desired (e.g. some packets don't like to be bundled). */ -sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc) +struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc) { return NULL; } @@ -691,13 +773,14 @@ sctp_chunk_t *sctp_get_no_prepend(struct /* * Find which transport this TSN was sent on. */ -struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u32 tsn) +struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, + __u32 tsn) { struct sctp_transport *active; struct sctp_transport *match; struct list_head *entry, *pos; struct sctp_transport *transport; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; __u32 key = htonl(tsn); match = NULL; @@ -720,7 +803,7 @@ struct sctp_transport *sctp_assoc_lookup active = asoc->peer.active_path; list_for_each(entry, &active->transmitted) { - chunk = list_entry(entry, sctp_chunk_t, transmitted_list); + chunk = list_entry(entry, struct sctp_chunk, transmitted_list); if (key == chunk->subh.data_hdr->tsn) { match = active; @@ -735,7 +818,7 @@ struct sctp_transport *sctp_assoc_lookup if (transport == active) break; list_for_each(entry, &transport->transmitted) { - chunk = list_entry(entry, sctp_chunk_t, + chunk = list_entry(entry, struct sctp_chunk, transmitted_list); if (key == chunk->subh.data_hdr->tsn) { match = transport; @@ -773,15 +856,34 @@ out: return transport; } +/* Is this a live association structure. */ +int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc) +{ + + /* First, verify that this is a kernel address. */ + if (!sctp_is_valid_kaddr((unsigned long) asoc)) + return 0; + + /* Verify that this _is_ an sctp_association + * data structure and if so, that the socket matches. + */ + if (SCTP_ASSOC_EYECATCHER != asoc->eyecatcher) + return 0; + if (asoc->base.sk != sk) + return 0; + + /* The association is valid. */ + return 1; +} + /* Do delayed input processing. This is scheduled by sctp_rcv(). */ static void sctp_assoc_bh_rcv(struct sctp_association *asoc) { struct sctp_endpoint *ep; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; struct sock *sk; struct sctp_inq *inqueue; int state, subtype; - sctp_assoc_t associd = sctp_assoc2id(asoc); int error = 0; /* The association should be held so we should be safe. */ @@ -811,7 +913,7 @@ static void sctp_assoc_bh_rcv(struct sct /* Check to see if the association is freed in response to * the incoming chunk. If so, get out of the while loop. */ - if (!sctp_id2assoc(sk, associd)) + if (!sctp_assoc_valid(sk, asoc)) break; /* If there is an error on chunk, discard this packet. */ @@ -830,11 +932,11 @@ void sctp_assoc_migrate(struct sctp_asso /* Delete the association from the old endpoint's list of * associations. */ - list_del(&assoc->asocs); + list_del_init(&assoc->asocs); /* Decrement the backlog value for a TCP-style socket. */ - if (SCTP_SOCKET_TCP == sctp_sk(oldsk)->type) - oldsk->ack_backlog--; + if (sctp_style(oldsk, TCP)) + oldsk->sk_ack_backlog--; /* Release references to the old endpoint and the sock. */ sctp_endpoint_put(assoc->ep); @@ -853,7 +955,8 @@ void sctp_assoc_migrate(struct sctp_asso } /* Update an association (possibly from unexpected COOKIE-ECHO processing). */ -void sctp_assoc_update(struct sctp_association *asoc, struct sctp_association *new) +void sctp_assoc_update(struct sctp_association *asoc, + struct sctp_association *new) { /* Copy in new parameters of peer. */ asoc->c = new->c; @@ -875,7 +978,7 @@ void sctp_assoc_update(struct sctp_assoc * current next_tsn in case data sent to peer * has been discarded and needs retransmission. */ - if (SCTP_STATE_ESTABLISHED == asoc->state) { + if (sctp_state(asoc, ESTABLISHED)) { asoc->next_tsn = new->next_tsn; asoc->ctsn_ack_point = new->ctsn_ack_point; @@ -947,7 +1050,8 @@ void sctp_assoc_update_retran_path(struc } /* Choose the transport for sending a SHUTDOWN packet. */ -struct sctp_transport *sctp_assoc_choose_shutdown_transport(struct sctp_association *asoc) +struct sctp_transport *sctp_assoc_choose_shutdown_transport( + struct sctp_association *asoc) { /* If this is the first time SHUTDOWN is sent, use the active path, * else use the retran path. If the last SHUTDOWN was sent over the @@ -983,8 +1087,9 @@ void sctp_assoc_sync_pmtu(struct sctp_as } if (pmtu) { + struct sctp_opt *sp = sctp_sk(asoc->base.sk); asoc->pmtu = pmtu; - asoc->frag_point = sctp_frag_point(pmtu); + asoc->frag_point = sctp_frag_point(sp, pmtu); } SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n", @@ -1000,7 +1105,7 @@ static inline int sctp_peer_needs_update case SCTP_STATE_SHUTDOWN_RECEIVED: if ((asoc->rwnd > asoc->a_rwnd) && ((asoc->rwnd - asoc->a_rwnd) >= - min_t(__u32, (asoc->base.sk->rcvbuf >> 1), asoc->pmtu))) + min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu))) return 1; break; default: @@ -1010,9 +1115,9 @@ static inline int sctp_peer_needs_update } /* Increase asoc's rwnd by len and send any window update SACK if needed. */ -void sctp_assoc_rwnd_increase(struct sctp_association *asoc, int len) +void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len) { - sctp_chunk_t *sack; + struct sctp_chunk *sack; struct timer_list *timer; if (asoc->rwnd_over) { @@ -1056,7 +1161,7 @@ void sctp_assoc_rwnd_increase(struct sct } /* Decrease asoc's rwnd by len. */ -void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, int len) +void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) { SCTP_ASSERT(asoc->rwnd, "rwnd zero", return); SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return); @@ -1083,7 +1188,7 @@ int sctp_assoc_set_bind_addr_from_ep(str * the endpoint. */ scope = sctp_scope(&asoc->peer.active_path->ipaddr); - flags = (PF_INET6 == asoc->base.sk->family) ? SCTP_ADDR6_ALLOWED : 0; + flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0; if (asoc->peer.ipv4_address) flags |= SCTP_ADDR4_PEERSUPP; if (asoc->peer.ipv6_address) @@ -1096,12 +1201,32 @@ int sctp_assoc_set_bind_addr_from_ep(str /* Build the association's bind address list from the cookie. */ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc, - sctp_cookie_t *cookie, int gfp) + struct sctp_cookie *cookie, int gfp) { int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length); int var_size3 = cookie->raw_addr_list_len; - __u8 *raw = (__u8 *)cookie + sizeof(sctp_cookie_t) + var_size2; + __u8 *raw = (__u8 *)cookie + sizeof(struct sctp_cookie) + var_size2; return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3, asoc->ep->base.bind_addr.port, gfp); } + +/* Lookup laddr in the bind address list of an association. */ +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr) +{ + int found; + + sctp_read_lock(&asoc->base.addr_lock); + if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && + sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + sctp_sk(asoc->base.sk))) { + found = 1; + goto out; + } + + found = 0; +out: + sctp_read_unlock(&asoc->base.addr_lock); + return found; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/bind_addr.c linux-2.4.26-pre1/net/sctp/bind_addr.c --- linux-2.4.25/net/sctp/bind_addr.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/bind_addr.c 2004-02-25 15:43:30.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) Cisco 1999,2000 * Copyright (c) Motorola 1999,2000,2001 - * Copyright (c) International Business Machines Corp., 2001,2002 * Copyright (c) La Monte H.P. Yarroll 2001 * * This file is part of the SCTP kernel reference implementation. @@ -52,19 +52,20 @@ #include /* Forward declarations for internal helpers. */ -static int sctp_copy_one_addr(sctp_bind_addr_t *, union sctp_addr *, +static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *, sctp_scope_t scope, int gfp, int flags); -static void sctp_bind_addr_clean(sctp_bind_addr_t *); +static void sctp_bind_addr_clean(struct sctp_bind_addr *); /* First Level Abstractions. */ /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses * in 'src' which have a broader scope than 'scope'. */ -int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, +int sctp_bind_addr_copy(struct sctp_bind_addr *dest, + const struct sctp_bind_addr *src, sctp_scope_t scope, int gfp, int flags) { - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; struct list_head *pos; int error = 0; @@ -73,7 +74,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t /* Extract the addresses which are relevant for this scope. */ list_for_each(pos, &src->address_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); + addr = list_entry(pos, struct sctp_sockaddr_entry, list); error = sctp_copy_one_addr(dest, &addr->a, scope, gfp, flags); if (error < 0) @@ -86,7 +87,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t */ if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) { list_for_each(pos, &src->address_list) { - addr = list_entry(pos, struct sockaddr_storage_list, + addr = list_entry(pos, struct sctp_sockaddr_entry, list); error = sctp_copy_one_addr(dest, &addr->a, SCTP_SCOPE_LINK, gfp, @@ -104,11 +105,11 @@ out: } /* Create a new SCTP_bind_addr from nothing. */ -sctp_bind_addr_t *sctp_bind_addr_new(int gfp) +struct sctp_bind_addr *sctp_bind_addr_new(int gfp) { - sctp_bind_addr_t *retval; + struct sctp_bind_addr *retval; - retval = t_new(sctp_bind_addr_t, gfp); + retval = t_new(struct sctp_bind_addr, gfp); if (!retval) goto nomem; @@ -123,7 +124,7 @@ nomem: /* Initialize the SCTP_bind_addr structure for either an endpoint or * an association. */ -void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port) +void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port) { bp->malloced = 0; @@ -132,14 +133,14 @@ void sctp_bind_addr_init(sctp_bind_addr_ } /* Dispose of the address list. */ -static void sctp_bind_addr_clean(sctp_bind_addr_t *bp) +static void sctp_bind_addr_clean(struct sctp_bind_addr *bp) { - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; /* Empty the bind address list. */ list_for_each_safe(pos, temp, &bp->address_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); + addr = list_entry(pos, struct sctp_sockaddr_entry, list); list_del(pos); kfree(addr); SCTP_DBG_OBJCNT_DEC(addr); @@ -147,7 +148,7 @@ static void sctp_bind_addr_clean(sctp_bi } /* Dispose of an SCTP_bind_addr structure */ -void sctp_bind_addr_free(sctp_bind_addr_t *bp) +void sctp_bind_addr_free(struct sctp_bind_addr *bp) { /* Empty the bind address list. */ sctp_bind_addr_clean(bp); @@ -159,17 +160,17 @@ void sctp_bind_addr_free(sctp_bind_addr_ } /* Add an address to the bind address list in the SCTP_bind_addr structure. */ -int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new, +int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, int gfp) { - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; /* Add the address to the bind address list. */ - addr = t_new(struct sockaddr_storage_list, gfp); + addr = t_new(struct sctp_sockaddr_entry, gfp); if (!addr) return -ENOMEM; - addr->a = *new; + memcpy(&addr->a, new, sizeof(*new)); /* Fix up the port if it has not yet been set. * Both v4 and v6 have the port at the same offset. @@ -187,13 +188,13 @@ int sctp_add_bind_addr(sctp_bind_addr_t /* Delete an address from the bind address list in the SCTP_bind_addr * structure. */ -int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) +int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) { struct list_head *pos, *temp; - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; list_for_each_safe(pos, temp, &bp->address_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); + addr = list_entry(pos, struct sctp_sockaddr_entry, list); if (sctp_cmp_addr_exact(&addr->a, del_addr)) { /* Found the exact match. */ list_del(pos); @@ -212,28 +213,30 @@ int sctp_del_bind_addr(sctp_bind_addr_t * * The second argument is the return value for the length. */ -union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, +union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int *addrs_len, int gfp) { union sctp_params addrparms; union sctp_params retval; int addrparms_len; - sctp_addr_param_t rawaddr; + union sctp_addr_param rawaddr; int len; - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; struct list_head *pos; + struct sctp_af *af; + addrparms_len = 0; len = 0; /* Allocate enough memory at once. */ list_for_each(pos, &bp->address_list) { - len += sizeof(sctp_addr_param_t); + len += sizeof(union sctp_addr_param); } /* Don't even bother embedding an address if there * is only one. */ - if (len == sizeof(sctp_addr_param_t)) { + if (len == sizeof(union sctp_addr_param)) { retval.v = NULL; goto end_raw; } @@ -245,8 +248,9 @@ union sctp_params sctp_bind_addrs_to_raw addrparms = retval; list_for_each(pos, &bp->address_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); - len = sockaddr2sctp_addr(&addr->a, &rawaddr); + addr = list_entry(pos, struct sctp_sockaddr_entry, list); + af = sctp_get_af_specific(addr->a.v4.sin_family); + len = af->to_addr_param(&addr->a, &rawaddr); memcpy(addrparms.v, &rawaddr, len); addrparms.v += len; addrparms_len += len; @@ -261,42 +265,39 @@ end_raw: * Create an address list out of the raw address list format (IPv4 and IPv6 * address parameters). */ -int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, +int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, int addrs_len, __u16 port, int gfp) { - sctp_addr_param_t *rawaddr; - sctp_paramhdr_t *param; + union sctp_addr_param *rawaddr; + struct sctp_paramhdr *param; union sctp_addr addr; int retval = 0; int len; + struct sctp_af *af; /* Convert the raw address to standard address format */ while (addrs_len) { - param = (sctp_paramhdr_t *)raw_addr_list; - rawaddr = (sctp_addr_param_t *)raw_addr_list; + param = (struct sctp_paramhdr *)raw_addr_list; + rawaddr = (union sctp_addr_param *)raw_addr_list; - switch (param->type) { - case SCTP_PARAM_IPV4_ADDRESS: - case SCTP_PARAM_IPV6_ADDRESS: - sctp_param2sockaddr(&addr, rawaddr, port, 0); - retval = sctp_add_bind_addr(bp, &addr, gfp); - if (retval) { - /* Can't finish building the list, clean up. */ - sctp_bind_addr_clean(bp); - break;; - } - len = ntohs(param->length); - addrs_len -= len; - raw_addr_list += len; - break; - default: - /* Corrupted raw addr list! */ + af = sctp_get_af_specific(param_type2af(param->type)); + if (unlikely(!af)) { retval = -EINVAL; sctp_bind_addr_clean(bp); break; } - if (retval) - break; + + af->from_addr_param(&addr, rawaddr, port, 0); + retval = sctp_add_bind_addr(bp, &addr, gfp); + if (retval) { + /* Can't finish building the list, clean up. */ + sctp_bind_addr_clean(bp); + break;; + } + + len = ntohs(param->length); + addrs_len -= len; + raw_addr_list += len; } return retval; @@ -307,14 +308,15 @@ int sctp_raw_to_bind_addrs(sctp_bind_add ********************************************************************/ /* Does this contain a specified address? Allow wildcarding. */ -int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, +int sctp_bind_addr_match(struct sctp_bind_addr *bp, + const union sctp_addr *addr, struct sctp_opt *opt) { - struct sockaddr_storage_list *laddr; + struct sctp_sockaddr_entry *laddr; struct list_head *pos; list_for_each(pos, &bp->address_list) { - laddr = list_entry(pos, struct sockaddr_storage_list, list); + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if (opt->pf->cmp_addr(&laddr->a, addr, opt)) return 1; } @@ -322,16 +324,52 @@ int sctp_bind_addr_match(sctp_bind_addr_ return 0; } +/* Find the first address in the bind address list that is not present in + * the addrs packed array. + */ +union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, + const union sctp_addr *addrs, + int addrcnt, + struct sctp_opt *opt) +{ + struct sctp_sockaddr_entry *laddr; + union sctp_addr *addr; + void *addr_buf; + struct sctp_af *af; + struct list_head *pos; + int i; + + list_for_each(pos, &bp->address_list) { + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); + + addr_buf = (union sctp_addr *)addrs; + for (i = 0; i < addrcnt; i++) { + addr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(addr->v4.sin_family); + if (!af) + return NULL; + + if (opt->pf->cmp_addr(&laddr->a, addr, opt)) + break; + + addr_buf += af->sockaddr_len; + } + if (i == addrcnt) + return &laddr->a; + } + + return NULL; +} + /* Copy out addresses from the global local address list. */ -static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr, +static int sctp_copy_one_addr(struct sctp_bind_addr *dest, + union sctp_addr *addr, sctp_scope_t scope, int gfp, int flags) { - struct sctp_protocol *proto = sctp_get_protocol(); int error = 0; if (sctp_is_any(addr)) { - error = sctp_copy_local_addr_list(proto, dest, scope, - gfp, flags); + error = sctp_copy_local_addr_list(dest, scope, gfp, flags); } else if (sctp_in_scope(addr, scope)) { /* Now that the address is in scope, check to see if * the address type is supported by local sock as diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/chunk.c linux-2.4.26-pre1/net/sctp/chunk.c --- linux-2.4.25/net/sctp/chunk.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/chunk.c 2004-02-25 15:41:14.000000000 +0000 @@ -0,0 +1,323 @@ +/* SCTP kernel reference Implementation + * Copyright (c) 2003 International Business Machines Corp. + * + * This file is part of the SCTP kernel reference Implementation + * + * This file contains the code relating the the chunk abstraction. + * + * The SCTP reference implementation is free software; + * you can redistribute it and/or modify it under the terms of + * the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * The SCTP reference implementation is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * ************************ + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Please send any bug reports or fixes you make to the + * email address(es): + * lksctp developers + * + * Or submit a bug report through the following website: + * http://www.sf.net/projects/lksctp + * + * Written or modified by: + * Jon Grimm + * + * Any bugs reported given to us we will try to fix... any fixes shared will + * be incorporated into the next SCTP release. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* This file is mostly in anticipation of future work, but initially + * populate with fragment tracking for an outbound message. + */ + +/* Initialize datamsg from memory. */ +void sctp_datamsg_init(struct sctp_datamsg *msg) +{ + atomic_set(&msg->refcnt, 1); + msg->send_failed = 0; + msg->send_error = 0; + msg->can_expire = 0; + INIT_LIST_HEAD(&msg->chunks); +} + +/* Allocate and initialize datamsg. */ +struct sctp_datamsg *sctp_datamsg_new(int gfp) +{ + struct sctp_datamsg *msg; + msg = kmalloc(sizeof(struct sctp_datamsg), gfp); + if (msg) + sctp_datamsg_init(msg); + SCTP_DBG_OBJCNT_INC(datamsg); + return msg; +} + +/* Final destructruction of datamsg memory. */ +static void sctp_datamsg_destroy(struct sctp_datamsg *msg) +{ + struct list_head *pos, *temp; + struct sctp_chunk *chunk; + struct sctp_opt *sp; + struct sctp_ulpevent *ev; + struct sctp_association *asoc = NULL; + int error = 0, notify; + + /* If we failed, we may need to notify. */ + notify = msg->send_failed ? -1 : 0; + + /* Release all references. */ + list_for_each_safe(pos, temp, &msg->chunks) { + list_del_init(pos); + chunk = list_entry(pos, struct sctp_chunk, frag_list); + /* Check whether we _really_ need to notify. */ + if (notify < 0) { + asoc = chunk->asoc; + if (msg->send_error) + error = msg->send_error; + else + error = asoc->outqueue.error; + + sp = sctp_sk(asoc->base.sk); + notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED, + &sp->subscribe); + } + + /* Generate a SEND FAILED event only if enabled. */ + if (notify > 0) { + int sent; + if (chunk->has_tsn) + sent = SCTP_DATA_SENT; + else + sent = SCTP_DATA_UNSENT; + + ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent, + error, GFP_ATOMIC); + if (ev) + sctp_ulpq_tail_event(&asoc->ulpq, ev); + } + + sctp_chunk_put(chunk); + } + + SCTP_DBG_OBJCNT_DEC(datamsg); + kfree(msg); +} + +/* Hold a reference. */ +void sctp_datamsg_hold(struct sctp_datamsg *msg) +{ + atomic_inc(&msg->refcnt); +} + +/* Release a reference. */ +void sctp_datamsg_put(struct sctp_datamsg *msg) +{ + if (atomic_dec_and_test(&msg->refcnt)) + sctp_datamsg_destroy(msg); +} + +/* Free a message. Really just give up a reference, the + * really free happens in sctp_datamsg_destroy(). + */ +void sctp_datamsg_free(struct sctp_datamsg *msg) +{ + sctp_datamsg_put(msg); +} + +/* Hold on to all the fragments until all chunks have been sent. */ +void sctp_datamsg_track(struct sctp_chunk *chunk) +{ + sctp_chunk_hold(chunk); +} + +/* Assign a chunk to this datamsg. */ +void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk) +{ + sctp_datamsg_hold(msg); + chunk->msg = msg; +} + + +/* A data chunk can have a maximum payload of (2^16 - 20). Break + * down any such message into smaller chunks. Opportunistically, fragment + * the chunks down to the current MTU constraints. We may get refragmented + * later if the PMTU changes, but it is _much better_ to fragment immediately + * with a reasonable guess than always doing our fragmentation on the + * soft-interrupt. + */ +struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, + struct sctp_sndrcvinfo *sinfo, + struct msghdr *msgh, int msg_len) +{ + int max, whole, i, offset, over, err; + int len, first_len; + struct sctp_chunk *chunk; + struct sctp_datamsg *msg; + struct list_head *pos, *temp; + __u8 frag; + + msg = sctp_datamsg_new(GFP_KERNEL); + if (!msg) + return NULL; + + /* Note: Calculate this outside of the loop, so that all fragments + * have the same expiration. + */ + if (sinfo->sinfo_timetolive) { + /* sinfo_timetolive is in milliseconds */ + msg->expires_at = jiffies + + MSECS_TO_JIFFIES(sinfo->sinfo_timetolive); + msg->can_expire = 1; + } + + /* What is a reasonable fragmentation point right now? */ + max = asoc->pmtu; + if (max < SCTP_MIN_PMTU) + max = SCTP_MIN_PMTU; + max -= SCTP_IP_OVERHEAD; + + /* Make sure not beyond maximum chunk size. */ + if (max > SCTP_MAX_CHUNK_LEN) + max = SCTP_MAX_CHUNK_LEN; + + /* Subtract out the overhead of a data chunk header. */ + max -= sizeof(struct sctp_data_chunk); + whole = 0; + + /* If user has specified smaller fragmentation, make it so. */ + if (sctp_sk(asoc->base.sk)->user_frag) + max = min_t(int, max, sctp_sk(asoc->base.sk)->user_frag); + + first_len = max; + + /* Encourage Cookie-ECHO bundling. */ + if (asoc->state < SCTP_STATE_COOKIE_ECHOED) { + whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN); + + /* Account for the DATA to be bundled with the COOKIE-ECHO. */ + if (whole) { + first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN; + msg_len -= first_len; + whole = 1; + } + } + + /* How many full sized? How many bytes leftover? */ + whole += msg_len / max; + over = msg_len % max; + offset = 0; + + if ((whole > 1) || (whole && over)) + SCTP_INC_STATS_USER(SctpFragUsrMsgs); + + /* Create chunks for all the full sized DATA chunks. */ + for (i=0, len=first_len; i < whole; i++) { + frag = SCTP_DATA_MIDDLE_FRAG; + + if (0 == i) + frag |= SCTP_DATA_FIRST_FRAG; + + if ((i == (whole - 1)) && !over) + frag |= SCTP_DATA_LAST_FRAG; + + chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); + + if (!chunk) + goto errout; + err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov); + if (err < 0) + goto errout; + + offset += len; + + /* Put the chunk->skb back into the form expected by send. */ + __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr + - (__u8 *)chunk->skb->data); + + sctp_datamsg_assign(msg, chunk); + list_add_tail(&chunk->frag_list, &msg->chunks); + + /* The first chunk, the first chunk was likely short + * to allow bundling, so reset to full size. + */ + if (0 == i) + len = max; + } + + /* .. now the leftover bytes. */ + if (over) { + if (!whole) + frag = SCTP_DATA_NOT_FRAG; + else + frag = SCTP_DATA_LAST_FRAG; + + chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); + + if (!chunk) + goto errout; + + err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov); + + /* Put the chunk->skb back into the form expected by send. */ + __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr + - (__u8 *)chunk->skb->data); + if (err < 0) + goto errout; + + sctp_datamsg_assign(msg, chunk); + list_add_tail(&chunk->frag_list, &msg->chunks); + } + + return msg; + +errout: + list_for_each_safe(pos, temp, &msg->chunks) { + list_del_init(pos); + chunk = list_entry(pos, struct sctp_chunk, frag_list); + sctp_chunk_free(chunk); + } + sctp_datamsg_free(msg); + return NULL; +} + +/* Check whether this message has expired. */ +int sctp_datamsg_expires(struct sctp_chunk *chunk) +{ + struct sctp_datamsg *msg = chunk->msg; + + /* FIXME: When PR-SCTP is supported we can make this + * check more lenient. + */ + if (!msg->can_expire) + return 0; + + if (time_after(jiffies, msg->expires_at)) + return 1; + + return 0; +} + +/* This chunk (and consequently entire message) has failed in its sending. */ +void sctp_datamsg_fail(struct sctp_chunk *chunk, int error) +{ + chunk->msg->send_failed = 1; + chunk->msg->send_error = error; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/debug.c linux-2.4.26-pre1/net/sctp/debug.c --- linux-2.4.25/net/sctp/debug.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/debug.c 2004-02-25 15:42:47.000000000 +0000 @@ -185,6 +185,7 @@ static const char *sctp_timer_tbl[] = { "TIMEOUT_T1_INIT", "TIMEOUT_T2_SHUTDOWN", "TIMEOUT_T3_RTX", + "TIMEOUT_T4_RTO", "TIMEOUT_T5_SHUTDOWN_GUARD", "TIMEOUT_HEARTBEAT", "TIMEOUT_SACK", diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/endpointola.c linux-2.4.26-pre1/net/sctp/endpointola.c --- linux-2.4.25/net/sctp/endpointola.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/endpointola.c 2004-02-25 15:45:31.000000000 +0000 @@ -54,6 +54,7 @@ #include #include #include /* get_random_bytes() */ +#include #include #include #include @@ -128,15 +129,16 @@ struct sctp_endpoint *sctp_endpoint_init ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = SCTP_DEFAULT_TIMEOUT_T1_INIT; ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = - sp->rtoinfo.srto_initial; + MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial); ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0; + ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0; /* sctpimpguide-05 Section 2.12.2 * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the * recommended value of 5 times 'RTO.Max'. */ ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD] - = 5 * sp->rtoinfo.srto_max; + = 5 * MSECS_TO_JIFFIES(sp->rtoinfo.srto_max); ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; @@ -145,17 +147,9 @@ struct sctp_endpoint *sctp_endpoint_init ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ; - /* Set up the default send/receive buffer space. */ - - /* FIXME - Should the min and max window size be configurable - * sysctl parameters as opposed to be constants? - */ - sk->rcvbuf = SCTP_DEFAULT_MAXWINDOW; - sk->sndbuf = SCTP_DEFAULT_MAXWINDOW * 2; - /* Use SCTP specific send buffer space queues. */ - sk->write_space = sctp_write_space; - sk->use_write_queue = 1; + sk->sk_write_space = sctp_write_space; + sk->sk_use_write_queue = 1; /* Initialize the secret key used with cookie. */ get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE); @@ -176,9 +170,8 @@ void sctp_endpoint_add_asoc(struct sctp_ list_add_tail(&asoc->asocs, &ep->asocs); /* Increment the backlog value for a TCP-style listening socket. */ - if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) && - (SCTP_SS_LISTENING == sk->state)) - sk->ack_backlog++; + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) + sk->sk_ack_backlog++; } /* Free the endpoint structure. Delay cleanup until @@ -195,7 +188,7 @@ void sctp_endpoint_destroy(struct sctp_e { SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); - ep->base.sk->state = SCTP_SS_CLOSED; + ep->base.sk->sk_state = SCTP_SS_CLOSED; /* Unlink this endpoint, so we can't find it again! */ sctp_unhash_endpoint(ep); @@ -313,13 +306,13 @@ int sctp_endpoint_is_peeled_off(struct s const union sctp_addr *paddr) { struct list_head *pos; - struct sockaddr_storage_list *addr; - sctp_bind_addr_t *bp; + struct sctp_sockaddr_entry *addr; + struct sctp_bind_addr *bp; sctp_read_lock(&ep->base.addr_lock); bp = &ep->base.bind_addr; list_for_each(pos, &bp->address_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); + addr = list_entry(pos, struct sctp_sockaddr_entry, list); if (sctp_has_association(&addr->a, paddr)) { sctp_read_unlock(&ep->base.addr_lock); return 1; @@ -338,7 +331,7 @@ static void sctp_endpoint_bh_rcv(struct struct sctp_association *asoc; struct sock *sk; struct sctp_transport *transport; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; struct sctp_inq *inqueue; sctp_subtype_t subtype; sctp_state_t state; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/input.c linux-2.4.26-pre1/net/sctp/input.c --- linux-2.4.25/net/sctp/input.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/input.c 2004-02-25 15:44:01.000000000 +0000 @@ -106,7 +106,7 @@ int sctp_rcv(struct sk_buff *skb) struct sctp_endpoint *ep = NULL; struct sctp_ep_common *rcvr; struct sctp_transport *transport = NULL; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; struct sctphdr *sh; union sctp_addr src; union sctp_addr dest; @@ -124,16 +124,16 @@ int sctp_rcv(struct sk_buff *skb) /* Pull up the IP and SCTP headers. */ __skb_pull(skb, skb->h.raw - skb->data); if (skb->len < sizeof(struct sctphdr)) - goto bad_packet; + goto discard_it; if (sctp_rcv_checksum(skb) < 0) - goto bad_packet; + goto discard_it; skb_pull(skb, sizeof(struct sctphdr)); family = ipver2af(skb->nh.iph->version); af = sctp_get_af_specific(family); if (unlikely(!af)) - goto bad_packet; + goto discard_it; /* Initialize local addresses for lookups. */ af->from_skb(&src, skb, 1); @@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb) * IP broadcast addresses cannot be used in an SCTP transport * address." */ - if (!af->addr_valid(&src) || !af->addr_valid(&dest)) + if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL)) goto discard_it; asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); @@ -180,7 +180,7 @@ int sctp_rcv(struct sk_buff *skb) ret = sk_filter(sk, skb, 1); if (ret) - goto discard_release; + goto discard_release; /* Create an SCTP packet structure. */ chunk = sctp_chunkify(skb, asoc, sk); @@ -223,9 +223,6 @@ int sctp_rcv(struct sk_buff *skb) sock_put(sk); return ret; -bad_packet: - SCTP_INC_STATS(SctpChecksumErrors); - discard_it: kfree_skb(skb); return ret; @@ -250,13 +247,13 @@ discard_release: */ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) { - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; struct sctp_inq *inqueue; /* One day chunk will live inside the skb, but for * now this works. */ - chunk = (sctp_chunk_t *) skb; + chunk = (struct sctp_chunk *) skb; inqueue = &chunk->rcvr->inqueue; sctp_inq_push(inqueue, chunk); @@ -447,10 +444,10 @@ void sctp_v4_err(struct sk_buff *skb, __ inet = inet_sk(sk); if (!sock_owned_by_user(sk) && inet->recverr) { - sk->err = err; - sk->error_report(sk); + sk->sk_err = err; + sk->sk_error_report(sk); } else { /* Only an error on timeout */ - sk->err_soft = err; + sk->sk_err_soft = err; } out_unlock: @@ -503,9 +500,10 @@ int sctp_rcv_ootb(struct sk_buff *skb) goto discard; if (SCTP_CID_ERROR == ch->type) { - err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t)); - if (SCTP_ERROR_STALE_COOKIE == err->cause) - goto discard; + sctp_walk_errors(err, ch) { + if (SCTP_ERROR_STALE_COOKIE == err->cause) + goto discard; + } } ch = (sctp_chunkhdr_t *) ch_end; @@ -522,12 +520,12 @@ void __sctp_hash_endpoint(struct sctp_en { struct sctp_ep_common **epp; struct sctp_ep_common *epb; - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; epb = &ep->base; epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); - head = &sctp_proto.ep_hashbucket[epb->hashent]; + head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); epp = &head->chain; @@ -550,14 +548,14 @@ void sctp_hash_endpoint(struct sctp_endp /* Remove endpoint from the hash table. */ void __sctp_unhash_endpoint(struct sctp_endpoint *ep) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; epb = &ep->base; epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); - head = &sctp_proto.ep_hashbucket[epb->hashent]; + head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); @@ -582,13 +580,13 @@ void sctp_unhash_endpoint(struct sctp_en /* Look up an endpoint. */ struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; struct sctp_endpoint *ep; int hash; hash = sctp_ep_hashfn(laddr->v4.sin_port); - head = &sctp_proto.ep_hashbucket[hash]; + head = &sctp_ep_hashtable[hash]; read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { ep = sctp_ep(epb); @@ -619,14 +617,14 @@ void __sctp_hash_established(struct sctp { struct sctp_ep_common **epp; struct sctp_ep_common *epb; - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; epb = &asoc->base; /* Calculate which chain this entry will belong to. */ epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port); - head = &sctp_proto.assoc_hashbucket[epb->hashent]; + head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); epp = &head->chain; @@ -649,7 +647,7 @@ void sctp_unhash_established(struct sctp /* Remove association from the hash table. */ void __sctp_unhash_established(struct sctp_association *asoc) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; epb = &asoc->base; @@ -657,7 +655,7 @@ void __sctp_unhash_established(struct sc epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port); - head = &sctp_proto.assoc_hashbucket[epb->hashent]; + head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); @@ -677,7 +675,7 @@ struct sctp_association *__sctp_lookup_a const union sctp_addr *peer, struct sctp_transport **pt) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; struct sctp_association *asoc; struct sctp_transport *transport; @@ -687,7 +685,7 @@ struct sctp_association *__sctp_lookup_a * have wildcards anyways. */ hash = sctp_assoc_hashfn(local->v4.sin_port, peer->v4.sin_port); - head = &sctp_proto.assoc_hashbucket[hash]; + head = &sctp_assoc_hashtable[hash]; read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { asoc = sctp_assoc(epb); @@ -766,6 +764,8 @@ static struct sctp_association *__sctp_r sctp_chunkhdr_t *ch; union sctp_params params; sctp_init_chunk_t *init; + struct sctp_transport *transport; + struct sctp_af *af; ch = (sctp_chunkhdr_t *) skb->data; @@ -800,12 +800,13 @@ static struct sctp_association *__sctp_r sctp_walk_params(params, init, init_hdr.params) { /* Note: Ignoring hostname addresses. */ - if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) && - (SCTP_PARAM_IPV6_ADDRESS != params.p->type)) + af = sctp_get_af_specific(param_type2af(params.p->type)); + if (!af) continue; - sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0); - asoc = __sctp_lookup_association(laddr, paddr, transportp); + af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0); + + asoc = __sctp_lookup_association(laddr, paddr, &transport); if (asoc) return asoc; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/inqueue.c linux-2.4.26-pre1/net/sctp/inqueue.c --- linux-2.4.25/net/sctp/inqueue.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/inqueue.c 2004-02-25 15:42:43.000000000 +0000 @@ -78,17 +78,17 @@ struct sctp_inq *sctp_inq_new(void) /* Release the memory associated with an SCTP inqueue. */ void sctp_inq_free(struct sctp_inq *queue) { - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; /* Empty the queue. */ - while ((chunk = (sctp_chunk_t *) skb_dequeue(&queue->in))) - sctp_free_chunk(chunk); + while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in))) + sctp_chunk_free(chunk); /* If there is a packet which is currently being worked on, * free it as well. */ if (queue->in_progress) - sctp_free_chunk(queue->in_progress); + sctp_chunk_free(queue->in_progress); if (queue->malloced) { /* Dump the master memory segment. */ @@ -99,7 +99,7 @@ void sctp_inq_free(struct sctp_inq *queu /* Put a new packet in an SCTP inqueue. * We assume that packet->sctp_hdr is set and in host byte order. */ -void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet) +void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet) { /* Directly call the packet handling routine. */ @@ -117,9 +117,9 @@ void sctp_inq_push(struct sctp_inq *q, s * WARNING: If you need to put the chunk on another queue, you need to * make a shallow copy (clone) of it. */ -sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue) +struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) { - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; sctp_chunkhdr_t *ch = NULL; /* The assumption is that we are safe to process the chunks @@ -133,7 +133,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_i if (chunk->singleton || chunk->end_of_packet || chunk->pdiscard) { - sctp_free_chunk(chunk); + sctp_chunk_free(chunk); chunk = queue->in_progress = NULL; } else { /* Nothing to do. Next chunk in the packet, please. */ @@ -152,7 +152,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_i return NULL; chunk = queue->in_progress = - (sctp_chunk_t *) skb_dequeue(&queue->in); + (struct sctp_chunk *) skb_dequeue(&queue->in); /* This is the first chunk in the packet. */ chunk->singleton = 1; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ipv6.c linux-2.4.26-pre1/net/sctp/ipv6.c --- linux-2.4.25/net/sctp/ipv6.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/ipv6.c 2004-02-25 15:43:10.000000000 +0000 @@ -2,6 +2,7 @@ * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2002-2003 International Business Machines, Corp. + * Copyright (c) 2002-2003 Intel Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -15,7 +16,7 @@ * * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied - * ************************ + * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * @@ -32,14 +33,15 @@ * http://www.sf.net/projects/lksctp * * Written or modified by: - * Le Yanqun + * Le Yanqun * Hui Huang * La Monte H.P. Yarroll * Sridhar Samudrala - * Jon Grimm + * Jon Grimm + * Ardelle Fan * * Based on: - * linux/net/ipv6/tcp_ipv6.c + * linux/net/ipv6/tcp_ipv6.c * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -61,6 +63,7 @@ #include #include #include +#include #include #include @@ -79,14 +82,14 @@ extern struct notifier_block sctp_inetad /* FIXME: This macro needs to be moved to a common header file. */ #define NIP6(addr) \ - ntohs((addr)->s6_addr16[0]), \ - ntohs((addr)->s6_addr16[1]), \ - ntohs((addr)->s6_addr16[2]), \ - ntohs((addr)->s6_addr16[3]), \ - ntohs((addr)->s6_addr16[4]), \ - ntohs((addr)->s6_addr16[5]), \ - ntohs((addr)->s6_addr16[6]), \ - ntohs((addr)->s6_addr16[7]) + ntohs((addr).s6_addr16[0]), \ + ntohs((addr).s6_addr16[1]), \ + ntohs((addr).s6_addr16[2]), \ + ntohs((addr).s6_addr16[3]), \ + ntohs((addr).s6_addr16[4]), \ + ntohs((addr).s6_addr16[5]), \ + ntohs((addr).s6_addr16[6]), \ + ntohs((addr).s6_addr16[7]) /* ICMP error handler. */ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -134,10 +137,10 @@ void sctp_v6_err(struct sk_buff *skb, st np = inet6_sk(sk); icmpv6_err_convert(type, code, &err); if (!sock_owned_by_user(sk) && np->recverr) { - sk->err = err; - sk->error_report(sk); + sk->sk_err = err; + sk->sk_error_report(sk); } else { /* Only an error on timeout */ - sk->err_soft = err; + sk->sk_err_soft = err; } out_unlock: @@ -155,7 +158,9 @@ static int sctp_v6_xmit(struct sk_buff * struct ipv6_pinfo *np = inet6_sk(sk); struct flowi fl; - fl.proto = sk->protocol; + memset(&fl, 0, sizeof(fl)); + + fl.proto = sk->sk_protocol; /* Fill in the dest address from the route entry passed with the skb * and the source address from the transport. @@ -168,20 +173,20 @@ static int sctp_v6_xmit(struct sk_buff * if (ipv6_addr_type(fl.fl6_src) & IPV6_ADDR_LINKLOCAL) fl.oif = transport->saddr.v6.sin6_scope_id; else - fl.oif = sk->bound_dev_if; - fl.uli_u.ports.sport = (sk)->sport; + fl.oif = sk->sk_bound_dev_if; + fl.uli_u.ports.sport = sk->sport; fl.uli_u.ports.dport = transport->ipaddr.v6.sin6_port; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - __FUNCTION__, skb, skb->len, NIP6(fl.fl6_src), - NIP6(fl.fl6_dst)); + __FUNCTION__, skb, skb->len, + NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); SCTP_INC_STATS(SctpOutSCTPPacks); @@ -196,8 +201,13 @@ struct dst_entry *sctp_v6_get_dst(struct union sctp_addr *saddr) { struct dst_entry *dst; - struct flowi fl = { - .nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } }; + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); + fl.fl6_dst = &daddr->v6.sin6_addr; + if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) + fl.oif = daddr->v6.sin6_scope_id; + SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", __FUNCTION__, NIP6(fl.fl6_dst)); @@ -216,7 +226,7 @@ struct dst_entry *sctp_v6_get_dst(struct SCTP_DEBUG_PRINTK( "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(&rt->rt6i_dst.addr), NIP6(&rt->rt6i_src.addr)); + NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); } else { SCTP_DEBUG_PRINTK("NO ROUTE\n"); } @@ -252,9 +262,9 @@ static inline int sctp_v6_addr_match_len void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst, union sctp_addr *daddr, union sctp_addr *saddr) { - sctp_bind_addr_t *bp; + struct sctp_bind_addr *bp; rwlock_t *addr_lock; - struct sockaddr_storage_list *laddr; + struct sctp_sockaddr_entry *laddr; struct list_head *pos; sctp_scope_t scope; union sctp_addr *baddr = NULL; @@ -263,13 +273,13 @@ void sctp_v6_get_saddr(struct sctp_assoc SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", - __FUNCTION__, asoc, dst, NIP6(&daddr->v6.sin6_addr)); + __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); if (!asoc) { ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(&saddr->v6.sin6_addr)); + NIP6(saddr->v6.sin6_addr)); return; } @@ -283,7 +293,7 @@ void sctp_v6_get_saddr(struct sctp_assoc */ sctp_read_lock(addr_lock); list_for_each(pos, &bp->address_list) { - laddr = list_entry(pos, struct sockaddr_storage_list, list); + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((laddr->a.sa.sa_family == AF_INET6) && (scope <= sctp_scope(&laddr->a))) { bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); @@ -298,12 +308,12 @@ void sctp_v6_get_saddr(struct sctp_assoc memcpy(saddr, baddr, sizeof(union sctp_addr)); SCTP_DEBUG_PRINTK("saddr: " "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(&saddr->v6.sin6_addr)); + NIP6(saddr->v6.sin6_addr)); } else { printk(KERN_ERR "%s: asoc:%p Could not find a valid source " "address for the " "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - __FUNCTION__, asoc, NIP6(&daddr->v6.sin6_addr)); + __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); } sctp_read_unlock(addr_lock); @@ -315,7 +325,7 @@ static void sctp_v6_copy_addrlist(struct { struct inet6_dev *in6_dev; struct inet6_ifaddr *ifp; - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; read_lock(&addrconf_lock); if ((in6_dev = __in6_dev_get(dev)) == NULL) { @@ -326,7 +336,7 @@ static void sctp_v6_copy_addrlist(struct read_lock(&in6_dev->lock); for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { /* Add the address to the local list. */ - addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC); + addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); if (addr) { addr->a.v6.sin6_family = AF_INET6; addr->a.v6.sin6_port = 0; @@ -369,20 +379,62 @@ static void sctp_v6_from_skb(union sctp_ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) { addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = (sk)->num; + addr->v6.sin6_port = sk->num; addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr; } -/* Initialize sk->rcv_saddr from sctp_addr. */ +/* Initialize sk->sk_rcv_saddr from sctp_addr. */ static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) { - inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr; + if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) { + inet6_sk(sk)->rcv_saddr.s6_addr32[0] = 0; + inet6_sk(sk)->rcv_saddr.s6_addr32[1] = 0; + inet6_sk(sk)->rcv_saddr.s6_addr32[2] = htonl(0x0000ffff); + inet6_sk(sk)->rcv_saddr.s6_addr32[3] = + addr->v4.sin_addr.s_addr; + } else { + inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr; + } } -/* Initialize sk->daddr from sctp_addr. */ +/* Initialize sk->sk_daddr from sctp_addr. */ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) { - inet6_sk(sk)->daddr = addr->v6.sin6_addr; + if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) { + inet6_sk(sk)->daddr.s6_addr32[0] = 0; + inet6_sk(sk)->daddr.s6_addr32[1] = 0; + inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff); + inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr; + } else { + inet6_sk(sk)->daddr = addr->v6.sin6_addr; + } +} + +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v6_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = port; + addr->v6.sin6_flowinfo = 0; /* BUG */ + ipv6_addr_copy(&addr->v6.sin6_addr, ¶m->v6.addr); + addr->v6.sin6_scope_id = iif; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v6_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv6addr_param_t); + + param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; + param->v6.param_hdr.length = ntohs(length); + ipv6_addr_copy(¶m->v6.addr, &addr->v6.sin6_addr); + + return length; } /* Initialize a sctp_addr from a dst_entry. */ @@ -396,13 +448,30 @@ static void sctp_v6_dst_saddr(union sctp } /* Compare addresses exactly. - * FIXME: v4-mapped-v6. + * v4-mapped-v6 is also in consideration. */ static int sctp_v6_cmp_addr(const union sctp_addr *addr1, const union sctp_addr *addr2) { - if (addr1->sa.sa_family != addr2->sa.sa_family) + if (addr1->sa.sa_family != addr2->sa.sa_family) { + if (addr1->sa.sa_family == AF_INET && + addr2->sa.sa_family == AF_INET6 && + IPV6_ADDR_MAPPED == ipv6_addr_type(&addr2->v6.sin6_addr)) { + if (addr2->v6.sin6_port == addr1->v4.sin_port && + addr2->v6.sin6_addr.s6_addr32[3] == + addr1->v4.sin_addr.s_addr) + return 1; + } + if (addr2->sa.sa_family == AF_INET && + addr1->sa.sa_family == AF_INET6 && + IPV6_ADDR_MAPPED == ipv6_addr_type(&addr1->v6.sin6_addr)) { + if (addr1->v6.sin6_port == addr2->v4.sin_port && + addr1->v6.sin6_addr.s6_addr32[3] == + addr2->v4.sin_addr.s_addr) + return 1; + } return 0; + } if (ipv6_addr_cmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) return 0; /* If this is a linklocal address, compare the scope_id. */ @@ -433,7 +502,7 @@ static int sctp_v6_is_any(const union sc } /* Should this be available for binding? */ -static int sctp_v6_available(const union sctp_addr *addr) +static int sctp_v6_available(union sctp_addr *addr, struct sctp_opt *sp) { int type; struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr; @@ -441,6 +510,14 @@ static int sctp_v6_available(const union type = ipv6_addr_type(in6); if (IPV6_ADDR_ANY == type) return 1; + if (type == IPV6_ADDR_MAPPED) { + if (sp && !sp->v4mapped) + return 0; + if (sp && ipv6_only_sock(sctp_opt2sk(sp))) + return 0; + sctp_v6_map_v4(addr); + return sctp_get_af_specific(AF_INET)->available(addr, sp); + } if (!(type & IPV6_ADDR_UNICAST)) return 0; @@ -454,11 +531,22 @@ static int sctp_v6_available(const union * Return 0 - If the address is a non-unicast or an illegal address. * Return 1 - If the address is a unicast. */ -static int sctp_v6_addr_valid(union sctp_addr *addr) +static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_opt *sp) { int ret = ipv6_addr_type(&addr->v6.sin6_addr); - /* FIXME: v4-mapped-v6 address support. */ + /* Support v4-mapped-v6 address. */ + if (ret == IPV6_ADDR_MAPPED) { + /* Note: This routine is used in input, so v4-mapped-v6 + * are disallowed here when there is no sctp_opt. + */ + if (!sp || !sp->v4mapped) + return 0; + if (sp && ipv6_only_sock(sctp_opt2sk(sp))) + return 0; + sctp_v6_map_v4(addr); + return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp); + } /* Is this a non-unicast address */ if (!(ret & IPV6_ADDR_UNICAST)) @@ -511,18 +599,18 @@ struct sock *sctp_v6_create_accept_sk(st sock_init_data(NULL, newsk); sk_set_owner(newsk, THIS_MODULE); - newsk->type = SOCK_STREAM; + newsk->sk_type = SOCK_STREAM; - newsk->prot = sk->prot; - newsk->no_check = sk->no_check; - newsk->reuse = sk->reuse; - - newsk->destruct = inet_sock_destruct; - newsk->zapped = 0; - newsk->family = PF_INET6; - newsk->protocol = IPPROTO_SCTP; - newsk->backlog_rcv = sk->prot->backlog_rcv; - newsk->shutdown = sk->shutdown; + newsk->sk_prot = sk->sk_prot; + newsk->sk_no_check = sk->sk_no_check; + newsk->sk_reuse = sk->sk_reuse; + + newsk->sk_destruct = inet_sock_destruct; + newsk->sk_zapped = 0; + newsk->sk_family = PF_INET6; + newsk->sk_protocol = IPPROTO_SCTP; + newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; + newsk->sk_shutdown = sk->sk_shutdown; newinet = inet_sk(newsk); newnp = inet6_sk(newsk); @@ -533,17 +621,31 @@ struct sock *sctp_v6_create_accept_sk(st * and getpeername(). */ newsk->sport = sk->sport; - newnp->saddr = np->saddr; + newsk->saddr = sk->saddr; newnp->rcv_saddr = np->rcv_saddr; newsk->dport = htons(asoc->peer.port); - newnp->daddr = asoc->peer.primary_addr.v6.sin6_addr; + sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); + + /* Init the ipv4 part of the socket since we can have sockets + * using v6 API for ipv4. + */ + newinet->ttl = sysctl_ip_default_ttl; + newinet->mc_loop = 1; + newinet->mc_ttl = 1; + newinet->mc_index = 0; + newinet->mc_list = NULL; + + if (ipv4_config.no_pmtu_disc) + newinet->pmtudisc = IP_PMTUDISC_DONT; + else + newinet->pmtudisc = IP_PMTUDISC_WANT; #ifdef INET_REFCNT_DEBUG atomic_inc(&inet6_sock_nr); atomic_inc(&inet_sock_nr); #endif - if (0 != newsk->prot->init(newsk)) { + if (newsk->sk_prot->init(newsk)) { inet_sock_release(newsk); newsk = NULL; } @@ -552,6 +654,13 @@ out: return newsk; } +/* Map v4 address to mapped v6 address */ +static void sctp_v6_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr) +{ + if (sp->v4mapped && AF_INET == addr->sa.sa_family) + sctp_v4_map_v6(addr); +} + /* Where did this skb come from? */ static int sctp_v6_skb_iif(const struct sk_buff *skb) { @@ -559,6 +668,19 @@ static int sctp_v6_skb_iif(const struct return opt->iif; } +/* Was this packet marked by Explicit Congestion Notification? */ +static int sctp_v6_is_ce(const struct sk_buff *skb) +{ + return *((__u32 *)(skb->nh.ipv6h)) & htonl(1<<20); +} + +/* Dump the v6 addr to the seq file. */ +static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) +{ + seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", + NIP6(addr->v6.sin6_addr)); +} + /* Initialize a PF_INET6 socket msg_name. */ static void sctp_inet6_msgname(char *msgname, int *addr_len) { @@ -579,25 +701,28 @@ static void sctp_inet6_event_msgname(str if (msgname) { union sctp_addr *addr; + struct sctp_association *asoc; + asoc = event->sndrcvinfo.sinfo_assoc_id; sctp_inet6_msgname(msgname, addrlen); sin6 = (struct sockaddr_in6 *)msgname; - sin6->sin6_port = htons(event->event_asoc->peer.port); - addr = &event->event_asoc->peer.primary_addr; + sin6->sin6_port = htons(asoc->peer.port); + addr = &asoc->peer.primary_addr; /* Note: If we go to a common v6 format, this code * will change. */ /* Map ipv4 address into v4-mapped-on-v6 address. */ - if (AF_INET == addr->sa.sa_family) { - /* FIXME: Easy, but there was no way to test this - * yet. - */ + if (sctp_sk(asoc->base.sk)->v4mapped && + AF_INET == addr->sa.sa_family) { + sctp_v4_map_v6((union sctp_addr *)sin6); + sin6->sin6_addr.s6_addr32[3] = + addr->v4.sin_addr.s_addr; return; } - sin6from = &event->event_asoc->peer.primary_addr.v6; + sin6from = &asoc->peer.primary_addr.v6; ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr); if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) sin6->sin6_scope_id = sin6from->sin6_scope_id; @@ -617,16 +742,15 @@ static void sctp_inet6_skb_msgname(struc sh = (struct sctphdr *)skb->h.raw; sin6->sin6_port = sh->source; - /* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */ - if (__constant_htons(ETH_P_IP) == skb->protocol) { - /* FIXME: The latest I-D added options for two - * behaviors. - */ + /* Map ipv4 address into v4-mapped-on-v6 address. */ + if (sctp_sk(skb->sk)->v4mapped && + skb->nh.iph->version == 4) { + sctp_v4_map_v6((union sctp_addr *)sin6); + sin6->sin6_addr.s6_addr32[3] = skb->nh.iph->saddr; return; } /* Otherwise, just copy the v6 address. */ - ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { struct sctp_ulpevent *ev = sctp_skb2event(skb); @@ -636,16 +760,15 @@ static void sctp_inet6_skb_msgname(struc } /* Do we support this AF? */ -static int sctp_inet6_af_supported(sa_family_t family) +static int sctp_inet6_af_supported(sa_family_t family, struct sctp_opt *sp) { - /* FIXME: v4-mapped-v6 addresses. The I-D is still waffling - * on what to do with sockaddr formats for PF_INET6 sockets. - * For now assume we'll support both. - */ switch (family) { case AF_INET6: - case AF_INET: return 1; + /* v4-mapped-v6 addresses */ + case AF_INET: + if (!__ipv6_only_sock(sctp_opt2sk(sp)) && sp->v4mapped) + return 1; default: return 0; } @@ -689,7 +812,7 @@ static int sctp_inet6_bind_verify(struct else { struct sock *sk; int type = ipv6_addr_type(&addr->v6.sin6_addr); - sk = container_of(opt, struct sock, tp_pinfo.af_sctp); + sk = sctp_opt2sk(opt); if (type & IPV6_ADDR_LINKLOCAL) { /* Note: Behavior similar to af_inet6.c: * 1) Overrides previous bound_dev_if @@ -697,13 +820,13 @@ static int sctp_inet6_bind_verify(struct */ if (addr->v6.sin6_scope_id) - sk->bound_dev_if = addr->v6.sin6_scope_id; - if (!sk->bound_dev_if) + sk->sk_bound_dev_if = addr->v6.sin6_scope_id; + if (!sk->sk_bound_dev_if) return 0; } af = opt->pf->af; } - return af->available(addr); + return af->available(addr, opt); } /* Verify that the provided sockaddr looks bindable. Common verification, @@ -719,7 +842,7 @@ static int sctp_inet6_send_verify(struct else { struct sock *sk; int type = ipv6_addr_type(&addr->v6.sin6_addr); - sk = container_of(opt, struct sock, tp_pinfo.af_sctp); + sk = sctp_opt2sk(opt); if (type & IPV6_ADDR_LINKLOCAL) { /* Note: Behavior similar to af_inet6.c: * 1) Overrides previous bound_dev_if @@ -727,8 +850,8 @@ static int sctp_inet6_send_verify(struct */ if (addr->v6.sin6_scope_id) - sk->bound_dev_if = addr->v6.sin6_scope_id; - if (!sk->bound_dev_if) + sk->sk_bound_dev_if = addr->v6.sin6_scope_id; + if (!sk->sk_bound_dev_if) return 0; } af = opt->pf->af; @@ -810,6 +933,8 @@ static struct sctp_af sctp_ipv6_specific .from_sk = sctp_v6_from_sk, .to_sk_saddr = sctp_v6_to_sk_saddr, .to_sk_daddr = sctp_v6_to_sk_daddr, + .from_addr_param = sctp_v6_from_addr_param, + .to_addr_param = sctp_v6_to_addr_param, .dst_saddr = sctp_v6_dst_saddr, .cmp_addr = sctp_v6_cmp_addr, .scope = sctp_v6_scope, @@ -818,6 +943,8 @@ static struct sctp_af sctp_ipv6_specific .is_any = sctp_v6_is_any, .available = sctp_v6_available, .skb_iif = sctp_v6_skb_iif, + .is_ce = sctp_v6_is_ce, + .seq_dump_addr = sctp_v6_seq_dump_addr, .net_header_len = sizeof(struct ipv6hdr), .sockaddr_len = sizeof(struct sockaddr_in6), .sa_family = AF_INET6, @@ -832,6 +959,7 @@ static struct sctp_pf sctp_pf_inet6_spec .send_verify = sctp_inet6_send_verify, .supported_addrs = sctp_inet6_supported_addrs, .create_accept_sk = sctp_v6_create_accept_sk, + .addr_v4map = sctp_v6_addr_v4map, .af = &sctp_ipv6_specific, }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/objcnt.c linux-2.4.26-pre1/net/sctp/objcnt.c --- linux-2.4.25/net/sctp/objcnt.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/objcnt.c 2004-02-25 15:42:31.000000000 +0000 @@ -38,6 +38,7 @@ * be incorporated into the next SCTP release. */ +#include #include /* @@ -55,6 +56,7 @@ SCTP_DBG_OBJCNT(bind_addr); SCTP_DBG_OBJCNT(chunk); SCTP_DBG_OBJCNT(addr); SCTP_DBG_OBJCNT(ssnmap); +SCTP_DBG_OBJCNT(datamsg); /* An array to make it easy to pretty print the debug information * to the proc fs. @@ -68,6 +70,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[ SCTP_DBG_OBJCNT_ENTRY(bind_addr), SCTP_DBG_OBJCNT_ENTRY(addr), SCTP_DBG_OBJCNT_ENTRY(ssnmap), + SCTP_DBG_OBJCNT_ENTRY(datamsg), }; /* Callback from procfs to read out objcount information. @@ -86,7 +89,7 @@ static int sctp_dbg_objcnt_read(char *bu char temp[128]; /* How many entries? */ - entries = sizeof(sctp_dbg_objcnt)/sizeof(sctp_dbg_objcnt[0]); + entries = ARRAY_SIZE(sctp_dbg_objcnt); /* Walk the entries and print out the debug information * for proc fs. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/output.c linux-2.4.26-pre1/net/sctp/output.c --- linux-2.4.25/net/sctp/output.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/output.c 2004-02-25 15:43:00.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -97,6 +97,7 @@ struct sctp_packet *sctp_packet_init(str packet->source_port = sport; packet->destination_port = dport; skb_queue_head_init(&packet->chunks); + packet->size = SCTP_IP_OVERHEAD; packet->vtag = 0; packet->ecn_capable = 0; packet->get_prepend_chunk = NULL; @@ -114,7 +115,7 @@ void sctp_packet_free(struct sctp_packet struct sctp_chunk *chunk; while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) - sctp_free_chunk(chunk); + sctp_chunk_free(chunk); if (packet->malloced) kfree(packet); @@ -138,7 +139,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(s if (!packet->has_cookie_echo) { error = sctp_packet_transmit(packet); if (error < 0) - chunk->skb->sk->err = -error; + chunk->skb->sk->sk_err = -error; /* If we have an empty packet, then we can NOT ever * return PMTU_FULL. @@ -219,22 +220,16 @@ sctp_xmit_t sctp_packet_append_chunk(str /* Both control chunks and data chunks with TSNs are * non-fragmentable. */ - int fragmentable = sctp_chunk_is_data(chunk) && - (!chunk->has_tsn); - if (packet_empty) { - if (fragmentable) { - retval = SCTP_XMIT_MUST_FRAG; - goto finish; - } else { - /* The packet is too big but we can - * not fragment it--we have to just - * transmit and rely on IP - * fragmentation. - */ - packet->ipfragok = 1; - goto append; - } - } else { /* !packet_empty */ + if (packet_empty || !sctp_chunk_is_data(chunk)) { + /* We no longer do re-fragmentation. + * Just fragment at the IP layer, if we + * actually hit this condition + */ + + packet->ipfragok = 1; + goto append; + + } else { retval = SCTP_XMIT_PMTU_FULL; goto finish; } @@ -288,20 +283,18 @@ int sctp_packet_transmit(struct sctp_pac __u8 has_data = 0; struct dst_entry *dst; - /* Do NOT generate a chunkless packet... */ - if (skb_queue_empty(&packet->chunks)) + /* Do NOT generate a chunkless packet. */ + chunk = (struct sctp_chunk *)skb_peek(&packet->chunks); + if (unlikely(!chunk)) return err; /* Set up convenience variables... */ - chunk = (struct sctp_chunk *) (packet->chunks.next); sk = chunk->skb->sk; /* Allocate the new skb. */ nskb = dev_alloc_skb(packet->size); - if (!nskb) { - err = -ENOMEM; - goto out; - } + if (!nskb) + goto nomem; /* Make sure the outbound skb has enough header room reserved. */ skb_reserve(nskb, SCTP_IP_OVERHEAD); @@ -327,7 +320,6 @@ int sctp_packet_transmit(struct sctp_pac sh->vtag = htonl(packet->vtag); sh->checksum = 0; - /* 2) Calculate the Adler-32 checksum of the whole packet, * including the SCTP common header and all the * chunks. @@ -358,10 +350,11 @@ int sctp_packet_transmit(struct sctp_pac */ SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { - chunk->num_times_sent++; - chunk->sent_at = jiffies; if (sctp_chunk_is_data(chunk)) { - sctp_chunk_assign_tsn(chunk); + + if (!chunk->has_tsn) { + sctp_chunk_assign_ssn(chunk); + sctp_chunk_assign_tsn(chunk); /* 6.3.1 C4) When data is in flight and when allowed * by rule C5, a new RTT measurement MUST be made each @@ -369,23 +362,27 @@ int sctp_packet_transmit(struct sctp_pac * SHOULD be made no more than once per round-trip * for a given destination transport address. */ - if ((1 == chunk->num_times_sent) && - (!tp->rto_pending)) { - chunk->rtt_in_progress = 1; - tp->rto_pending = 1; - } + + if (!tp->rto_pending) { + chunk->rtt_in_progress = 1; + tp->rto_pending = 1; + } + } else + chunk->resent = 1; + + chunk->sent_at = jiffies; has_data = 1; } + padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len; if (padding) - memset(skb_put(chunk->skb, padding), 0, padding); + memset(skb_put(chunk->skb, padding), 0, padding); crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len), - chunk->skb->data, + chunk->skb->data, chunk->skb->len, crc32); - - SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, " - "%s %d\n", + + SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", "*** Chunk", chunk, sctp_cname(SCTP_ST_CHUNK( chunk->chunk_hdr->type)), @@ -394,7 +391,6 @@ int sctp_packet_transmit(struct sctp_pac ntohl(chunk->subh.data_hdr->tsn) : 0, "length", ntohs(chunk->chunk_hdr->length), "chunk->skb->len", chunk->skb->len, - "num_times_sent", chunk->num_times_sent, "rtt_in_progress", chunk->rtt_in_progress); /* @@ -403,7 +399,7 @@ int sctp_packet_transmit(struct sctp_pac * acknowledged or have failed. */ if (!sctp_chunk_is_data(chunk)) - sctp_free_chunk(chunk); + sctp_chunk_free(chunk); } /* Perform final transformation on checksum. */ @@ -420,21 +416,17 @@ int sctp_packet_transmit(struct sctp_pac * data sender to indicate that the end-points of the * transport protocol are ECN-capable." * - * If ECN capable && negotiated && it makes sense for - * this packet to support it (e.g. post ECN negotiation) - * then lets set the ECT bit + * Now setting the ECT bit all the time, as it should not cause + * any problems protocol-wise even if our peer ignores it. * - * FIXME: Need to do something else for IPv6 + * Note: The works for IPv6 layer checks this bit too later + * in transmission. See IP6_ECN_flow_xmit(). */ - if (packet->ecn_capable) { - INET_ECN_xmit(nskb->sk); - } else { - INET_ECN_dontxmit(nskb->sk); - } + INET_ECN_xmit(nskb->sk); /* Set up the IP options. */ /* BUG: not implemented - * For v4 this all lives somewhere in sk->opt... + * For v4 this all lives somewhere in sk->sk_opt... */ /* Dump that on IP! */ @@ -452,8 +444,7 @@ int sctp_packet_transmit(struct sctp_pac tp->last_time_used = jiffies; /* Restart the AUTOCLOSE timer when sending data. */ - if ((SCTP_STATE_ESTABLISHED == asoc->state) && - (asoc->autoclose)) { + if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; @@ -474,9 +465,11 @@ int sctp_packet_transmit(struct sctp_pac if (!nskb->dst) goto no_route; - SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n", + SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n", nskb->len); + (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok); + out: packet->size = SCTP_IP_OVERHEAD; return err; @@ -492,7 +485,20 @@ no_route: * required. */ /* err = -EHOSTUNREACH; */ +err: + /* Control chunks are unreliable so just drop them. DATA chunks + * will get resent or dropped later. + */ + + while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { + if (!sctp_chunk_is_data(chunk)) + sctp_chunk_free(chunk); + } goto out; +nomem: + err = -ENOMEM; + printk("%s alloc_skb failed.\n", __FUNCTION__); + goto err; } /******************************************************************** @@ -604,7 +610,7 @@ static sctp_xmit_t sctp_packet_append_da * unacknowledged. */ if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size && - q->outstanding_bytes && SCTP_STATE_ESTABLISHED == asoc->state) { + q->outstanding_bytes && sctp_state(asoc, ESTABLISHED)) { unsigned len = datasize + q->out_qlen; /* Check whether this chunk and all the rest of pending @@ -630,6 +636,8 @@ static sctp_xmit_t sctp_packet_append_da rwnd = 0; asoc->peer.rwnd = rwnd; + /* Has been accepted for transmission. */ + chunk->msg->can_expire = 0; finish: return retval; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/outqueue.c linux-2.4.26-pre1/net/sctp/outqueue.c --- linux-2.4.25/net/sctp/outqueue.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/outqueue.c 2004-02-25 15:42:05.000000000 +0000 @@ -56,13 +56,19 @@ #include /* Declare internal functions here. */ -static int sctp_acked(sctp_sackhdr_t *sack, __u32 tsn); +static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn); static void sctp_check_transmitted(struct sctp_outq *q, struct list_head *transmitted_queue, struct sctp_transport *transport, - sctp_sackhdr_t *sack, + struct sctp_sackhdr *sack, __u32 highest_new_tsn); +static void sctp_mark_missing(struct sctp_outq *q, + struct list_head *transmitted_queue, + struct sctp_transport *transport, + __u32 highest_new_tsn, + int count_of_newacks); + /* Add data to the front of the queue. */ static inline void sctp_outq_head_data(struct sctp_outq *q, struct sctp_chunk *ch) @@ -100,6 +106,98 @@ static inline void sctp_outq_insert_data q->out_qlen += ch->skb->len; } +/* + * SFR-CACC algorithm: + * D) If count_of_newacks is greater than or equal to 2 + * and t was not sent to the current primary then the + * sender MUST NOT increment missing report count for t. + */ +static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary, + struct sctp_transport *transport, + int count_of_newacks) +{ + if (count_of_newacks >=2 && transport != primary) + return 1; + return 0; +} + +/* + * SFR-CACC algorithm: + * F) If count_of_newacks is less than 2, let d be the + * destination to which t was sent. If cacc_saw_newack + * is 0 for destination d, then the sender MUST NOT + * increment missing report count for t. + */ +static inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport, + int count_of_newacks) +{ + if (count_of_newacks < 2 && !transport->cacc.cacc_saw_newack) + return 1; + return 0; +} + +/* + * SFR-CACC algorithm: + * 3.1) If CYCLING_CHANGEOVER is 0, the sender SHOULD + * execute steps C, D, F. + * + * C has been implemented in sctp_outq_sack + */ +static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary, + struct sctp_transport *transport, + int count_of_newacks) +{ + if (!primary->cacc.cycling_changeover) { + if (sctp_cacc_skip_3_1_d(primary, transport, count_of_newacks)) + return 1; + if (sctp_cacc_skip_3_1_f(transport, count_of_newacks)) + return 1; + return 0; + } + return 0; +} + +/* + * SFR-CACC algorithm: + * 3.2) Else if CYCLING_CHANGEOVER is 1, and t is less + * than next_tsn_at_change of the current primary, then + * the sender MUST NOT increment missing report count + * for t. + */ +static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn) +{ + if (primary->cacc.cycling_changeover && + TSN_lt(tsn, primary->cacc.next_tsn_at_change)) + return 1; + return 0; +} + +/* + * SFR-CACC algorithm: + * 3) If the missing report count for TSN t is to be + * incremented according to [RFC2960] and + * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, + * then the sender MUST futher execute steps 3.1 and + * 3.2 to determine if the missing report count for + * TSN t SHOULD NOT be incremented. + * + * 3.3) If 3.1 and 3.2 do not dictate that the missing + * report count for t should not be incremented, then + * the sender SOULD increment missing report count for + * t (according to [RFC2960] and [SCTP_STEWART_2002]). + */ +static inline int sctp_cacc_skip(struct sctp_transport *primary, + struct sctp_transport *transport, + int count_of_newacks, + __u32 tsn) +{ + if (primary->cacc.changeover_active && + (sctp_cacc_skip_3_1(primary, transport, count_of_newacks) + || sctp_cacc_skip_3_2(primary, tsn))) + return 1; + return 0; +} + /* Generate a new outqueue. */ struct sctp_outq *sctp_outq_new(struct sctp_association *asoc) { @@ -133,6 +231,7 @@ void sctp_outq_init(struct sctp_associat q->outstanding_bytes = 0; q->empty = 1; + q->cork = 0; q->malloced = 0; q->out_qlen = 0; @@ -144,59 +243,51 @@ void sctp_outq_teardown(struct sctp_outq { struct sctp_transport *transport; struct list_head *lchunk, *pos, *temp; - sctp_chunk_t *chunk; - struct sctp_ulpevent *ev; + struct sctp_chunk *chunk; /* Throw away unacknowledged chunks. */ list_for_each(pos, &q->asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); while ((lchunk = sctp_list_dequeue(&transport->transmitted))) { - chunk = list_entry(lchunk, sctp_chunk_t, + chunk = list_entry(lchunk, struct sctp_chunk, transmitted_list); - - /* Generate a SEND FAILED event. */ - ev = sctp_ulpevent_make_send_failed(q->asoc, - chunk, SCTP_DATA_SENT, - q->error, GFP_ATOMIC); - if (ev) - sctp_ulpq_tail_event(&q->asoc->ulpq, ev); - - sctp_free_chunk(chunk); + /* Mark as part of a failed message. */ + sctp_datamsg_fail(chunk, q->error); + sctp_chunk_free(chunk); } } /* Throw away chunks that have been gap ACKed. */ list_for_each_safe(lchunk, temp, &q->sacked) { - list_del(lchunk); - chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); - sctp_free_chunk(chunk); + list_del_init(lchunk); + chunk = list_entry(lchunk, struct sctp_chunk, + transmitted_list); + sctp_datamsg_fail(chunk, q->error); + sctp_chunk_free(chunk); } /* Throw away any chunks in the retransmit queue. */ list_for_each_safe(lchunk, temp, &q->retransmit) { - list_del(lchunk); - chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); - sctp_free_chunk(chunk); + list_del_init(lchunk); + chunk = list_entry(lchunk, struct sctp_chunk, + transmitted_list); + sctp_datamsg_fail(chunk, q->error); + sctp_chunk_free(chunk); } /* Throw away any leftover data chunks. */ while ((chunk = sctp_outq_dequeue_data(q))) { - /* Generate a SEND FAILED event. */ - ev = sctp_ulpevent_make_send_failed(q->asoc, - chunk, SCTP_DATA_UNSENT, - q->error, GFP_ATOMIC); - if (ev) - sctp_ulpq_tail_event(&q->asoc->ulpq, ev); - - sctp_free_chunk(chunk); + /* Mark as send failure. */ + sctp_datamsg_fail(chunk, q->error); + sctp_chunk_free(chunk); } q->error = 0; /* Throw away any leftover control chunks. */ - while ((chunk = (sctp_chunk_t *) skb_dequeue(&q->control))) - sctp_free_chunk(chunk); + while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control))) + sctp_chunk_free(chunk); } /* Free the outqueue structure and any related pending chunks. */ @@ -211,7 +302,7 @@ void sctp_outq_free(struct sctp_outq *q) } /* Put a new chunk in an sctp_outq. */ -int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk) +int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) { int error = 0; @@ -266,7 +357,8 @@ int sctp_outq_tail(struct sctp_outq *q, if (error < 0) return error; - error = sctp_outq_flush(q, 0); + if (!q->cork) + error = sctp_outq_flush(q, 0); return error; } @@ -277,15 +369,16 @@ int sctp_outq_tail(struct sctp_outq *q, void sctp_retransmit_insert(struct list_head *tlchunk, struct sctp_outq *q) { struct list_head *rlchunk; - sctp_chunk_t *tchunk, *rchunk; + struct sctp_chunk *tchunk, *rchunk; __u32 ttsn, rtsn; int done = 0; - tchunk = list_entry(tlchunk, sctp_chunk_t, transmitted_list); + tchunk = list_entry(tlchunk, struct sctp_chunk, transmitted_list); ttsn = ntohl(tchunk->subh.data_hdr->tsn); list_for_each(rlchunk, &q->retransmit) { - rchunk = list_entry(rlchunk, sctp_chunk_t, transmitted_list); + rchunk = list_entry(rlchunk, struct sctp_chunk, + transmitted_list); rtsn = ntohl(rchunk->subh.data_hdr->tsn); if (TSN_lt(ttsn, rtsn)) { list_add(tlchunk, rlchunk->prev); @@ -304,11 +397,12 @@ void sctp_retransmit_mark(struct sctp_ou __u8 fast_retransmit) { struct list_head *lchunk, *ltemp; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; /* Walk through the specified transmitted queue. */ list_for_each_safe(lchunk, ltemp, &transport->transmitted) { - chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); + chunk = list_entry(lchunk, struct sctp_chunk, + transmitted_list); /* If we are doing retransmission due to a fast retransmit, * only the chunk's that are marked for fast retransmit @@ -352,7 +446,7 @@ void sctp_retransmit_mark(struct sctp_ou /* Move the chunk to the retransmit queue. The chunks * on the retransmit queue is always kept in order. */ - list_del(lchunk); + list_del_init(lchunk); sctp_retransmit_insert(lchunk, q); } } @@ -399,7 +493,7 @@ void sctp_retransmit(struct sctp_outq *q error = sctp_outq_flush(q, /* rtx_timeout */ 1); if (error) - q->asoc->base.sk->err = -error; + q->asoc->base.sk->sk_err = -error; } /* @@ -417,7 +511,7 @@ static int sctp_outq_flush_rtx(struct sc struct list_head *lchunk; struct sctp_transport *transport = pkt->transport; sctp_xmit_t status; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; struct sctp_association *asoc; int error = 0; @@ -443,7 +537,8 @@ static int sctp_outq_flush_rtx(struct sc lchunk = sctp_list_dequeue(lqueue); while (lchunk) { - chunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); + chunk = list_entry(lchunk, struct sctp_chunk, + transmitted_list); /* Make sure that Gap Acked TSNs are not retransmitted. A * simple approach is just to move such TSNs out of the @@ -505,215 +600,19 @@ static int sctp_outq_flush_rtx(struct sc return error; } -/* This routine either transmits the fragment or puts it on the output - * queue. 'pos' points to the next chunk in the output queue after the - * chunk that is currently in the process of fragmentation. - */ -void sctp_xmit_frag(struct sctp_outq *q, struct sctp_chunk *pos, - struct sctp_packet *packet, struct sctp_chunk *frag, __u32 tsn) -{ - struct sctp_transport *transport = packet->transport; - struct sk_buff_head *queue = &q->out; - sctp_xmit_t status; - int error; - - frag->subh.data_hdr->tsn = htonl(tsn); - frag->has_tsn = 1; - - /* An inner fragment may be smaller than the earlier one and may get - * in if we call q->build_output. This ensures that all the fragments - * are sent in order. - */ - if (!skb_queue_empty(queue)) { - SCTP_DEBUG_PRINTK("sctp_xmit_frag: q not empty. " - "adding 0x%x to outqueue\n", - ntohl(frag->subh.data_hdr->tsn)); - if (pos) - sctp_outq_insert_data(q, frag, pos); - else - sctp_outq_tail_data(q, frag); - return; - } - - /* Add the chunk fragment to the packet. */ - status = (*q->build_output)(packet, frag); - switch (status) { - case SCTP_XMIT_RWND_FULL: - /* RWND is full, so put the chunk in the output queue. */ - SCTP_DEBUG_PRINTK("sctp_xmit_frag: rwnd full. " - "adding 0x%x to outqueue\n", - ntohl(frag->subh.data_hdr->tsn)); - if (pos) - sctp_outq_insert_data(q, frag, pos); - else - sctp_outq_tail_data(q, frag); - break; - - case SCTP_XMIT_OK: - error = (*q->force_output)(packet); - if (error < 0) { - /* Packet could not be transmitted, put the chunk in - * the output queue - */ - SCTP_DEBUG_PRINTK("sctp_xmit_frag: force output " - "failed. adding 0x%x to outqueue\n", - ntohl(frag->subh.data_hdr->tsn)); - if (pos) - sctp_outq_insert_data(q, frag, pos); - else - sctp_outq_tail_data(q, frag); - } else { - SCTP_DEBUG_PRINTK("sctp_xmit_frag: force output " - "success. 0x%x sent\n", - ntohl(frag->subh.data_hdr->tsn)); - list_add_tail(&frag->transmitted_list, - &transport->transmitted); - - sctp_transport_reset_timers(transport); - } - break; - - default: - BUG(); - }; -} - -/* This routine calls sctp_xmit_frag() for all the fragments of a message. - * The argument 'frag' point to the first fragment and it holds the list - * of all the other fragments in the 'frag_list' field. - */ -void sctp_xmit_fragmented_chunks(struct sctp_outq *q, struct sctp_packet *pkt, - sctp_chunk_t *frag) -{ - struct sctp_association *asoc = frag->asoc; - struct list_head *lfrag, *frag_list; - __u32 tsn; - int nfrags = 1; - struct sctp_chunk *pos; - - /* Count the number of fragments. */ - frag_list = &frag->frag_list; - list_for_each(lfrag, frag_list) { - nfrags++; - } - - /* Get a TSN block of nfrags TSNs. */ - tsn = sctp_association_get_tsn_block(asoc, nfrags); - - pos = (struct sctp_chunk *)skb_peek(&q->out); - /* Transmit the first fragment. */ - sctp_xmit_frag(q, pos, pkt, frag, tsn++); - - /* Transmit the rest of fragments. */ - frag_list = &frag->frag_list; - list_for_each(lfrag, frag_list) { - frag = list_entry(lfrag, sctp_chunk_t, frag_list); - sctp_xmit_frag(q, pos, pkt, frag, tsn++); - } -} - -/* This routine breaks the given chunk into 'max_frag_data_len' size - * fragments. It returns the first fragment with the frag_list field holding - * the remaining fragments. - */ -sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, - size_t max_frag_data_len) +/* Cork the outqueue so queued chunks are really queued. */ +int sctp_outq_uncork(struct sctp_outq *q) { - struct sctp_association *asoc = chunk->asoc; - void *data_ptr = chunk->subh.data_hdr; - struct sctp_sndrcvinfo *sinfo = &chunk->sinfo; - __u16 chunk_data_len = sctp_data_size(chunk); - __u16 ssn = ntohs(chunk->subh.data_hdr->ssn); - sctp_chunk_t *first_frag, *frag; - struct list_head *frag_list; - int nfrags; - __u8 old_flags, flags; - - /* nfrags = no. of max size fragments + any smaller last fragment. */ - nfrags = ((chunk_data_len / max_frag_data_len) + - ((chunk_data_len % max_frag_data_len) ? 1 : 0)); - - /* Start of the data in the chunk. */ - data_ptr += sizeof(sctp_datahdr_t); - - /* Are we fragmenting an already fragmented large message? */ - old_flags = chunk->chunk_hdr->flags; - if (old_flags & SCTP_DATA_FIRST_FRAG) - flags = SCTP_DATA_FIRST_FRAG; - else - flags = SCTP_DATA_MIDDLE_FRAG; - - /* Make the first fragment. */ - first_frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len, - data_ptr, flags, ssn); - - if (!first_frag) - goto err; - first_frag->has_ssn = 1; - /* All the fragments are added to the frag_list of the first chunk. */ - frag_list = &first_frag->frag_list; - - chunk_data_len -= max_frag_data_len; - data_ptr += max_frag_data_len; - - /* Make the middle fragments. */ - while (chunk_data_len > max_frag_data_len) { - frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len, - data_ptr, SCTP_DATA_MIDDLE_FRAG, - ssn); - if (!frag) - goto err; - frag->has_ssn = 1; - /* Add the middle fragment to the first fragment's - * frag_list. - */ - list_add_tail(&frag->frag_list, frag_list); - - chunk_data_len -= max_frag_data_len; - data_ptr += max_frag_data_len; - } - - if (old_flags & SCTP_DATA_LAST_FRAG) - flags = SCTP_DATA_LAST_FRAG; - else - flags = SCTP_DATA_MIDDLE_FRAG; - - /* Make the last fragment. */ - frag = sctp_make_datafrag(asoc, sinfo, chunk_data_len, data_ptr, - flags, ssn); - if (!frag) - goto err; - frag->has_ssn = 1; - - /* Add the last fragment to the first fragment's frag_list. */ - list_add_tail(&frag->frag_list, frag_list); - - /* Free the original chunk. */ - sctp_free_chunk(chunk); - - return first_frag; - -err: - /* Free any fragments that are created before the failure. */ - if (first_frag) { - struct list_head *flist, *lfrag; - - /* Free all the fragments off the first one. */ - flist = &first_frag->frag_list; - while (NULL != (lfrag = sctp_list_dequeue(flist))) { - frag = list_entry(lfrag, sctp_chunk_t, frag_list); - sctp_free_chunk(frag); - } - - /* Free the first fragment. */ - sctp_free_chunk(first_frag); + int error = 0; + if (q->cork) { + q->cork = 0; + error = sctp_outq_flush(q, 0); } - - return NULL; + return error; } /* - * sctp_outq_flush - Try to flush an outqueue. + * Try to flush an outqueue. * * Description: Send everything in q which we legally can, subject to * congestion limitations. @@ -736,7 +635,7 @@ int sctp_outq_flush(struct sctp_outq *q, struct sk_buff_head *queue; struct sctp_transport *transport = NULL; struct sctp_transport *new_transport; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; sctp_xmit_t status; int error = 0; int start_timer = 0; @@ -763,7 +662,7 @@ int sctp_outq_flush(struct sctp_outq *q, } queue = &q->control; - while ((chunk = (sctp_chunk_t *)skb_dequeue(queue))) { + while ((chunk = (struct sctp_chunk *)skb_dequeue(queue))) { /* Pick the right transport to use. */ new_transport = chunk->transport; @@ -903,32 +802,25 @@ int sctp_outq_flush(struct sctp_outq *q, */ if (chunk->sinfo.sinfo_stream >= asoc->c.sinit_num_ostreams) { - struct sctp_ulpevent *ev; - /* Generate a SEND FAILED event. */ - ev = sctp_ulpevent_make_send_failed(asoc, - chunk, SCTP_DATA_UNSENT, - SCTP_ERROR_INV_STRM, GFP_ATOMIC); - if (ev) - sctp_ulpq_tail_event(&asoc->ulpq, ev); - - /* Free the chunk. */ - sctp_free_chunk(chunk); + /* Mark as s failed send. */ + sctp_datamsg_fail(chunk, SCTP_ERROR_INV_STRM); + sctp_chunk_free(chunk); continue; } - /* Now do delayed assignment of SSN. This will - * probably change again when we start supporting - * large (> approximately 2^16) size messages. - */ - sctp_chunk_assign_ssn(chunk); + /* Has this chunk expired? */ + if (sctp_datamsg_expires(chunk)) { + sctp_datamsg_fail(chunk, 0); + sctp_chunk_free(chunk); + continue; + } /* If there is a specified transport, use it. * Otherwise, we want to use the active path. */ new_transport = chunk->transport; - if (new_transport == NULL || - !new_transport->active) + if (!new_transport || !new_transport->active) new_transport = asoc->peer.active_path; /* Change packets if necessary. */ @@ -980,26 +872,6 @@ int sctp_outq_flush(struct sctp_outq *q, goto sctp_flush_out; break; - case SCTP_XMIT_MUST_FRAG: { - sctp_chunk_t *frag; - - frag = sctp_fragment_chunk(chunk, - packet->transport->asoc->frag_point); - if (!frag) { - /* We could not fragment due to out of - * memory condition. Free the original - * chunk and return ENOMEM. - */ - sctp_free_chunk(chunk); - error = -ENOMEM; - return error; - } - - sctp_xmit_fragmented_chunks(q, packet, frag); - goto sctp_flush_out; - break; - } - case SCTP_XMIT_OK: break; @@ -1079,7 +951,7 @@ int sctp_outq_set_output_handlers(struct /* Update unack_data based on the incoming SACK chunk */ static void sctp_sack_update_unack_data(struct sctp_association *assoc, - sctp_sackhdr_t *sack) + struct sctp_sackhdr *sack) { sctp_sack_variable_t *frags; __u16 unack_data; @@ -1097,12 +969,12 @@ static void sctp_sack_update_unack_data( } /* Return the highest new tsn that is acknowledged by the given SACK chunk. */ -static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack, +static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack, struct sctp_association *asoc) { struct list_head *ltransport, *lchunk; struct sctp_transport *transport; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; __u32 highest_new_tsn, tsn; struct list_head *transport_list = &asoc->peer.transport_addr_list; @@ -1112,7 +984,7 @@ static __u32 sctp_highest_new_tsn(sctp_s transport = list_entry(ltransport, struct sctp_transport, transports); list_for_each(lchunk, &transport->transmitted) { - chunk = list_entry(lchunk, sctp_chunk_t, + chunk = list_entry(lchunk, struct sctp_chunk, transmitted_list); tsn = ntohl(chunk->subh.data_hdr->tsn); @@ -1131,26 +1003,64 @@ static __u32 sctp_highest_new_tsn(sctp_s * Process the SACK against the outqueue. Mostly, this just frees * things off the transmitted queue. */ -int sctp_outq_sack(struct sctp_outq *q, sctp_sackhdr_t *sack) +int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) { struct sctp_association *asoc = q->asoc; struct sctp_transport *transport; - sctp_chunk_t *tchunk; - struct list_head *lchunk, *transport_list, *pos; + struct sctp_chunk *tchunk; + struct list_head *lchunk, *transport_list, *pos, *temp; sctp_sack_variable_t *frags = sack->variable; __u32 sack_ctsn, ctsn, tsn; __u32 highest_tsn, highest_new_tsn; __u32 sack_a_rwnd; - int outstanding; + unsigned outstanding; + struct sctp_transport *primary = asoc->peer.primary_path; + int count_of_newacks = 0; /* Grab the association's destination address list. */ transport_list = &asoc->peer.transport_addr_list; sack_ctsn = ntohl(sack->cum_tsn_ack); + /* + * SFR-CACC algorithm: + * On receipt of a SACK the sender SHOULD execute the + * following statements. + * + * 1) If the cumulative ack in the SACK passes next tsn_at_change + * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be + * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for + * all destinations. + */ + if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { + primary->cacc.changeover_active = 0; + list_for_each(pos, transport_list) { + transport = list_entry(pos, struct sctp_transport, + transports); + transport->cacc.cycling_changeover = 0; + } + } + + /* + * SFR-CACC algorithm: + * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE + * is set the receiver of the SACK MUST take the following actions: + * + * A) Initialize the cacc_saw_newack to 0 for all destination + * addresses. + */ + if (sack->num_gap_ack_blocks > 0 && + primary->cacc.changeover_active) { + list_for_each(pos, transport_list) { + transport = list_entry(pos, struct sctp_transport, + transports); + transport->cacc.cacc_saw_newack = 0; + } + } + /* Get the highest TSN in the sack. */ highest_tsn = sack_ctsn + - ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); + ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); if (TSN_lt(asoc->highest_sacked, highest_tsn)) { highest_new_tsn = highest_tsn; @@ -1163,6 +1073,7 @@ int sctp_outq_sack(struct sctp_outq *q, * and free those chunks that we can. */ sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); + sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); /* Run through the transmitted queue. * Credit bytes received and free those chunks which we can. @@ -1174,6 +1085,20 @@ int sctp_outq_sack(struct sctp_outq *q, transports); sctp_check_transmitted(q, &transport->transmitted, transport, sack, highest_new_tsn); + /* + * SFR-CACC algorithm: + * C) Let count_of_newacks be the number of + * destinations for which cacc_saw_newack is set. + */ + if (transport->cacc.cacc_saw_newack) + count_of_newacks ++; + } + + list_for_each(pos, transport_list) { + transport = list_entry(pos, struct sctp_transport, + transports); + sctp_mark_missing(q, &transport->transmitted, transport, + highest_new_tsn, count_of_newacks); } /* Move the Cumulative TSN Ack Point if appropriate. */ @@ -1191,13 +1116,12 @@ int sctp_outq_sack(struct sctp_outq *q, "%p is 0x%x.\n", __FUNCTION__, asoc, ctsn); /* Throw away stuff rotting on the sack queue. */ - list_for_each(lchunk, &q->sacked) { - tchunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); + list_for_each_safe(lchunk, temp, &q->sacked) { + tchunk = list_entry(lchunk, struct sctp_chunk, + transmitted_list); tsn = ntohl(tchunk->subh.data_hdr->tsn); - if (TSN_lte(tsn, ctsn)) { - lchunk = lchunk->prev; - sctp_free_chunk(tchunk); - } + if (TSN_lte(tsn, ctsn)) + sctp_chunk_free(tchunk); } /* ii) Set rwnd equal to the newly received a_rwnd minus the @@ -1245,12 +1169,9 @@ int sctp_outq_is_empty(const struct sctp * 2nd Level Abstractions ********************************************************************/ -/* Go through a transport's transmitted list or the assocication's retransmit +/* Go through a transport's transmitted list or the association's retransmit * list and move chunks that are acked by the Cumulative TSN Ack to q->sacked. - * The retransmit list will not have an associated transport. In case of a - * transmitted list with a transport, the transport's congestion, rto and fast - * retransmit parameters are also updated and if needed a fast retransmit - * process is started. + * The retransmit list will not have an associated transport. * * I added coherent debug information output. --xguo * @@ -1261,17 +1182,16 @@ int sctp_outq_is_empty(const struct sctp static void sctp_check_transmitted(struct sctp_outq *q, struct list_head *transmitted_queue, struct sctp_transport *transport, - sctp_sackhdr_t *sack, + struct sctp_sackhdr *sack, __u32 highest_new_tsn_in_sack) { struct list_head *lchunk; - sctp_chunk_t *tchunk; + struct sctp_chunk *tchunk; struct list_head tlist; __u32 tsn; __u32 sack_ctsn; __u32 rtt; __u8 restart_timer = 0; - __u8 do_fast_retransmit = 0; int bytes_acked = 0; /* These state variables are for coherent debug output. --xguo */ @@ -1295,7 +1215,8 @@ static void sctp_check_transmitted(struc /* The while loop will skip empty transmitted queues. */ while (NULL != (lchunk = sctp_list_dequeue(transmitted_queue))) { - tchunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); + tchunk = list_entry(lchunk, struct sctp_chunk, + transmitted_list); tsn = ntohl(tchunk->subh.data_hdr->tsn); if (sctp_acked(sack, tsn)) { @@ -1316,9 +1237,9 @@ static void sctp_check_transmitted(struc * first instance of the packet or a later * instance). */ - if ((!tchunk->tsn_gap_acked) && - (1 == tchunk->num_times_sent) && - (tchunk->rtt_in_progress)) { + if (!tchunk->tsn_gap_acked && + !tchunk->resent && + tchunk->rtt_in_progress) { rtt = jiffies - tchunk->sent_at; sctp_transport_update_rto(transport, rtt); @@ -1339,6 +1260,25 @@ static void sctp_check_transmitted(struc if (!tchunk->tsn_gap_acked) { tchunk->tsn_gap_acked = 1; bytes_acked += sctp_data_size(tchunk); + /* + * SFR-CACC algorithm: + * 2) If the SACK contains gap acks + * and the flag CHANGEOVER_ACTIVE is + * set the receiver of the SACK MUST + * take the following action: + * + * B) For each TSN t being acked that + * has not been acked in any SACK so + * far, set cacc_saw_newack to 1 for + * the destination that the TSN was + * sent to. + */ + if (transport && + sack->num_gap_ack_blocks && + q->asoc->peer.primary_path->cacc. + changeover_active) + transport->cacc.cacc_saw_newack + = 1; } list_add_tail(&tchunk->transmitted_list, @@ -1525,8 +1465,8 @@ static void sctp_check_transmitted(struc * receiver's advertised window is zero, and there is * only one data chunk in flight to the receiver. */ - if ((0 == q->asoc->peer.rwnd) && - (!list_empty(&tlist)) && + if (!q->asoc->peer.rwnd && + !list_empty(&tlist) && (sack_ctsn+2 == q->asoc->next_tsn)) { SCTP_DEBUG_PRINTK("%s: SACK received for zero " "window probe: %u\n", @@ -1554,12 +1494,26 @@ static void sctp_check_transmitted(struc } } - /* Reconstruct the transmitted list with chunks that are not yet - * acked by the Cumulative TSN Ack. - */ - while (NULL != (lchunk = sctp_list_dequeue(&tlist))) { - tchunk = list_entry(lchunk, sctp_chunk_t, transmitted_list); - tsn = ntohl(tchunk->subh.data_hdr->tsn); + list_splice(&tlist, transmitted_queue); +} + +/* Mark chunks as missing and consequently may get retransmitted. */ +static void sctp_mark_missing(struct sctp_outq *q, + struct list_head *transmitted_queue, + struct sctp_transport *transport, + __u32 highest_new_tsn_in_sack, + int count_of_newacks) +{ + struct sctp_chunk *chunk; + struct list_head *pos; + __u32 tsn; + char do_fast_retransmit = 0; + struct sctp_transport *primary = q->asoc->peer.primary_path; + + list_for_each(pos, transmitted_queue) { + + chunk = list_entry(pos, struct sctp_chunk, transmitted_list); + tsn = ntohl(chunk->subh.data_hdr->tsn); /* RFC 2960 7.2.4, sctpimpguide-05 2.8.2 M3) Examine all * 'Unacknowledged TSN's', if the TSN number of an @@ -1567,26 +1521,35 @@ static void sctp_check_transmitted(struc * value, increment the 'TSN.Missing.Report' count on that * chunk if it has NOT been fast retransmitted or marked for * fast retransmit already. - * + */ + if (!chunk->fast_retransmit && + !chunk->tsn_gap_acked && + TSN_lt(tsn, highest_new_tsn_in_sack)) { + + /* SFR-CACC may require us to skip marking + * this chunk as missing. + */ + if (!transport || !sctp_cacc_skip(primary, transport, + count_of_newacks, tsn)) { + chunk->tsn_missing_report++; + + SCTP_DEBUG_PRINTK( + "%s: TSN 0x%x missing counter: %d\n", + __FUNCTION__, tsn, + chunk->tsn_missing_report); + } + } + /* * M4) If any DATA chunk is found to have a * 'TSN.Missing.Report' * value larger than or equal to 4, mark that chunk for * retransmission and start the fast retransmit procedure. */ - if ((!tchunk->fast_retransmit) && - (!tchunk->tsn_gap_acked) && - (TSN_lt(tsn, highest_new_tsn_in_sack))) { - tchunk->tsn_missing_report++; - SCTP_DEBUG_PRINTK("%s: TSN 0x%x missing counter: %d\n", - __FUNCTION__, tsn, - tchunk->tsn_missing_report); - } - if (tchunk->tsn_missing_report >= 4) { - tchunk->fast_retransmit = 1; + + if (chunk->tsn_missing_report >= 4) { + chunk->fast_retransmit = 1; do_fast_retransmit = 1; } - - list_add_tail(lchunk, transmitted_queue); } if (transport) { @@ -1602,7 +1565,7 @@ static void sctp_check_transmitted(struc } /* Is the given TSN acked by this packet? */ -static int sctp_acked(sctp_sackhdr_t *sack, __u32 tsn) +static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn) { int i; sctp_sack_variable_t *frags; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/primitive.c linux-2.4.26-pre1/net/sctp/primitive.c --- linux-2.4.25/net/sctp/primitive.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/primitive.c 2004-02-25 15:41:13.000000000 +0000 @@ -39,6 +39,7 @@ * Narasimha Budihal * Karl Knutson * Ardelle Fan + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -203,3 +204,16 @@ DECLARE_PRIMITIVE(SEND); */ DECLARE_PRIMITIVE(REQUESTHEARTBEAT); + +/* ADDIP +* 3.1.1 Address Configuration Change Chunk (ASCONF) +* +* This chunk is used to communicate to the remote endpoint one of the +* configuration change requests that MUST be acknowledged. The +* information carried in the ASCONF Chunk uses the form of a +* Type-Length-Value (TLV), as described in "3.2.1 Optional/ +* Variable-length Parameter Format" in RFC2960 [5], forall variable +* parameters. +*/ + +DECLARE_PRIMITIVE(ASCONF); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/proc.c linux-2.4.26-pre1/net/sctp/proc.c --- linux-2.4.25/net/sctp/proc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/proc.c 2004-02-25 15:41:40.000000000 +0000 @@ -35,8 +35,6 @@ */ #include -#include -#include #include #include #include @@ -92,6 +90,7 @@ static int sctp_snmp_seq_show(struct seq for (i = 0; i < sizeof(sctp_snmp_list) / sizeof(char *); i++) seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i], fold_field((void **)sctp_statistics, i)); + return 0; } @@ -102,6 +101,7 @@ static int sctp_snmp_seq_open(struct ino } static struct file_operations sctp_snmp_seq_fops = { + .owner = THIS_MODULE, .open = sctp_snmp_seq_open, .read = seq_read, .llseek = seq_lseek, @@ -127,3 +127,162 @@ void sctp_snmp_proc_exit(void) { remove_proc_entry("snmp", proc_net_sctp); } + +/* Dump local addresses of an association/endpoint. */ +static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb) +{ + struct list_head *pos; + struct sctp_sockaddr_entry *laddr; + union sctp_addr *addr; + struct sctp_af *af; + + list_for_each(pos, &epb->bind_addr.address_list) { + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); + addr = (union sctp_addr *)&laddr->a; + af = sctp_get_af_specific(addr->sa.sa_family); + af->seq_dump_addr(seq, addr); + } +} + +/* Dump remote addresses of an association. */ +static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc) +{ + struct list_head *pos; + struct sctp_transport *transport; + union sctp_addr *addr; + struct sctp_af *af; + + list_for_each(pos, &assoc->peer.transport_addr_list) { + transport = list_entry(pos, struct sctp_transport, transports); + addr = (union sctp_addr *)&transport->ipaddr; + af = sctp_get_af_specific(addr->sa.sa_family); + af->seq_dump_addr(seq, addr); + } +} + +/* Display sctp endpoints (/proc/net/sctp/eps). */ +static int sctp_eps_seq_show(struct seq_file *seq, void *v) +{ + struct sctp_hashbucket *head; + struct sctp_ep_common *epb; + struct sctp_endpoint *ep; + struct sock *sk; + int hash; + + seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT LADDRS\n"); + for (hash = 0; hash < sctp_ep_hashsize; hash++) { + head = &sctp_ep_hashtable[hash]; + read_lock(&head->lock); + for (epb = head->chain; epb; epb = epb->next) { + ep = sctp_ep(epb); + sk = epb->sk; + seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d ", ep, sk, + sctp_sk(sk)->type, sk->sk_state, hash, + epb->bind_addr.port); + sctp_seq_dump_local_addrs(seq, epb); + seq_printf(seq, "\n"); + } + read_unlock(&head->lock); + } + + return 0; +} + +/* Initialize the seq file operations for 'eps' object. */ +static int sctp_eps_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, sctp_eps_seq_show, NULL); +} + +static struct file_operations sctp_eps_seq_fops = { + .open = sctp_eps_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* Set up the proc fs entry for 'eps' object. */ +int __init sctp_eps_proc_init(void) +{ + struct proc_dir_entry *p; + + p = create_proc_entry("eps", S_IRUGO, proc_net_sctp); + if (!p) + return -ENOMEM; + + p->proc_fops = &sctp_eps_seq_fops; + + return 0; +} + +/* Cleanup the proc fs entry for 'eps' object. */ +void sctp_eps_proc_exit(void) +{ + remove_proc_entry("eps", proc_net_sctp); +} + +/* Display sctp associations (/proc/net/sctp/assocs). */ +static int sctp_assocs_seq_show(struct seq_file *seq, void *v) +{ + struct sctp_hashbucket *head; + struct sctp_ep_common *epb; + struct sctp_association *assoc; + struct sock *sk; + int hash; + + seq_printf(seq, " ASSOC SOCK STY SST ST HBKT LPORT RPORT " + "LADDRS <-> RADDRS\n"); + for (hash = 0; hash < sctp_assoc_hashsize; hash++) { + head = &sctp_assoc_hashtable[hash]; + read_lock(&head->lock); + for (epb = head->chain; epb; epb = epb->next) { + assoc = sctp_assoc(epb); + sk = epb->sk; + seq_printf(seq, + "%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ", + assoc, sk, sctp_sk(sk)->type, sk->sk_state, + assoc->state, hash, epb->bind_addr.port, + assoc->peer.port); + sctp_seq_dump_local_addrs(seq, epb); + seq_printf(seq, "<-> "); + sctp_seq_dump_remote_addrs(seq, assoc); + seq_printf(seq, "\n"); + } + read_unlock(&head->lock); + } + + return 0; +} + +/* Initialize the seq file operations for 'assocs' object. */ +static int sctp_assocs_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, sctp_assocs_seq_show, NULL); +} + +static struct file_operations sctp_assocs_seq_fops = { + .open = sctp_assocs_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* Set up the proc fs entry for 'assocs' object. */ +int __init sctp_assocs_proc_init(void) +{ + struct proc_dir_entry *p; + + p = create_proc_entry("assocs", S_IRUGO, proc_net_sctp); + if (!p) + return -ENOMEM; + + p->proc_fops = &sctp_assocs_seq_fops; + + return 0; +} + +/* Cleanup the proc fs entry for 'assocs' object. */ +void sctp_assocs_proc_exit(void) +{ + remove_proc_entry("assocs", proc_net_sctp); +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/protocol.c linux-2.4.26-pre1/net/sctp/protocol.c --- linux-2.4.25/net/sctp/protocol.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/protocol.c 2004-02-25 15:43:25.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -50,15 +50,17 @@ #include #include #include +#include #include #include #include #include #include #include +#include /* Global data structures. */ -struct sctp_protocol sctp_proto; +struct sctp_globals sctp_globals; struct proc_dir_entry *proc_net_sctp; DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics); @@ -73,10 +75,16 @@ static struct sctp_pf *sctp_pf_inet_spec static struct sctp_af *sctp_af_v4_specific; static struct sctp_af *sctp_af_v6_specific; +kmem_cache_t *sctp_chunk_cachep; + extern struct net_proto_family inet_family_ops; extern int sctp_snmp_proc_init(void); extern int sctp_snmp_proc_exit(void); +extern int sctp_eps_proc_init(void); +extern int sctp_eps_proc_exit(void); +extern int sctp_assocs_proc_init(void); +extern int sctp_assocs_proc_exit(void); /* Return the address of the control sock. */ struct sock *sctp_get_ctl_sock(void) @@ -87,8 +95,6 @@ struct sock *sctp_get_ctl_sock(void) /* Set up the proc fs entry for the SCTP protocol. */ __init int sctp_proc_init(void) { - int rc = 0; - if (!proc_net_sctp) { struct proc_dir_entry *ent; ent = proc_mkdir("net/sctp", 0); @@ -96,20 +102,31 @@ __init int sctp_proc_init(void) ent->owner = THIS_MODULE; proc_net_sctp = ent; } else - rc = -ENOMEM; + goto out_nomem; } if (sctp_snmp_proc_init()) - rc = -ENOMEM; + goto out_nomem; + if (sctp_eps_proc_init()) + goto out_nomem; + if (sctp_assocs_proc_init()) + goto out_nomem; + + return 0; - return rc; +out_nomem: + return -ENOMEM; } -/* Clean up the proc fs entry for the SCTP protocol. */ +/* Clean up the proc fs entry for the SCTP protocol. + * Note: Do not make this __exit as it is used in the init error + * path. + */ void sctp_proc_exit(void) { - sctp_snmp_proc_exit(); + sctp_eps_proc_exit(); + sctp_assocs_proc_exit(); if (proc_net_sctp) { proc_net_sctp = NULL; @@ -125,7 +142,7 @@ static void sctp_v4_copy_addrlist(struct { struct in_device *in_dev; struct in_ifaddr *ifa; - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; read_lock(&inetdev_lock); if ((in_dev = __in_dev_get(dev)) == NULL) { @@ -136,7 +153,7 @@ static void sctp_v4_copy_addrlist(struct read_lock(&in_dev->lock); for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { /* Add the address to the local list. */ - addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC); + addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); if (addr) { addr->a.v4.sin_family = AF_INET; addr->a.v4.sin_port = 0; @@ -152,7 +169,7 @@ static void sctp_v4_copy_addrlist(struct /* Extract our IP addresses from the system and stash them in the * protocol structure. */ -static void __sctp_get_local_addr_list(struct sctp_protocol *proto) +static void __sctp_get_local_addr_list(void) { struct net_device *dev; struct list_head *pos; @@ -160,59 +177,58 @@ static void __sctp_get_local_addr_list(s read_lock(&dev_base_lock); for (dev = dev_base; dev; dev = dev->next) { - list_for_each(pos, &proto->address_families) { + list_for_each(pos, &sctp_address_families) { af = list_entry(pos, struct sctp_af, list); - af->copy_addrlist(&proto->local_addr_list, dev); + af->copy_addrlist(&sctp_local_addr_list, dev); } } read_unlock(&dev_base_lock); } -static void sctp_get_local_addr_list(struct sctp_protocol *proto) +static void sctp_get_local_addr_list(void) { unsigned long flags; - sctp_spin_lock_irqsave(&sctp_proto.local_addr_lock, flags); - __sctp_get_local_addr_list(&sctp_proto); - sctp_spin_unlock_irqrestore(&sctp_proto.local_addr_lock, flags); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + __sctp_get_local_addr_list(); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); } /* Free the existing local addresses. */ -static void __sctp_free_local_addr_list(struct sctp_protocol *proto) +static void __sctp_free_local_addr_list(void) { - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; - list_for_each_safe(pos, temp, &proto->local_addr_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); + list_for_each_safe(pos, temp, &sctp_local_addr_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); list_del(pos); kfree(addr); } } /* Free the existing local addresses. */ -static void sctp_free_local_addr_list(struct sctp_protocol *proto) +static void sctp_free_local_addr_list(void) { unsigned long flags; - sctp_spin_lock_irqsave(&proto->local_addr_lock, flags); - __sctp_free_local_addr_list(proto); - sctp_spin_unlock_irqrestore(&proto->local_addr_lock, flags); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + __sctp_free_local_addr_list(); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); } /* Copy the local addresses which are valid for 'scope' into 'bp'. */ -int sctp_copy_local_addr_list(struct sctp_protocol *proto, - struct sctp_bind_addr *bp, sctp_scope_t scope, +int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, int gfp, int copy_flags) { - struct sockaddr_storage_list *addr; + struct sctp_sockaddr_entry *addr; int error = 0; struct list_head *pos; unsigned long flags; - sctp_spin_lock_irqsave(&proto->local_addr_lock, flags); - list_for_each(pos, &proto->local_addr_list) { - addr = list_entry(pos, struct sockaddr_storage_list, list); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + list_for_each(pos, &sctp_local_addr_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); if (sctp_in_scope(&addr->a, scope)) { /* Now that the address is in scope, check to see if * the address type is really supported by the local @@ -232,7 +248,7 @@ int sctp_copy_local_addr_list(struct sct } end_copy: - sctp_spin_unlock_irqrestore(&proto->local_addr_lock, flags); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); return error; } @@ -262,20 +278,45 @@ static void sctp_v4_from_skb(union sctp_ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) { addr->v4.sin_family = AF_INET; - addr->v4.sin_port = (sk)->num; - addr->v4.sin_addr.s_addr = (sk)->rcv_saddr; + addr->v4.sin_port = sk->num; + addr->v4.sin_addr.s_addr = sk->rcv_saddr; } -/* Initialize sk->rcv_saddr from sctp_addr. */ +/* Initialize sk->sk_rcv_saddr from sctp_addr. */ static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk) { - (sk)->rcv_saddr = addr->v4.sin_addr.s_addr; + sk->rcv_saddr = addr->v4.sin_addr.s_addr; } -/* Initialize sk->daddr from sctp_addr. */ +/* Initialize sk->sk_daddr from sctp_addr. */ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) { - (sk)->daddr = addr->v4.sin_addr.s_addr; + sk->daddr = addr->v4.sin_addr.s_addr; +} + +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v4_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v4.sin_family = AF_INET; + addr->v4.sin_port = port; + addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v4_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv4addr_param_t); + + param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; + param->v4.param_hdr.length = ntohs(length); + param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; + + return length; } /* Initialize a sctp_addr from a dst_entry. */ @@ -323,7 +364,7 @@ static int sctp_v4_is_any(const union sc * Return 0 - If the address is a non-unicast or an illegal address. * Return 1 - If the address is a unicast. */ -static int sctp_v4_addr_valid(union sctp_addr *addr) +static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_opt *sp) { /* Is this a non-unicast address or a unusable SCTP address? */ if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) @@ -333,7 +374,7 @@ static int sctp_v4_addr_valid(union sctp } /* Should this be available for binding? */ -static int sctp_v4_available(const union sctp_addr *addr) +static int sctp_v4_available(union sctp_addr *addr, struct sctp_opt *sp) { int ret = inet_addr_type(addr->v4.sin_addr.s_addr); @@ -393,16 +434,20 @@ struct dst_entry *sctp_v4_get_dst(struct { struct rtable *rt; struct rt_key key; - sctp_bind_addr_t *bp; + struct sctp_bind_addr *bp; rwlock_t *addr_lock; - struct sockaddr_storage_list *laddr; + struct sctp_sockaddr_entry *laddr; struct list_head *pos; struct dst_entry *dst = NULL; union sctp_addr dst_saddr; - + memset(&key, 0x0, sizeof(struct rt_key)); key.dst = daddr->v4.sin_addr.s_addr; - + + if (asoc) { + key.tos = RT_CONN_FLAGS(asoc->base.sk); + key.oif = asoc->base.sk->bound_dev_if; + } if (saddr) key.src = saddr->v4.sin_addr.s_addr; @@ -429,7 +474,7 @@ struct dst_entry *sctp_v4_get_dst(struct */ sctp_read_lock(addr_lock); list_for_each(pos, &bp->address_list) { - laddr = list_entry(pos, struct sockaddr_storage_list, + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) @@ -449,7 +494,7 @@ struct dst_entry *sctp_v4_get_dst(struct */ sctp_read_lock(addr_lock); list_for_each(pos, &bp->address_list) { - laddr = list_entry(pos, struct sockaddr_storage_list, list); + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if (AF_INET == laddr->a.sa.sa_family) { key.src = laddr->a.v4.sin_addr.s_addr; @@ -490,11 +535,17 @@ void sctp_v4_get_saddr(struct sctp_assoc } /* What interface did this skb arrive on? */ -int sctp_v4_skb_iif(const struct sk_buff *skb) +static int sctp_v4_skb_iif(const struct sk_buff *skb) { return ((struct rtable *)skb->dst)->rt_iif; } +/* Was this packet marked by Explicit Congestion Notification? */ +static int sctp_v4_is_ce(const struct sk_buff *skb) +{ + return INET_ECN_is_ce(skb->nh.iph->tos); +} + /* Create and initialize a new sk for the socket returned by accept(). */ struct sock *sctp_v4_create_accept_sk(struct sock *sk, struct sctp_association *asoc) @@ -510,18 +561,18 @@ struct sock *sctp_v4_create_accept_sk(st sock_init_data(NULL, newsk); sk_set_owner(newsk, THIS_MODULE); - newsk->type = SOCK_STREAM; + newsk->sk_type = SOCK_STREAM; - newsk->prot = sk->prot; - newsk->no_check = sk->no_check; - newsk->reuse = sk->reuse; - newsk->shutdown = sk->shutdown; - - newsk->destruct = inet_sock_destruct; - newsk->zapped = 0; - newsk->family = PF_INET; - newsk->protocol = IPPROTO_SCTP; - newsk->backlog_rcv = sk->prot->backlog_rcv; + newsk->sk_prot = sk->sk_prot; + newsk->sk_no_check = sk->sk_no_check; + newsk->sk_reuse = sk->sk_reuse; + newsk->sk_shutdown = sk->sk_shutdown; + + newsk->sk_destruct = inet_sock_destruct; + newsk->sk_zapped = 0; + newsk->sk_family = PF_INET; + newsk->sk_protocol = IPPROTO_SCTP; + newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; newinet = inet_sk(newsk); @@ -546,7 +597,7 @@ struct sock *sctp_v4_create_accept_sk(st atomic_inc(&inet_sock_nr); #endif - if (0 != newsk->prot->init(newsk)) { + if (newsk->sk_prot->init(newsk)) { inet_sock_release(newsk); newsk = NULL; } @@ -555,6 +606,18 @@ out: return newsk; } +/* Map address, empty for v4 family */ +static void sctp_v4_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr) +{ + /* Empty */ +} + +/* Dump the v4 addr to the seq file. */ +static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) +{ + seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr)); +} + /* Event handler for inet address addition/deletion events. * Basically, whenever there is an event, we re-build our local address list. */ @@ -563,10 +626,10 @@ static int sctp_inetaddr_event(struct no { unsigned long flags; - sctp_spin_lock_irqsave(&sctp_proto.local_addr_lock, flags); - __sctp_free_local_addr_list(&sctp_proto); - __sctp_get_local_addr_list(&sctp_proto); - sctp_spin_unlock_irqrestore(&sctp_proto.local_addr_lock, flags); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + __sctp_free_local_addr_list(); + __sctp_get_local_addr_list(); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); return NOTIFY_DONE; } @@ -592,7 +655,7 @@ int sctp_ctl_sock_init(void) "SCTP: Failed to create the SCTP control socket.\n"); return err; } - sctp_ctl_socket->sk->allocation = GFP_ATOMIC; + sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC; inet_sk(sctp_ctl_socket->sk)->ttl = MAXTTL; return 0; @@ -617,7 +680,7 @@ int sctp_register_af(struct sctp_af *af) } INIT_LIST_HEAD(&af->list); - list_add_tail(&af->list, &sctp_proto.address_families); + list_add_tail(&af->list, &sctp_address_families); return 1; } @@ -654,10 +717,13 @@ static void sctp_inet_event_msgname(stru struct sockaddr_in *sin, *sinfrom; if (msgname) { + struct sctp_association *asoc; + + asoc = event->sndrcvinfo.sinfo_assoc_id; sctp_inet_msgname(msgname, addr_len); sin = (struct sockaddr_in *)msgname; - sinfrom = &event->event_asoc->peer.primary_addr.v4; - sin->sin_port = htons(event->event_asoc->peer.port); + sinfrom = &asoc->peer.primary_addr.v4; + sin->sin_port = htons(asoc->peer.port); sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr; } } @@ -678,7 +744,7 @@ static void sctp_inet_skb_msgname(struct } /* Do we support this AF? */ -static int sctp_inet_af_supported(sa_family_t family) +static int sctp_inet_af_supported(sa_family_t family, struct sctp_opt *sp) { /* PF_INET only supports AF_INET addresses. */ return (AF_INET == family); @@ -706,7 +772,7 @@ static int sctp_inet_cmp_addr(const unio */ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) { - return sctp_v4_available(addr); + return sctp_v4_available(addr, opt); } /* Verify that sockaddr looks sendable. Common verification has already @@ -752,6 +818,7 @@ static struct sctp_pf sctp_pf_inet = { .send_verify = sctp_inet_send_verify, .supported_addrs = sctp_inet_supported_addrs, .create_accept_sk = sctp_v4_create_accept_sk, + .addr_v4map = sctp_v4_addr_v4map, .af = &sctp_ipv4_specific, }; @@ -821,6 +888,8 @@ struct sctp_af sctp_ipv4_specific = { .from_sk = sctp_v4_from_sk, .to_sk_saddr = sctp_v4_to_sk_saddr, .to_sk_daddr = sctp_v4_to_sk_daddr, + .from_addr_param= sctp_v4_from_addr_param, + .to_addr_param = sctp_v4_to_addr_param, .dst_saddr = sctp_v4_dst_saddr, .cmp_addr = sctp_v4_cmp_addr, .addr_valid = sctp_v4_addr_valid, @@ -829,6 +898,8 @@ struct sctp_af sctp_ipv4_specific = { .available = sctp_v4_available, .scope = sctp_v4_scope, .skb_iif = sctp_v4_skb_iif, + .is_ce = sctp_v4_is_ce, + .seq_dump_addr = sctp_v4_seq_dump_addr, .net_header_len = sizeof(struct iphdr), .sockaddr_len = sizeof(struct sockaddr_in), .sa_family = AF_INET, @@ -873,6 +944,7 @@ static int __init init_sctp_mibs(void) static void cleanup_sctp_mibs(void) { + return; } /* Initialize the universe into something sensible. */ @@ -880,6 +952,8 @@ __init int sctp_init(void) { int i; int status = 0; + unsigned long goal; + int order; /* SCTP_DEBUG sanity check. */ if (!sctp_sanity_check()) @@ -892,6 +966,14 @@ __init int sctp_init(void) inet_register_protosw(&sctp_seqpacket_protosw); inet_register_protosw(&sctp_stream_protosw); + /* Allocate cache pools. */ + sctp_chunk_cachep = kmem_cache_create("sctp_chunk", + sizeof(struct sctp_chunk), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!sctp_chunk_cachep) + goto err_chunk_cachep; + /* Allocate and initialise sctp mibs. */ status = init_sctp_mibs(); if (status) @@ -910,91 +992,116 @@ __init int sctp_init(void) */ /* The following protocol parameters are RECOMMENDED: */ /* RTO.Initial - 3 seconds */ - sctp_proto.rto_initial = SCTP_RTO_INITIAL; + sctp_rto_initial = SCTP_RTO_INITIAL; /* RTO.Min - 1 second */ - sctp_proto.rto_min = SCTP_RTO_MIN; + sctp_rto_min = SCTP_RTO_MIN; /* RTO.Max - 60 seconds */ - sctp_proto.rto_max = SCTP_RTO_MAX; + sctp_rto_max = SCTP_RTO_MAX; /* RTO.Alpha - 1/8 */ - sctp_proto.rto_alpha = SCTP_RTO_ALPHA; + sctp_rto_alpha = SCTP_RTO_ALPHA; /* RTO.Beta - 1/4 */ - sctp_proto.rto_beta = SCTP_RTO_BETA; - + sctp_rto_beta = SCTP_RTO_BETA; /* Valid.Cookie.Life - 60 seconds */ - sctp_proto.valid_cookie_life = 60 * HZ; + sctp_valid_cookie_life = 60 * HZ; /* Whether Cookie Preservative is enabled(1) or not(0) */ - sctp_proto.cookie_preserve_enable = 1; + sctp_cookie_preserve_enable = 1; /* Max.Burst - 4 */ - sctp_proto.max_burst = SCTP_MAX_BURST; + sctp_max_burst = SCTP_MAX_BURST; /* Association.Max.Retrans - 10 attempts * Path.Max.Retrans - 5 attempts (per destination address) * Max.Init.Retransmits - 8 attempts */ - sctp_proto.max_retrans_association = 10; - sctp_proto.max_retrans_path = 5; - sctp_proto.max_retrans_init = 8; + sctp_max_retrans_association = 10; + sctp_max_retrans_path = 5; + sctp_max_retrans_init = 8; /* HB.interval - 30 seconds */ - sctp_proto.hb_interval = 30 * HZ; + sctp_hb_interval = 30 * HZ; /* Implementation specific variables. */ /* Initialize default stream count setup information. */ - sctp_proto.max_instreams = SCTP_DEFAULT_INSTREAMS; - sctp_proto.max_outstreams = SCTP_DEFAULT_OUTSTREAMS; + sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; + sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; - /* Allocate and initialize the association hash table. */ - sctp_proto.assoc_hashsize = 4096; - sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *) - kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL); - if (!sctp_proto.assoc_hashbucket) { + /* Size and allocate the association hash table. + * The methodology is similar to that of the tcp hash tables. + */ + if (num_physpages >= (128 * 1024)) + goal = num_physpages >> (22 - PAGE_SHIFT); + else + goal = num_physpages >> (24 - PAGE_SHIFT); + + for (order = 0; (1UL << order) < goal; order++) + ; + + do { + sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE / + sizeof(struct sctp_hashbucket); + if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0) + continue; + sctp_assoc_hashtable = (struct sctp_hashbucket *) + __get_free_pages(GFP_ATOMIC, order); + } while (!sctp_assoc_hashtable && --order > 0); + if (!sctp_assoc_hashtable) { printk(KERN_ERR "SCTP: Failed association hash alloc.\n"); status = -ENOMEM; goto err_ahash_alloc; } - for (i = 0; i < sctp_proto.assoc_hashsize; i++) { - sctp_proto.assoc_hashbucket[i].lock = RW_LOCK_UNLOCKED; - sctp_proto.assoc_hashbucket[i].chain = NULL; + for (i = 0; i < sctp_assoc_hashsize; i++) { + sctp_assoc_hashtable[i].lock = RW_LOCK_UNLOCKED; + sctp_assoc_hashtable[i].chain = NULL; } /* Allocate and initialize the endpoint hash table. */ - sctp_proto.ep_hashsize = 64; - sctp_proto.ep_hashbucket = (sctp_hashbucket_t *) - kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL); - if (!sctp_proto.ep_hashbucket) { + sctp_ep_hashsize = 64; + sctp_ep_hashtable = (struct sctp_hashbucket *) + kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL); + if (!sctp_ep_hashtable) { printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); status = -ENOMEM; goto err_ehash_alloc; } - - for (i = 0; i < sctp_proto.ep_hashsize; i++) { - sctp_proto.ep_hashbucket[i].lock = RW_LOCK_UNLOCKED; - sctp_proto.ep_hashbucket[i].chain = NULL; + for (i = 0; i < sctp_ep_hashsize; i++) { + sctp_ep_hashtable[i].lock = RW_LOCK_UNLOCKED; + sctp_ep_hashtable[i].chain = NULL; } /* Allocate and initialize the SCTP port hash table. */ - sctp_proto.port_hashsize = 4096; - sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *) - kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL); - if (!sctp_proto.port_hashtable) { + do { + sctp_port_hashsize = (1UL << order) * PAGE_SIZE / + sizeof(struct sctp_bind_hashbucket); + if ((sctp_port_hashsize > (64 * 1024)) && order > 0) + continue; + sctp_port_hashtable = (struct sctp_bind_hashbucket *) + __get_free_pages(GFP_ATOMIC, order); + } while (!sctp_port_hashtable && --order > 0); + if (!sctp_port_hashtable) { printk(KERN_ERR "SCTP: Failed bind hash alloc."); status = -ENOMEM; goto err_bhash_alloc; } - - sctp_proto.port_alloc_lock = SPIN_LOCK_UNLOCKED; - sctp_proto.port_rover = sysctl_local_port_range[0] - 1; - for (i = 0; i < sctp_proto.port_hashsize; i++) { - sctp_proto.port_hashtable[i].lock = SPIN_LOCK_UNLOCKED; - sctp_proto.port_hashtable[i].chain = NULL; + for (i = 0; i < sctp_port_hashsize; i++) { + sctp_port_hashtable[i].lock = SPIN_LOCK_UNLOCKED; + sctp_port_hashtable[i].chain = NULL; } + sctp_port_alloc_lock = SPIN_LOCK_UNLOCKED; + sctp_port_rover = sysctl_local_port_range[0] - 1; + + printk(KERN_INFO "SCTP: Hash tables configured " + "(established %d bind %d)\n", + sctp_assoc_hashsize, sctp_port_hashsize); + + /* Disable ADDIP by default. */ + sctp_addip_enable = 0; + sctp_sysctl_register(); - INIT_LIST_HEAD(&sctp_proto.address_families); + INIT_LIST_HEAD(&sctp_address_families); sctp_register_af(&sctp_ipv4_specific); status = sctp_v6_init(); @@ -1009,13 +1116,13 @@ __init int sctp_init(void) } /* Initialize the local address list. */ - INIT_LIST_HEAD(&sctp_proto.local_addr_list); - sctp_proto.local_addr_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&sctp_local_addr_list); + sctp_local_addr_lock = SPIN_LOCK_UNLOCKED; /* Register notifier for inet address additions/deletions. */ register_inetaddr_notifier(&sctp_inetaddr_notifier); - sctp_get_local_addr_list(&sctp_proto); + sctp_get_local_addr_list(); __unsafe(THIS_MODULE); return 0; @@ -1025,16 +1132,22 @@ err_ctl_sock_init: err_v6_init: sctp_sysctl_unregister(); list_del(&sctp_ipv4_specific.list); - kfree(sctp_proto.port_hashtable); + free_pages((unsigned long)sctp_port_hashtable, + get_order(sctp_port_hashsize * + sizeof(struct sctp_bind_hashbucket))); err_bhash_alloc: - kfree(sctp_proto.ep_hashbucket); + kfree(sctp_ep_hashtable); err_ehash_alloc: - kfree(sctp_proto.assoc_hashbucket); + free_pages((unsigned long)sctp_assoc_hashtable, + get_order(sctp_assoc_hashsize * + sizeof(struct sctp_hashbucket))); err_ahash_alloc: sctp_dbg_objcnt_exit(); sctp_proc_exit(); cleanup_sctp_mibs(); err_init_mibs: + kmem_cache_destroy(sctp_chunk_cachep); +err_chunk_cachep: inet_del_protocol(&sctp_protocol); inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_stream_protosw); @@ -1052,7 +1165,7 @@ __exit void sctp_exit(void) unregister_inetaddr_notifier(&sctp_inetaddr_notifier); /* Free the local address list. */ - sctp_free_local_addr_list(&sctp_proto); + sctp_free_local_addr_list(); /* Free the control endpoint. */ sock_release(sctp_ctl_socket); @@ -1061,9 +1174,15 @@ __exit void sctp_exit(void) sctp_sysctl_unregister(); list_del(&sctp_ipv4_specific.list); - kfree(sctp_proto.assoc_hashbucket); - kfree(sctp_proto.ep_hashbucket); - kfree(sctp_proto.port_hashtable); + free_pages((unsigned long)sctp_assoc_hashtable, + get_order(sctp_assoc_hashsize * + sizeof(struct sctp_hashbucket))); + kfree(sctp_ep_hashtable); + free_pages((unsigned long)sctp_port_hashtable, + get_order(sctp_port_hashsize * + sizeof(struct sctp_bind_hashbucket))); + + kmem_cache_destroy(sctp_chunk_cachep); sctp_dbg_objcnt_exit(); sctp_proc_exit(); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_make_chunk.c linux-2.4.26-pre1/net/sctp/sm_make_chunk.c --- linux-2.4.25/net/sctp/sm_make_chunk.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/sm_make_chunk.c 2004-02-25 15:40:49.000000000 +0000 @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -48,6 +48,7 @@ * Sridhar Samudrala * Daisy Chang * Ardelle Fan + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -60,6 +61,7 @@ #include #include #include +#include #include #include @@ -67,6 +69,8 @@ #include #include +extern kmem_cache_t *sctp_chunk_cachep; + /* What was the inbound interface for this chunk? */ int sctp_chunk_iif(const struct sctp_chunk *chunk) { @@ -96,7 +100,7 @@ static const sctp_ecn_capable_param_t ec * provided chunk, as most cause codes will be embedded inside an * abort chunk. */ -void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code, +void sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code, const void *payload, size_t paylen) { sctp_errhdr_t err; @@ -157,14 +161,14 @@ void sctp_init_cause(sctp_chunk_t *chun * Host Name Address (Note 3) Optional 11 * Supported Address Types (Note 4) Optional 12 */ -sctp_chunk_t *sctp_make_init(const struct sctp_association *asoc, - const sctp_bind_addr_t *bp, +struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, + const struct sctp_bind_addr *bp, int gfp, int vparam_len) { sctp_inithdr_t init; union sctp_params addrs; size_t chunksize; - sctp_chunk_t *retval = NULL; + struct sctp_chunk *retval = NULL; int num_types, addrs_len = 0; struct sctp_opt *sp; sctp_supported_addrs_param_t sat; @@ -234,12 +238,12 @@ nodata: return retval; } -sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, +struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, + const struct sctp_chunk *chunk, int gfp, int unkparam_len) { sctp_inithdr_t initack; - sctp_chunk_t *retval; + struct sctp_chunk *retval; union sctp_params addrs; int addrs_len; sctp_cookie_param_t *cookie; @@ -347,10 +351,10 @@ nomem_cookie: * An implementation SHOULD make the cookie as small as possible * to insure interoperability. */ -sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *asoc, - const sctp_chunk_t *chunk) +struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *asoc, + const struct sctp_chunk *chunk) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; void *cookie; int cookie_len; @@ -398,10 +402,10 @@ nodata: * * Set to zero on transmit and ignored on receipt. */ -sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *asoc, - const sctp_chunk_t *chunk) +struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc, + const struct sctp_chunk *chunk) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ACK, 0, 0); @@ -443,11 +447,11 @@ sctp_chunk_t *sctp_make_cookie_ack(const * * Note: The CWR is considered a Control chunk. */ -sctp_chunk_t *sctp_make_cwr(const struct sctp_association *asoc, +struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc, const __u32 lowest_tsn, - const sctp_chunk_t *chunk) + const struct sctp_chunk *chunk) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; sctp_cwrhdr_t cwr; cwr.lowest_tsn = htonl(lowest_tsn); @@ -478,10 +482,10 @@ nodata: } /* Make an ECNE chunk. This is a congestion experienced report. */ -sctp_chunk_t *sctp_make_ecne(const struct sctp_association *asoc, +struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc, const __u32 lowest_tsn) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; sctp_ecnehdr_t ecne; ecne.lowest_tsn = htonl(lowest_tsn); @@ -499,25 +503,27 @@ nodata: /* Make a DATA chunk for the given association from the provided * parameters. However, do not populate the data payload. */ -sctp_chunk_t *sctp_make_datafrag_empty(struct sctp_association *asoc, +struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc, const struct sctp_sndrcvinfo *sinfo, int data_len, __u8 flags, __u16 ssn) { - sctp_chunk_t *retval; - sctp_datahdr_t dp; + struct sctp_chunk *retval; + struct sctp_datahdr dp; int chunk_len; /* We assign the TSN as LATE as possible, not here when * creating the chunk. */ - dp.tsn= 1000000; /* This marker is a debugging aid. */ + dp.tsn = 0; dp.stream = htons(sinfo->sinfo_stream); dp.ppid = htonl(sinfo->sinfo_ppid); - dp.ssn = htons(ssn); /* Set the flags for an unordered send. */ - if (sinfo->sinfo_flags & MSG_UNORDERED) + if (sinfo->sinfo_flags & MSG_UNORDERED) { flags |= SCTP_DATA_UNORDERED; + dp.ssn = 0; + } else + dp.ssn = htons(ssn); chunk_len = sizeof(dp) + data_len; retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len); @@ -534,12 +540,12 @@ nodata: /* Make a DATA chunk for the given association. Populate the data * payload. */ -sctp_chunk_t *sctp_make_datafrag(struct sctp_association *asoc, +struct sctp_chunk *sctp_make_datafrag(struct sctp_association *asoc, const struct sctp_sndrcvinfo *sinfo, int data_len, const __u8 *data, __u8 flags, __u16 ssn) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; retval = sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, ssn); if (retval) @@ -551,11 +557,11 @@ sctp_chunk_t *sctp_make_datafrag(struct /* Make a DATA chunk for the given association to ride on stream id * 'stream', with a payload id of 'payload', and a body of 'data'. */ -sctp_chunk_t *sctp_make_data(struct sctp_association *asoc, +struct sctp_chunk *sctp_make_data(struct sctp_association *asoc, const struct sctp_sndrcvinfo *sinfo, int data_len, const __u8 *data) { - sctp_chunk_t *retval = NULL; + struct sctp_chunk *retval = NULL; retval = sctp_make_data_empty(asoc, sinfo, data_len); if (retval) @@ -568,7 +574,7 @@ sctp_chunk_t *sctp_make_data(struct sctp * hold 'data_len' octets of data. We use this version when we need * to build the message AFTER allocating memory. */ -sctp_chunk_t *sctp_make_data_empty(struct sctp_association *asoc, +struct sctp_chunk *sctp_make_data_empty(struct sctp_association *asoc, const struct sctp_sndrcvinfo *sinfo, int data_len) { @@ -581,30 +587,20 @@ sctp_chunk_t *sctp_make_data_empty(struc * association. This reports on which TSN's we've seen to date, * including duplicates and gaps. */ -sctp_chunk_t *sctp_make_sack(const struct sctp_association *asoc) +struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) { - sctp_chunk_t *retval; - sctp_sackhdr_t sack; - sctp_gap_ack_block_t gab; - int length; + struct sctp_chunk *retval; + struct sctp_sackhdr sack; + int len; __u32 ctsn; - struct sctp_tsnmap_iter iter; __u16 num_gabs, num_dup_tsns; struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; ctsn = sctp_tsnmap_get_ctsn(map); - SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn); - - /* Count the number of Gap Ack Blocks. */ - num_gabs = 0; - - if (sctp_tsnmap_has_gap(map)) { - sctp_tsnmap_iter_init(map, &iter); - while (sctp_tsnmap_next_gap_ack(map, &iter, - &gab.start, &gab.end)) - num_gabs++; - } + SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn); + /* How much room is needed in the chunk? */ + num_gabs = sctp_tsnmap_num_gabs(map); num_dup_tsns = sctp_tsnmap_num_dups(map); /* Initialize the SACK header. */ @@ -613,12 +609,12 @@ sctp_chunk_t *sctp_make_sack(const struc sack.num_gap_ack_blocks = htons(num_gabs); sack.num_dup_tsns = htons(num_dup_tsns); - length = sizeof(sack) - + sizeof(sctp_gap_ack_block_t) * num_gabs + len = sizeof(sack) + + sizeof(struct sctp_gap_ack_block) * num_gabs + sizeof(__u32) * num_dup_tsns; /* Create the chunk. */ - retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, length); + retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len); if (!retval) goto nodata; @@ -657,30 +653,25 @@ sctp_chunk_t *sctp_make_sack(const struc retval->subh.sack_hdr = sctp_addto_chunk(retval, sizeof(sack), &sack); - /* Put the Gap Ack Blocks into the chunk. */ - if (num_gabs) { - sctp_tsnmap_iter_init(map, &iter); - while(sctp_tsnmap_next_gap_ack(map, &iter, - &gab.start, &gab.end)) { - gab.start = htons(gab.start); - gab.end = htons(gab.end); - sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t), - &gab); - } - } - - /* Register the duplicates. */ - sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns, - sctp_tsnmap_get_dups(map)); + /* Add the gap ack block information. */ + if (num_gabs) + sctp_addto_chunk(retval, sizeof(__u32) * num_gabs, + sctp_tsnmap_get_gabs(map)); + + /* Add the duplicate TSN information. */ + if (num_dup_tsns) + sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns, + sctp_tsnmap_get_dups(map)); nodata: return retval; } /* Make a SHUTDOWN chunk. */ -sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc) +struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc, + const struct sctp_chunk *chunk) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; sctp_shutdownhdr_t shut; __u32 ctsn; @@ -694,14 +685,17 @@ sctp_chunk_t *sctp_make_shutdown(const s retval->subh.shutdown_hdr = sctp_addto_chunk(retval, sizeof(shut), &shut); + + if (chunk) + retval->transport = chunk->transport; nodata: return retval; } -sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc, - const sctp_chunk_t *chunk) +struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc, + const struct sctp_chunk *chunk) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0); @@ -720,10 +714,11 @@ sctp_chunk_t *sctp_make_shutdown_ack(con return retval; } -sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *asoc, - const sctp_chunk_t *chunk) +struct sctp_chunk *sctp_make_shutdown_complete( + const struct sctp_association *asoc, + const struct sctp_chunk *chunk) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; __u8 flags = 0; /* Maybe set the T-bit if we have no association. */ @@ -750,11 +745,11 @@ sctp_chunk_t *sctp_make_shutdown_complet /* Create an ABORT. Note that we set the T bit if we have no * association. */ -sctp_chunk_t *sctp_make_abort(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, +struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc, + const struct sctp_chunk *chunk, const size_t hint) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; __u8 flags = 0; /* Maybe set the T-bit if we have no association. */ @@ -778,10 +773,11 @@ sctp_chunk_t *sctp_make_abort(const stru } /* Helper to create ABORT with a NO_USER_DATA error. */ -sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, __u32 tsn) +struct sctp_chunk *sctp_make_abort_no_data( + const struct sctp_association *asoc, + const struct sctp_chunk *chunk, __u32 tsn) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; __u32 payload; retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) @@ -812,17 +808,22 @@ no_mem: } /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ -sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, +struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, + const struct sctp_chunk *chunk, const struct msghdr *msg) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; void *payload = NULL, *payoff; - size_t paylen; - struct iovec *iov = msg->msg_iov; - int iovlen = msg->msg_iovlen; + size_t paylen = 0; + struct iovec *iov = NULL; + int iovlen = 0; + + if (msg) { + iov = msg->msg_iov; + iovlen = msg->msg_iovlen; + paylen = get_user_iov_size(iov, iovlen); + } - paylen = get_user_iov_size(iov, iovlen); retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen); if (!retval) goto err_chunk; @@ -852,19 +853,19 @@ sctp_chunk_t *sctp_make_abort_user(const err_copy: kfree(payload); err_payload: - sctp_free_chunk(retval); + sctp_chunk_free(retval); retval = NULL; err_chunk: return retval; } /* Make a HEARTBEAT chunk. */ -sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *asoc, +struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, const struct sctp_transport *transport, const void *payload, const size_t paylen) { - sctp_chunk_t *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, - 0, paylen); + struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, + 0, paylen); if (!retval) goto nodata; @@ -879,15 +880,16 @@ nodata: return retval; } -sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, +struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *asoc, + const struct sctp_chunk *chunk, const void *payload, const size_t paylen) { - sctp_chunk_t *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK, - 0, paylen); + struct sctp_chunk *retval; + retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK, 0, paylen); if (!retval) goto nodata; + retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload); /* RFC 2960 6.4 Multi-homed SCTP Endpoints @@ -909,11 +911,12 @@ nodata: /* Create an Operation Error chunk with the specified space reserved. * This routine can be used for containing multiple causes in the chunk. */ -sctp_chunk_t *sctp_make_op_error_space(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, - size_t size) +struct sctp_chunk *sctp_make_op_error_space( + const struct sctp_association *asoc, + const struct sctp_chunk *chunk, + size_t size) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; retval = sctp_make_chunk(asoc, SCTP_CID_ERROR, 0, sizeof(sctp_errhdr_t) + size); @@ -936,13 +939,14 @@ nodata: } /* Create an Operation Error chunk. */ -sctp_chunk_t *sctp_make_op_error(const struct sctp_association *asoc, - const sctp_chunk_t *chunk, +struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, + const struct sctp_chunk *chunk, __u16 cause_code, const void *payload, size_t paylen) { - sctp_chunk_t *retval = sctp_make_op_error_space(asoc, chunk, paylen); + struct sctp_chunk *retval; + retval = sctp_make_op_error_space(asoc, chunk, paylen); if (!retval) goto nodata; @@ -959,15 +963,17 @@ nodata: /* Turn an skb into a chunk. * FIXME: Eventually move the structure directly inside the skb->cb[]. */ -sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, +struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, const struct sctp_association *asoc, struct sock *sk) { - sctp_chunk_t *retval = t_new(sctp_chunk_t, GFP_ATOMIC); + struct sctp_chunk *retval; + + retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC); if (!retval) goto nodata; - memset(retval, 0, sizeof(sctp_chunk_t)); + memset(retval, 0, sizeof(struct sctp_chunk)); if (!sk) { SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb); @@ -975,11 +981,11 @@ sctp_chunk_t *sctp_chunkify(struct sk_bu retval->skb = skb; retval->asoc = (struct sctp_association *)asoc; - retval->num_times_sent = 0; + retval->resent = 0; retval->has_tsn = 0; retval->has_ssn = 0; retval->rtt_in_progress = 0; - retval->sent_at = jiffies; + retval->sent_at = 0; retval->singleton = 1; retval->end_of_packet = 0; retval->ecn_ce_done = 0; @@ -995,17 +1001,24 @@ sctp_chunk_t *sctp_chunkify(struct sk_bu retval->tsn_gap_acked = 0; retval->fast_retransmit = 0; + /* If this is a fragmented message, track all fragments + * of the message (for SEND_FAILED). + */ + retval->msg = NULL; + /* Polish the bead hole. */ INIT_LIST_HEAD(&retval->transmitted_list); INIT_LIST_HEAD(&retval->frag_list); SCTP_DBG_OBJCNT_INC(chunk); + atomic_set(&retval->refcnt, 1); + nodata: return retval; } /* Set chunk->source and dest based on the IP header in chunk->skb. */ -void sctp_init_addrs(sctp_chunk_t *chunk, union sctp_addr *src, +void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src, union sctp_addr *dest) { memcpy(&chunk->source, src, sizeof(union sctp_addr)); @@ -1013,7 +1026,7 @@ void sctp_init_addrs(sctp_chunk_t *chunk } /* Extract the source address from a chunk. */ -const union sctp_addr *sctp_source(const sctp_chunk_t *chunk) +const union sctp_addr *sctp_source(const struct sctp_chunk *chunk) { /* If we have a known transport, use that. */ if (chunk->transport) { @@ -1027,10 +1040,10 @@ const union sctp_addr *sctp_source(const /* Create a new chunk, setting the type and flags headers from the * arguments, reserving enough space for a 'paylen' byte payload. */ -sctp_chunk_t *sctp_make_chunk(const struct sctp_association *asoc, - __u8 type, __u8 flags, int paylen) +struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, + __u8 type, __u8 flags, int paylen) { - sctp_chunk_t *retval; + struct sctp_chunk *retval; sctp_chunkhdr_t *chunk_hdr; struct sk_buff *skb; struct sock *sk; @@ -1055,36 +1068,58 @@ sctp_chunk_t *sctp_make_chunk(const stru } retval->chunk_hdr = chunk_hdr; - retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(sctp_chunkhdr_t); + retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr); /* Set the skb to the belonging sock for accounting. */ skb->sk = sk; return retval; - nodata: return NULL; } + /* Release the memory occupied by a chunk. */ -void sctp_free_chunk(sctp_chunk_t *chunk) +static void sctp_chunk_destroy(struct sctp_chunk *chunk) { - /* Make sure that we are not on any list. */ - skb_unlink((struct sk_buff *) chunk); - list_del(&chunk->transmitted_list); - /* Free the chunk skb data and the SCTP_chunk stub itself. */ dev_kfree_skb(chunk->skb); - kfree(chunk); SCTP_DBG_OBJCNT_DEC(chunk); + kmem_cache_free(sctp_chunk_cachep, chunk); +} + +/* Possibly, free the chunk. */ +void sctp_chunk_free(struct sctp_chunk *chunk) +{ + /* Make sure that we are not on any list. */ + skb_unlink((struct sk_buff *) chunk); + list_del_init(&chunk->transmitted_list); + + /* Release our reference on the message tracker. */ + if (chunk->msg) + sctp_datamsg_put(chunk->msg); + + sctp_chunk_put(chunk); +} + +/* Grab a reference to the chunk. */ +void sctp_chunk_hold(struct sctp_chunk *ch) +{ + atomic_inc(&ch->refcnt); } +/* Release a reference to the chunk. */ +void sctp_chunk_put(struct sctp_chunk *ch) +{ + if (atomic_dec_and_test(&ch->refcnt)) + sctp_chunk_destroy(ch); +} /* Append bytes to the end of a chunk. Will panic if chunk is not big * enough. */ -void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data) +void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) { void *target; void *padding; @@ -1108,8 +1143,8 @@ void *sctp_addto_chunk(sctp_chunk_t *chu * chunk is not big enough. * Returns a kernel err value. */ -static int sctp_user_addto_chunk(sctp_chunk_t *chunk, int off, int len, - struct iovec *data) +int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len, + struct iovec *data) { __u8 *target; int err = 0; @@ -1130,132 +1165,10 @@ out: return err; } -/* A data chunk can have a maximum payload of (2^16 - 20). Break - * down any such message into smaller chunks. Opportunistically, fragment - * the chunks down to the current MTU constraints. We may get refragmented - * later if the PMTU changes, but it is _much better_ to fragment immediately - * with a reasonable guess than always doing our fragmentation on the - * soft-interrupt. - */ - - -int sctp_datachunks_from_user(struct sctp_association *asoc, - const struct sctp_sndrcvinfo *sinfo, - struct msghdr *msg, int msg_len, - struct sk_buff_head *chunks) -{ - int max, whole, i, offset, over, err; - int len, first_len; - sctp_chunk_t *chunk; - __u8 frag; - - /* What is a reasonable fragmentation point right now? */ - max = asoc->pmtu; - if (max < SCTP_MIN_PMTU) - max = SCTP_MIN_PMTU; - max -= SCTP_IP_OVERHEAD; - - /* Make sure not beyond maximum chunk size. */ - if (max > SCTP_MAX_CHUNK_LEN) - max = SCTP_MAX_CHUNK_LEN; - - /* Subtract out the overhead of a data chunk header. */ - max -= sizeof(struct sctp_data_chunk); - - whole = 0; - first_len = max; - - /* Encourage Cookie-ECHO bundling. */ - if (asoc->state < SCTP_STATE_COOKIE_ECHOED) { - whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN); - - /* Account for the DATA to be bundled with the COOKIE-ECHO. */ - if (whole) { - first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN; - msg_len -= first_len; - whole = 1; - } - } - - /* How many full sized? How many bytes leftover? */ - whole += msg_len / max; - over = msg_len % max; - offset = 0; - - if (whole && over) - SCTP_INC_STATS_USER(SctpFragUsrMsgs); - - /* Create chunks for all the full sized DATA chunks. */ - for (i=0, len=first_len; i < whole; i++) { - frag = SCTP_DATA_MIDDLE_FRAG; - - if (0 == i) - frag |= SCTP_DATA_FIRST_FRAG; - - if ((i == (whole - 1)) && !over) - frag |= SCTP_DATA_LAST_FRAG; - - chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); - - if (!chunk) - goto nomem; - err = sctp_user_addto_chunk(chunk, offset, len, msg->msg_iov); - if (err < 0) - goto errout; - - offset += len; - - /* Put the chunk->skb back into the form expected by send. */ - __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr - - (__u8 *)chunk->skb->data); - - __skb_queue_tail(chunks, (struct sk_buff *)chunk); - - /* The first chunk, the first chunk was likely short - * to allow bundling, so reset to full size. - */ - if (0 == i) - len = max; - } - - /* .. now the leftover bytes. */ - if (over) { - if (!whole) - frag = SCTP_DATA_NOT_FRAG; - else - frag = SCTP_DATA_LAST_FRAG; - - chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); - - if (!chunk) - goto nomem; - - err = sctp_user_addto_chunk(chunk, offset, over, msg->msg_iov); - - /* Put the chunk->skb back into the form expected by send. */ - __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr - - (__u8 *)chunk->skb->data); - if (err < 0) - goto errout; - - __skb_queue_tail(chunks, (struct sk_buff *)chunk); - } - err = 0; - goto out; - -nomem: - err = -ENOMEM; -errout: - while ((chunk = (sctp_chunk_t *)__skb_dequeue(chunks))) - sctp_free_chunk(chunk); -out: - return err; -} - /* Helper function to assign a TSN if needed. This assumes that both * the data_hdr and association have already been assigned. */ -void sctp_chunk_assign_ssn(sctp_chunk_t *chunk) +void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) { __u16 ssn; __u16 sid; @@ -1282,7 +1195,7 @@ void sctp_chunk_assign_ssn(sctp_chunk_t /* Helper function to assign a TSN if needed. This assumes that both * the data_hdr and association have already been assigned. */ -void sctp_chunk_assign_tsn(sctp_chunk_t *chunk) +void sctp_chunk_assign_tsn(struct sctp_chunk *chunk) { if (!chunk->has_tsn) { /* This is the last possible instant to @@ -1301,6 +1214,7 @@ struct sctp_association *sctp_make_temp_ struct sctp_association *asoc; struct sk_buff *skb; sctp_scope_t scope; + struct sctp_af *af; /* Create the bare association. */ scope = sctp_scope(sctp_source(chunk)); @@ -1310,29 +1224,10 @@ struct sctp_association *sctp_make_temp_ asoc->temp = 1; skb = chunk->skb; /* Create an entry for the source address of the packet. */ - /* FIXME: Use the af specific helpers. */ - switch (skb->nh.iph->version) { - case 4: - asoc->c.peer_addr.v4.sin_family = AF_INET; - asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v4.sin_addr.s_addr = skb->nh.iph->saddr; - break; - - case 6: - asoc->c.peer_addr.v6.sin6_family = AF_INET6; - asoc->c.peer_addr.v6.sin6_port - = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */ - asoc->c.peer_addr.v6.sin6_addr = skb->nh.ipv6h->saddr; - asoc->c.peer_addr.v6.sin6_scope_id = - ((struct inet6_skb_parm *)skb->cb)->iif; - break; - - default: - /* Yikes! I never heard of this kind of address. */ + af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); + if (unlikely(!af)) goto fail; - }; - + af->from_skb(&asoc->c.peer_addr, skb, 1); nodata: return asoc; @@ -1346,19 +1241,19 @@ fail: */ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, const struct sctp_association *asoc, - const sctp_chunk_t *init_chunk, + const struct sctp_chunk *init_chunk, int *cookie_len, const __u8 *raw_addrs, int addrs_len) { sctp_cookie_param_t *retval; - sctp_signed_cookie_t *cookie; + struct sctp_signed_cookie *cookie; struct scatterlist sg; int headersize, bodysize; unsigned int keylen; char *key; headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE; - bodysize = sizeof(sctp_cookie_t) + bodysize = sizeof(struct sctp_cookie) + ntohs(init_chunk->chunk_hdr->length) + addrs_len; /* Pad out the cookie to a multiple to make the signature @@ -1380,7 +1275,7 @@ sctp_cookie_param_t *sctp_pack_cookie(co * out on the network. */ memset(retval, 0x00, *cookie_len); - cookie = (sctp_signed_cookie_t *) retval->body; + cookie = (struct sctp_signed_cookie *) retval->body; /* Set up the parameter header. */ retval->p.type = SCTP_PARAM_STATE_COOKIE; @@ -1388,22 +1283,21 @@ sctp_cookie_param_t *sctp_pack_cookie(co /* Copy the cookie part of the association itself. */ cookie->c = asoc->c; - /* Save the raw address list length in the cookie. */ cookie->c.raw_addr_list_len = addrs_len; /* Set an expiration time for the cookie. */ do_gettimeofday(&cookie->c.expiration); - tv_add(&asoc->cookie_life, &cookie->c.expiration); + TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration); /* Copy the peer's init packet. */ memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr, ntohs(init_chunk->chunk_hdr->length)); /* Copy the raw local address list of the association. */ - memcpy((__u8 *)&cookie->c.peer_init[0] + + memcpy((__u8 *)&cookie->c.peer_init[0] + ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len); - + if (sctp_sk(ep->base.sk)->hmac) { /* Sign the message. */ sg.page = virt_to_page(&cookie->c); @@ -1411,13 +1305,10 @@ sctp_cookie_param_t *sctp_pack_cookie(co sg.length = bodysize; keylen = SCTP_SECRET_SIZE; key = (char *)ep->secret_key[ep->current_key]; - - sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, + + sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1, cookie->signature); - } else - sctp_hash_digest(ep->secret_key[ep->current_key], - SCTP_SECRET_SIZE, (__u8 *) &cookie->c, - bodysize, cookie->signature); + } nodata: return retval; @@ -1427,31 +1318,30 @@ nodata: struct sctp_association *sctp_unpack_cookie( const struct sctp_endpoint *ep, const struct sctp_association *asoc, - sctp_chunk_t *chunk, int gfp, - int *error, sctp_chunk_t **errp) + struct sctp_chunk *chunk, int gfp, + int *error, struct sctp_chunk **errp) { struct sctp_association *retval = NULL; - sctp_signed_cookie_t *cookie; - sctp_cookie_t *bear_cookie; + struct sctp_signed_cookie *cookie; + struct sctp_cookie *bear_cookie; int headersize, bodysize, fixed_size; __u8 digest[SCTP_SIGNATURE_SIZE]; - int secret; struct scatterlist sg; - unsigned int keylen; + unsigned int keylen, len; char *key; sctp_scope_t scope; struct sk_buff *skb = chunk->skb; headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE; bodysize = ntohs(chunk->chunk_hdr->length) - headersize; - fixed_size = headersize + sizeof(sctp_cookie_t); + fixed_size = headersize + sizeof(struct sctp_cookie); /* Verify that the chunk looks like it even has a cookie. * There must be enough room for our cookie and our peer's * INIT chunk. */ - if (ntohs(chunk->chunk_hdr->length) < - (fixed_size + sizeof(sctp_chunkhdr_t))) + len = ntohs(chunk->chunk_hdr->length); + if (len < fixed_size + sizeof(struct sctp_chunkhdr)) goto malformed; /* Verify that the cookie has been padded out. */ @@ -1462,28 +1352,8 @@ struct sctp_association *sctp_unpack_coo cookie = chunk->subh.cookie_hdr; bear_cookie = &cookie->c; - if (!sctp_sk(ep->base.sk)->hmac) { - secret = ep->current_key; - sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE, - (__u8 *) bear_cookie, bodysize, digest); - - if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { - /* Try the previous key. */ - secret = ep->last_key; - sctp_hash_digest(ep->secret_key[secret], - SCTP_SECRET_SIZE, (__u8 *) bear_cookie, - bodysize, digest); - - if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { - /* Yikes! Still bad signature! */ - *error = -SCTP_IERROR_BAD_SIG; - goto fail; - } - - } - + if (!sctp_sk(ep->base.sk)->hmac) goto no_hmac; - } /* Check the signature. */ keylen = SCTP_SECRET_SIZE; @@ -1493,16 +1363,16 @@ struct sctp_association *sctp_unpack_coo key = (char *)ep->secret_key[ep->current_key]; memset(digest, 0x00, sizeof(digest)); - sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, + sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1, digest); if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { - /* Try the previous key. */ + /* Try the previous key. */ key = (char *)ep->secret_key[ep->last_key]; memset(digest, 0x00, sizeof(digest)); - sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, + sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1, digest); - + if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { /* Yikes! Still bad signature! */ *error = -SCTP_IERROR_BAD_SIG; @@ -1555,7 +1425,7 @@ no_hmac: retval->peer.port = ntohs(chunk->sctp_hdr->source); /* Populate the association from the cookie. */ - retval->c = *bear_cookie; + memcpy(&retval->c, bear_cookie, sizeof(*bear_cookie)); if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie, GFP_ATOMIC) < 0) { @@ -1565,12 +1435,13 @@ no_hmac: /* Also, add the destination address. */ if (list_empty(&retval->base.bind_addr.address_list)) { - sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, + sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, GFP_ATOMIC); } retval->next_tsn = retval->c.initial_tsn; retval->ctsn_ack_point = retval->next_tsn - 1; + retval->addip_serial = retval->c.initial_tsn; /* The INIT stuff will be done by the side effects. */ return retval; @@ -1603,8 +1474,8 @@ struct __sctp_missing { */ static int sctp_process_missing_param(const struct sctp_association *asoc, sctp_param_t paramtype, - sctp_chunk_t *chunk, - sctp_chunk_t **errp) + struct sctp_chunk *chunk, + struct sctp_chunk **errp) { struct __sctp_missing report; __u16 len; @@ -1630,8 +1501,8 @@ static int sctp_process_missing_param(co /* Report an Invalid Mandatory Parameter. */ static int sctp_process_inv_mandatory(const struct sctp_association *asoc, - sctp_chunk_t *chunk, - sctp_chunk_t **errp) + struct sctp_chunk *chunk, + struct sctp_chunk **errp) { /* Invalid Mandatory Parameter Error has no payload. */ @@ -1650,8 +1521,8 @@ static int sctp_process_inv_mandatory(co */ static int sctp_process_hn_param(const struct sctp_association *asoc, union sctp_params param, - sctp_chunk_t *chunk, - sctp_chunk_t **errp) + struct sctp_chunk *chunk, + struct sctp_chunk **errp) { __u16 len = ntohs(param.p->length); @@ -1695,8 +1566,8 @@ static int sctp_process_hn_param(const s */ static int sctp_process_unk_param(const struct sctp_association *asoc, union sctp_params param, - sctp_chunk_t *chunk, - sctp_chunk_t **errp) + struct sctp_chunk *chunk, + struct sctp_chunk **errp) { int retval = 1; @@ -1758,8 +1629,8 @@ static int sctp_process_unk_param(const static int sctp_verify_param(const struct sctp_association *asoc, union sctp_params param, sctp_cid_t cid, - sctp_chunk_t *chunk, - sctp_chunk_t **err_chunk) + struct sctp_chunk *chunk, + struct sctp_chunk **err_chunk) { int retval = 1; @@ -1796,8 +1667,8 @@ static int sctp_verify_param(const struc int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t cid, sctp_init_chunk_t *peer_init, - sctp_chunk_t *chunk, - sctp_chunk_t **errp) + struct sctp_chunk *chunk, + struct sctp_chunk **errp) { union sctp_params param; int has_cookie = 0; @@ -1831,8 +1702,12 @@ int sctp_verify_init(const struct sctp_a sctp_walk_params(param, peer_init, init_hdr.params) { - if (!sctp_verify_param(asoc, param, cid, chunk, errp)) - return 0; + if (!sctp_verify_param(asoc, param, cid, chunk, errp)) { + if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type) + return 0; + else + return 1; + } } /* for (loop through all parameters) */ @@ -1939,11 +1814,14 @@ int sctp_process_init(struct sctp_associ * stream sequence number shall be set to 0. */ - /* Allocate storage for the negotiated streams. */ - asoc->ssnmap = sctp_ssnmap_new(asoc->peer.i.num_outbound_streams, - asoc->c.sinit_num_ostreams, gfp); - if (!asoc->ssnmap) - goto nomem_ssnmap; + /* Allocate storage for the negotiated streams if it is not a temporary * association. + */ + if (!asoc->temp) { + asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, + asoc->c.sinit_num_ostreams, gfp); + if (!asoc->ssnmap) + goto nomem_ssnmap; + } /* ADDIP Section 4.1 ASCONF Chunk Procedures * @@ -1963,7 +1841,7 @@ clean_up: /* Release the transport structures. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - list_del(pos); + list_del_init(pos); sctp_transport_free(transport); } nomem: @@ -1991,6 +1869,7 @@ int sctp_process_param(struct sctp_assoc int retval = 1; sctp_scope_t scope; time_t stale; + struct sctp_af *af; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -1998,11 +1877,12 @@ int sctp_process_param(struct sctp_assoc */ switch (param.p->type) { case SCTP_PARAM_IPV6_ADDRESS: - if( PF_INET6 != asoc->base.sk->family) + if (PF_INET6 != asoc->base.sk->sk_family) break; /* Fall through. */ case SCTP_PARAM_IPV4_ADDRESS: - sctp_param2sockaddr(&addr, param.addr, asoc->peer.port, 0); + af = sctp_get_af_specific(param_type2af(param.p->type)); + af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); scope = sctp_scope(peer_addr); if (sctp_in_scope(&addr, scope)) if (!sctp_assoc_add_peer(asoc, &addr, gfp)) @@ -2010,7 +1890,7 @@ int sctp_process_param(struct sctp_assoc break; case SCTP_PARAM_COOKIE_PRESERVATIVE: - if (!sctp_proto.cookie_preserve_enable) + if (!sctp_cookie_preserve_enable) break; stale = ntohl(param.life->lifespan_increment); @@ -2114,86 +1994,619 @@ __u32 sctp_generate_tsn(const struct sct return retval; } -/******************************************************************** - * 4th Level Abstractions - ********************************************************************/ - -/* Convert from an SCTP IP parameter to a union sctp_addr. */ -void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *param, - __u16 port, int iif) +/* + * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type = 0xC1 | Chunk Flags | Chunk Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Serial Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF Parameter #1 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * \ \ + * / .... / + * \ \ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF Parameter #N | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Address Parameter and other parameter will not be wrapped in this function + */ +struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, + union sctp_addr *addr, int vparam_len) { - switch(param->v4.param_hdr.type) { - case SCTP_PARAM_IPV4_ADDRESS: - addr->v4.sin_family = AF_INET; - addr->v4.sin_port = port; - addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; - break; + sctp_addiphdr_t asconf; + struct sctp_chunk *retval; + int length = sizeof(asconf) + vparam_len; + union sctp_addr_param addrparam; + int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); + + addrlen = af->to_addr_param(addr, &addrparam); + if (!addrlen) + return NULL; + length += addrlen; - case SCTP_PARAM_IPV6_ADDRESS: - addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = port; - addr->v6.sin6_flowinfo = 0; /* BUG */ - addr->v6.sin6_addr = param->v6.addr; - addr->v6.sin6_scope_id = iif; - break; + /* Create the chunk. */ + retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF, 0, length); + if (!retval) + return NULL; - default: - SCTP_DEBUG_PRINTK("Illegal address type %d\n", - ntohs(param->v4.param_hdr.type)); - break; - }; + asconf.serial = htonl(asoc->addip_serial++); + + retval->subh.addip_hdr = + sctp_addto_chunk(retval, sizeof(asconf), &asconf); + retval->param_hdr.v = + sctp_addto_chunk(retval, addrlen, &addrparam); + + return retval; +} + +/* ADDIP + * 3.2.1 Add IP Address + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type = 0xC001 | Length = Variable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF-Request Correlation ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 3.2.2 Delete IP Address + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type = 0xC002 | Length = Variable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF-Request Correlation ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc, + union sctp_addr *laddr, + struct sockaddr *addrs, + int addrcnt, + __u16 flags) +{ + sctp_addip_param_t param; + struct sctp_chunk *retval; + union sctp_addr_param addr_param; + union sctp_addr *addr; + void *addr_buf; + struct sctp_af *af; + int paramlen = sizeof(param); + int addr_param_len = 0; + int totallen = 0; + int i; + + /* Get total length of all the address parameters. */ + addr_buf = addrs; + for (i = 0; i < addrcnt; i++) { + addr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(addr->v4.sin_family); + addr_param_len = af->to_addr_param(addr, &addr_param); + + totallen += paramlen; + totallen += addr_param_len; + + addr_buf += af->sockaddr_len; + } + + /* Create an asconf chunk with the required length. */ + retval = sctp_make_asconf(asoc, laddr, totallen); + if (!retval) + return NULL; + + /* Add the address parameters to the asconf chunk. */ + addr_buf = addrs; + for (i = 0; i < addrcnt; i++) { + addr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(addr->v4.sin_family); + addr_param_len = af->to_addr_param(addr, &addr_param); + param.param_hdr.type = flags; + param.param_hdr.length = htons(paramlen + addr_param_len); + param.crr_id = i; + + sctp_addto_chunk(retval, paramlen, ¶m); + sctp_addto_chunk(retval, addr_param_len, &addr_param); + + addr_buf += af->sockaddr_len; + } + return retval; } -/* Convert an IP address in an SCTP param into a sockaddr_in. */ -/* Returns true if a valid conversion was possible. */ -int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa) +/* ADDIP + * 3.2.4 Set Primary IP Address + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type =0xC004 | Length = Variable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF-Request Correlation ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Create an ASCONF chunk with Set Primary IP address parameter. + */ +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr) { - switch (p.p->type) { - case SCTP_PARAM_IPV4_ADDRESS: - sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr); - sa->v4.sin_family = AF_INET; - break; + sctp_addip_param_t param; + struct sctp_chunk *retval; + int len = sizeof(param); + union sctp_addr_param addrparam; + int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); + + addrlen = af->to_addr_param(addr, &addrparam); + if (!addrlen) + return NULL; + len += addrlen; - case SCTP_PARAM_IPV6_ADDRESS: - *((struct in6_addr *)&sa->v4.sin_addr) - = p.v6->addr; - sa->v4.sin_family = AF_INET6; - break; + /* Create the chunk and make asconf header. */ + retval = sctp_make_asconf(asoc, addr, len); + if (!retval) + return NULL; - default: - return 0; - }; + param.param_hdr.type = SCTP_PARAM_SET_PRIMARY; + param.param_hdr.length = htons(len); + param.crr_id = 0; - return 1; + sctp_addto_chunk(retval, sizeof(param), ¶m); + sctp_addto_chunk(retval, addrlen, &addrparam); + + return retval; } -/* Convert a sockaddr_in to an IP address in an SCTP param. - * Returns len if a valid conversion was possible. +/* ADDIP 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type = 0x80 | Chunk Flags | Chunk Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Serial Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF Parameter Response#1 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * \ \ + * / .... / + * \ \ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF Parameter Response#N | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Create an ASCONF_ACK chunk with enough space for the parameter responses. */ -int sockaddr2sctp_addr(const union sctp_addr *sa, sctp_addr_param_t *p) +struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc, + __u32 serial, int vparam_len) { - int len = 0; + sctp_addiphdr_t asconf; + struct sctp_chunk *retval; + int length = sizeof(asconf) + vparam_len; - switch (sa->v4.sin_family) { - case AF_INET: - p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; - p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t)); - len = sizeof(sctp_ipv4addr_param_t); - p->v4.addr.s_addr = sa->v4.sin_addr.s_addr; - break; - - case AF_INET6: - p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; - p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t)); - len = sizeof(sctp_ipv6addr_param_t); - p->v6.addr = *(&sa->v6.sin6_addr); + /* Create the chunk. */ + retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF_ACK, 0, length); + if (!retval) + return NULL; + + asconf.serial = htonl(serial); + + retval->subh.addip_hdr = + sctp_addto_chunk(retval, sizeof(asconf), &asconf); + + return retval; +} + +/* Add response parameters to an ASCONF_ACK chunk. */ +static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id, + __u16 err_code, sctp_addip_param_t *asconf_param) +{ + sctp_addip_param_t ack_param; + sctp_errhdr_t err_param; + int asconf_param_len = 0; + int err_param_len = 0; + __u16 response_type; + + if (SCTP_ERROR_NO_ERROR == err_code) { + response_type = SCTP_PARAM_SUCCESS_REPORT; + } else { + response_type = SCTP_PARAM_ERR_CAUSE; + err_param_len = sizeof(err_param); + if (asconf_param) + asconf_param_len = + ntohs(asconf_param->param_hdr.length); + } + + /* Add Success Indication or Error Cause Indication parameter. */ + ack_param.param_hdr.type = response_type; + ack_param.param_hdr.length = htons(sizeof(ack_param) + + err_param_len + + asconf_param_len); + ack_param.crr_id = crr_id; + sctp_addto_chunk(chunk, sizeof(ack_param), &ack_param); + + if (SCTP_ERROR_NO_ERROR == err_code) + return; + + /* Add Error Cause parameter. */ + err_param.cause = err_code; + err_param.length = htons(err_param_len + asconf_param_len); + sctp_addto_chunk(chunk, err_param_len, &err_param); + + /* Add the failed TLV copied from ASCONF chunk. */ + if (asconf_param) + sctp_addto_chunk(chunk, asconf_param_len, asconf_param); +} + +/* Process a asconf parameter. */ +static __u16 sctp_process_asconf_param(struct sctp_association *asoc, + struct sctp_chunk *asconf, + sctp_addip_param_t *asconf_param) +{ + struct sctp_transport *peer; + struct sctp_af *af; + union sctp_addr addr; + struct list_head *pos; + union sctp_addr_param *addr_param; + + addr_param = (union sctp_addr_param *) + ((void *)asconf_param + sizeof(sctp_addip_param_t)); + + af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); + if (unlikely(!af)) + return SCTP_ERROR_INV_PARAM; + + af->from_addr_param(&addr, addr_param, asoc->peer.port, 0); + switch (asconf_param->param_hdr.type) { + case SCTP_PARAM_ADD_IP: + /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address + * request and does not have the local resources to add this + * new address to the association, it MUST return an Error + * Cause TLV set to the new error code 'Operation Refused + * Due to Resource Shortage'. + */ + + peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC); + if (!peer) + return SCTP_ERROR_RSRC_LOW; + + /* Start the heartbeat timer. */ + if (!mod_timer(&peer->hb_timer, sctp_transport_timeout(peer))) + sctp_transport_hold(peer); + break; + case SCTP_PARAM_DEL_IP: + /* ADDIP 4.3 D7) If a request is received to delete the + * last remaining IP address of a peer endpoint, the receiver + * MUST send an Error Cause TLV with the error cause set to the + * new error code 'Request to Delete Last Remaining IP Address'. + */ + pos = asoc->peer.transport_addr_list.next; + if (pos->next == &asoc->peer.transport_addr_list) + return SCTP_ERROR_DEL_LAST_IP; + + /* ADDIP 4.3 D8) If a request is received to delete an IP + * address which is also the source address of the IP packet + * which contained the ASCONF chunk, the receiver MUST reject + * this request. To reject the request the receiver MUST send + * an Error Cause TLV set to the new error code 'Request to + * Delete Source IP Address' + */ + if (sctp_cmp_addr_exact(sctp_source(asconf), &addr)) + return SCTP_ERROR_DEL_SRC_IP; + + sctp_assoc_del_peer(asoc, &addr); break; + case SCTP_PARAM_SET_PRIMARY: + peer = sctp_assoc_lookup_paddr(asoc, &addr); + if (!peer) + return SCTP_ERROR_INV_PARAM; + sctp_assoc_set_primary(asoc, peer); + break; default: - printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n", - sa->v4.sin_family); - return 0; - }; + return SCTP_ERROR_INV_PARAM; + break; + } + + return SCTP_ERROR_NO_ERROR; +} + +/* Process an incoming ASCONF chunk with the next expected serial no. and + * return an ASCONF_ACK chunk to be sent in response. + */ +struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + struct sctp_chunk *asconf) +{ + sctp_addiphdr_t *hdr; + union sctp_addr_param *addr_param; + sctp_addip_param_t *asconf_param; + struct sctp_chunk *asconf_ack; + + __u16 err_code; + int length = 0; + int chunk_len = asconf->skb->len; + __u32 serial; + int all_param_pass = 1; + + hdr = (sctp_addiphdr_t *)asconf->skb->data; + serial = ntohl(hdr->serial); + + /* Skip the addiphdr and store a pointer to address parameter. */ + length = sizeof(sctp_addiphdr_t); + addr_param = (union sctp_addr_param *)(asconf->skb->data + length); + chunk_len -= length; + + /* Skip the address parameter and store a pointer to the first + * asconf paramter. + */ + length = ntohs(addr_param->v4.param_hdr.length); + asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); + chunk_len -= length; + + /* create an ASCONF_ACK chunk. + * Based on the definitions of parameters, we know that the size of + * ASCONF_ACK parameters are less than or equal to the twice of ASCONF + * paramters. + */ + asconf_ack = sctp_make_asconf_ack(asoc, serial, chunk_len * 2); + if (!asconf_ack) + goto done; + + /* Process the TLVs contained within the ASCONF chunk. */ + while (chunk_len > 0) { + err_code = sctp_process_asconf_param(asoc, asconf, + asconf_param); + /* ADDIP 4.1 A7) + * If an error response is received for a TLV parameter, + * all TLVs with no response before the failed TLV are + * considered successful if not reported. All TLVs after + * the failed response are considered unsuccessful unless + * a specific success indication is present for the parameter. + */ + if (SCTP_ERROR_NO_ERROR != err_code) + all_param_pass = 0; + + if (!all_param_pass) + sctp_add_asconf_response(asconf_ack, + asconf_param->crr_id, err_code, + asconf_param); + + /* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add + * an IP address sends an 'Out of Resource' in its response, it + * MUST also fail any subsequent add or delete requests bundled + * in the ASCONF. + */ + if (SCTP_ERROR_RSRC_LOW == err_code) + goto done; - return len; + /* Move to the next ASCONF param. */ + length = ntohs(asconf_param->param_hdr.length); + asconf_param = (sctp_addip_param_t *)((void *)asconf_param + + length); + chunk_len -= length; + } + +done: + asoc->peer.addip_serial++; + + /* If we are sending a new ASCONF_ACK hold a reference to it in assoc + * after freeing the reference to old asconf ack if any. + */ + if (asconf_ack) { + if (asoc->addip_last_asconf_ack) + sctp_chunk_free(asoc->addip_last_asconf_ack); + + sctp_chunk_hold(asconf_ack); + asoc->addip_last_asconf_ack = asconf_ack; + } + + return asconf_ack; +} + +/* Process a asconf parameter that is successfully acked. */ +static int sctp_asconf_param_success(struct sctp_association *asoc, + sctp_addip_param_t *asconf_param) +{ + struct sctp_af *af; + union sctp_addr addr; + struct sctp_bind_addr *bp = &asoc->base.bind_addr; + union sctp_addr_param *addr_param; + int retval = 0; + + addr_param = (union sctp_addr_param *) + ((void *)asconf_param + sizeof(sctp_addip_param_t)); + + /* We have checked the packet before, so we do not check again. */ + af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); + af->from_addr_param(&addr, addr_param, bp->port, 0); + + switch (asconf_param->param_hdr.type) { + case SCTP_PARAM_ADD_IP: + sctp_local_bh_disable(); + sctp_write_lock(&asoc->base.addr_lock); + retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC); + sctp_write_unlock(&asoc->base.addr_lock); + sctp_local_bh_enable(); + break; + case SCTP_PARAM_DEL_IP: + sctp_local_bh_disable(); + sctp_write_lock(&asoc->base.addr_lock); + retval = sctp_del_bind_addr(bp, &addr); + sctp_write_unlock(&asoc->base.addr_lock); + sctp_local_bh_enable(); + break; + default: + break; + } + + return retval; +} + +/* Get the corresponding ASCONF response error code from the ASCONF_ACK chunk + * for the given asconf parameter. If there is no response for this parameter, + * return the error code based on the third argument 'no_err'. + * ADDIP 4.1 + * A7) If an error response is received for a TLV parameter, all TLVs with no + * response before the failed TLV are considered successful if not reported. + * All TLVs after the failed response are considered unsuccessful unless a + * specific success indication is present for the parameter. + */ +static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, + sctp_addip_param_t *asconf_param, + int no_err) +{ + sctp_addip_param_t *asconf_ack_param; + sctp_errhdr_t *err_param; + int length; + int asconf_ack_len = asconf_ack->skb->len; + __u16 err_code; + + if (no_err) + err_code = SCTP_ERROR_NO_ERROR; + else + err_code = SCTP_ERROR_REQ_REFUSED; + + /* Skip the addiphdr from the asconf_ack chunk and store a pointer to + * the first asconf_ack parameter. + */ + length = sizeof(sctp_addiphdr_t); + asconf_ack_param = (sctp_addip_param_t *)(asconf_ack->skb->data + + length); + asconf_ack_len -= length; + + while (asconf_ack_len > 0) { + if (asconf_ack_param->crr_id == asconf_param->crr_id) { + switch(asconf_ack_param->param_hdr.type) { + case SCTP_PARAM_SUCCESS_REPORT: + return SCTP_ERROR_NO_ERROR; + case SCTP_PARAM_ERR_CAUSE: + length = sizeof(sctp_addip_param_t); + err_param = (sctp_errhdr_t *) + ((void *)asconf_ack_param + length); + asconf_ack_len -= length; + if (asconf_ack_len > 0) + return err_param->cause; + else + return SCTP_ERROR_INV_PARAM; + break; + default: + return SCTP_ERROR_INV_PARAM; + } + } + + length = ntohs(asconf_ack_param->param_hdr.length); + asconf_ack_param = (sctp_addip_param_t *) + ((void *)asconf_ack_param + length); + asconf_ack_len -= length; + } + + return err_code; +} + +/* Process an incoming ASCONF_ACK chunk against the cached last ASCONF chunk. */ +int sctp_process_asconf_ack(struct sctp_association *asoc, + struct sctp_chunk *asconf_ack) +{ + struct sctp_chunk *asconf = asoc->addip_last_asconf; + union sctp_addr_param *addr_param; + sctp_addip_param_t *asconf_param; + int length = 0; + int asconf_len = asconf->skb->len; + int all_param_pass = 0; + int no_err = 1; + int retval = 0; + __u16 err_code = SCTP_ERROR_NO_ERROR; + + /* Skip the chunkhdr and addiphdr from the last asconf sent and store + * a pointer to address parameter. + */ + length = sizeof(sctp_addip_chunk_t); + addr_param = (union sctp_addr_param *)(asconf->skb->data + length); + asconf_len -= length; + + /* Skip the address parameter in the last asconf sent and store a + * pointer to the first asconf paramter. + */ + length = ntohs(addr_param->v4.param_hdr.length); + asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); + asconf_len -= length; + + /* ADDIP 4.1 + * A8) If there is no response(s) to specific TLV parameter(s), and no + * failures are indicated, then all request(s) are considered + * successful. + */ + if (asconf_ack->skb->len == sizeof(sctp_addiphdr_t)) + all_param_pass = 1; + + /* Process the TLVs contained in the last sent ASCONF chunk. */ + while (asconf_len > 0) { + if (all_param_pass) + err_code = SCTP_ERROR_NO_ERROR; + else { + err_code = sctp_get_asconf_response(asconf_ack, + asconf_param, + no_err); + if (no_err && (SCTP_ERROR_NO_ERROR != err_code)) + no_err = 0; + } + + switch (err_code) { + case SCTP_ERROR_NO_ERROR: + retval = sctp_asconf_param_success(asoc, asconf_param); + break; + + case SCTP_ERROR_RSRC_LOW: + retval = 1; + break; + + case SCTP_ERROR_INV_PARAM: + /* Disable sending this type of asconf parameter in + * future. + */ + asoc->peer.addip_disabled_mask |= + asconf_param->param_hdr.type; + break; + + case SCTP_ERROR_REQ_REFUSED: + case SCTP_ERROR_DEL_LAST_IP: + case SCTP_ERROR_DEL_SRC_IP: + default: + break; + } + + /* Skip the processed asconf parameter and move to the next + * one. + */ + length = ntohs(asconf_param->param_hdr.length); + asconf_param = (sctp_addip_param_t *)((void *)asconf_param + + length); + asconf_len -= length; + } + + /* Free the cached last sent asconf chunk. */ + sctp_chunk_free(asconf); + asoc->addip_last_asconf = NULL; + + /* Send the next asconf chunk from the addip chunk queue. */ + asconf = (struct sctp_chunk *)__skb_dequeue(&asoc->addip_chunks); + if (asconf) { + /* Hold the chunk until an ASCONF_ACK is received. */ + sctp_chunk_hold(asconf); + if (sctp_primitive_ASCONF(asoc, asconf)) + sctp_chunk_free(asconf); + else + asoc->addip_last_asconf = asconf; + } + + return retval; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_sideeffect.c linux-2.4.26-pre1/net/sctp/sm_sideeffect.c --- linux-2.4.25/net/sctp/sm_sideeffect.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/sm_sideeffect.c 2004-02-25 15:43:46.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -81,11 +81,11 @@ static void sctp_do_ecn_ce_work(struct s * This element represents the lowest TSN number in the datagram * that was originally marked with the CE bit. */ -static sctp_chunk_t *sctp_do_ecn_ecne_work(struct sctp_association *asoc, +static struct sctp_chunk *sctp_do_ecn_ecne_work(struct sctp_association *asoc, __u32 lowest_tsn, - sctp_chunk_t *chunk) + struct sctp_chunk *chunk) { - sctp_chunk_t *repl; + struct sctp_chunk *repl; /* Our previously transmitted packet ran into some congestion * so we should take action by reducing cwnd and ssthresh @@ -229,7 +229,7 @@ void sctp_generate_t3_rtx_event(unsigned transport, GFP_ATOMIC); if (error) - asoc->base.sk->err = -error; + asoc->base.sk->sk_err = -error; out_unlock: sctp_bh_unlock_sock(asoc->base.sk); @@ -269,7 +269,7 @@ static void sctp_generate_timeout_event( (void *)timeout_type, GFP_ATOMIC); if (error) - asoc->base.sk->err = -error; + asoc->base.sk->sk_err = -error; out_unlock: sctp_bh_unlock_sock(asoc->base.sk); @@ -294,6 +294,12 @@ void sctp_generate_t2_shutdown_event(uns sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN); } +void sctp_generate_t4_rto_event(unsigned long data) +{ + struct sctp_association *asoc = (struct sctp_association *) data; + sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T4_RTO); +} + void sctp_generate_t5_shutdown_guard_event(unsigned long data) { struct sctp_association *asoc = (struct sctp_association *)data; @@ -339,7 +345,7 @@ void sctp_generate_heartbeat_event(unsig transport, GFP_ATOMIC); if (error) - asoc->base.sk->err = -error; + asoc->base.sk->sk_err = -error; out_unlock: sctp_bh_unlock_sock(asoc->base.sk); @@ -359,6 +365,7 @@ sctp_timer_event_t *sctp_timer_events[SC sctp_generate_t1_init_event, sctp_generate_t2_shutdown_event, NULL, + sctp_generate_t4_rto_event, sctp_generate_t5_shutdown_guard_event, sctp_generate_heartbeat_event, sctp_generate_sack_event, @@ -415,7 +422,8 @@ static void sctp_cmd_init_failed(sctp_cm struct sctp_ulpevent *event; event = sctp_ulpevent_make_assoc_change(asoc,0, SCTP_CANT_STR_ASSOC, - 0, 0, 0, GFP_ATOMIC); + (__u16)error, 0, 0, + GFP_ATOMIC); if (event) sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, @@ -528,7 +536,7 @@ static void sctp_cmd_hb_timer_update(sct static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, struct sctp_transport *t, - sctp_chunk_t *chunk) + struct sctp_chunk *chunk) { sctp_sender_hb_info_t *hbinfo; @@ -596,7 +604,7 @@ static int sctp_cmd_process_sack(sctp_cm */ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, - sctp_chunk_t *chunk) + struct sctp_chunk *chunk) { struct sctp_transport *t; @@ -607,33 +615,30 @@ static void sctp_cmd_setup_t2(sctp_cmd_s } /* Helper function to change the state of an association. */ -static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, +static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, + struct sctp_association *asoc, sctp_state_t state) { - struct sock *sk = asoc->base.sk; - struct sctp_opt *sp = sctp_sk(sk); asoc->state = state; - asoc->state_timestamp = jiffies; - if (SCTP_SOCKET_TCP == sp->type) { - /* Change the sk->state of a TCP-style socket that has + if (sctp_style(sk, TCP)) { + /* Change the sk->sk_state of a TCP-style socket that has * sucessfully completed a connect() call. */ - if ((SCTP_STATE_ESTABLISHED == asoc->state) && - (SCTP_SS_CLOSED == sk->state)) - sk->state = SCTP_SS_ESTABLISHED; + if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) + sk->sk_state = SCTP_SS_ESTABLISHED; /* Set the RCV_SHUTDOWN flag when a SHUTDOWN is received. */ - if (SCTP_STATE_SHUTDOWN_RECEIVED == asoc->state) - sk->shutdown |= RCV_SHUTDOWN; - + if (sctp_state(asoc, SHUTDOWN_RECEIVED) && + sctp_sstate(sk, ESTABLISHED)) + sk->sk_shutdown |= RCV_SHUTDOWN; } - if ((SCTP_STATE_ESTABLISHED == asoc->state) || - (SCTP_STATE_CLOSED == asoc->state) || - (SCTP_STATE_SHUTDOWN_RECEIVED == asoc->state)) { + if (sctp_state(asoc, ESTABLISHED) || + sctp_state(asoc, CLOSED) || + sctp_state(asoc, SHUTDOWN_RECEIVED)) { /* Wake up any processes waiting in the asoc's wait queue in * sctp_wait_for_connect() or sctp_wait_for_sndbuf(). */ @@ -646,30 +651,84 @@ static void sctp_cmd_new_state(sctp_cmd_ * For a UDP-style socket, the waiters are woken up by the * notifications. */ - if (SCTP_SOCKET_UDP != sp->type) - sk->state_change(sk); + if (!sctp_style(sk, UDP)) + sk->sk_state_change(sk); } - } /* Helper function to delete an association. */ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds, - struct sctp_association *asoc) + struct sctp_association *asoc) { struct sock *sk = asoc->base.sk; /* If it is a non-temporary association belonging to a TCP-style - * listening socket, do not free it so that accept() can pick it - * up later. - */ - if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) && - (SCTP_SS_LISTENING == sk->state) && (!asoc->temp)) + * listening socket that is not closed, do not free it so that accept() + * can pick it up later. + */ + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING) && + (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK)) return; sctp_unhash_established(asoc); sctp_association_free(asoc); } +/* + * ADDIP Section 4.1 ASCONF Chunk Procedures + * A4) Start a T-4 RTO timer, using the RTO value of the selected + * destination address (we use active path instead of primary path just + * because primary path may be inactive. + */ +static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, + struct sctp_association *asoc, + struct sctp_chunk *chunk) +{ + struct sctp_transport *t; + + t = asoc->peer.active_path; + asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; + chunk->transport = t; +} + +/* Process an incoming Operation Error Chunk. */ +static void sctp_cmd_process_operr(sctp_cmd_seq_t *cmds, + struct sctp_association *asoc, + struct sctp_chunk *chunk) +{ + struct sctp_operr_chunk *operr_chunk; + struct sctp_errhdr *err_hdr; + + operr_chunk = (struct sctp_operr_chunk *)chunk->chunk_hdr; + err_hdr = &operr_chunk->err_hdr; + + switch (err_hdr->cause) { + case SCTP_ERROR_UNKNOWN_CHUNK: + { + struct sctp_chunkhdr *unk_chunk_hdr; + + unk_chunk_hdr = (struct sctp_chunkhdr *)err_hdr->variable; + switch (unk_chunk_hdr->type) { + /* ADDIP 4.1 A9) If the peer responds to an ASCONF with an + * ERROR chunk reporting that it did not recognized the ASCONF + * chunk type, the sender of the ASCONF MUST NOT send any + * further ASCONF chunks and MUST stop its T-4 timer. + */ + case SCTP_CID_ASCONF: + asoc->peer.asconf_capable = 0; + sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + break; + default: + break; + } + break; + } + default: + break; + } +} + /* These three macros allow us to pull the debugging code out of the * main flow of sctp_do_sm() to keep attention focused on the real * functionality there. @@ -706,7 +765,7 @@ int sctp_do_sm(sctp_event_t event_type, int gfp) { sctp_cmd_seq_t commands; - sctp_sm_table_entry_t *state_fn; + const sctp_sm_table_entry_t *state_fn; sctp_disposition_t status; int error = 0; typedef const char *(printfn_t)(sctp_subtype_t); @@ -837,17 +896,18 @@ int sctp_cmd_interpreter(sctp_event_t ev int error = 0; int force; sctp_cmd_t *cmd; - sctp_chunk_t *new_obj; - sctp_chunk_t *chunk = NULL; + struct sctp_chunk *new_obj; + struct sctp_chunk *chunk = NULL; struct sctp_packet *packet; struct list_head *pos; struct timer_list *timer; unsigned long timeout; struct sctp_transport *t; sctp_sackhdr_t sackh; + int local_cork = 0; - if(SCTP_EVENT_T_TIMEOUT != event_type) - chunk = (sctp_chunk_t *) event_arg; + if (SCTP_EVENT_T_TIMEOUT != event_type) + chunk = (struct sctp_chunk *) event_arg; /* Note: This whole file is a huge candidate for rework. * For example, each command could either have its own handler, so @@ -864,6 +924,10 @@ int sctp_cmd_interpreter(sctp_event_t ev case SCTP_CMD_NEW_ASOC: /* Register a new association. */ + if (local_cork) { + sctp_outq_uncork(&asoc->outqueue); + local_cork = 0; + } asoc = cmd->obj.ptr; /* Register with the endpoint. */ sctp_endpoint_add_asoc(ep, asoc); @@ -878,7 +942,11 @@ int sctp_cmd_interpreter(sctp_event_t ev sctp_outq_teardown(&asoc->outqueue); break; - case SCTP_CMD_DELETE_TCB: + case SCTP_CMD_DELETE_TCB: + if (local_cork) { + sctp_outq_uncork(&asoc->outqueue); + local_cork = 0; + } /* Delete the current association. */ sctp_cmd_delete_tcb(commands, asoc); asoc = NULL; @@ -936,7 +1004,7 @@ int sctp_cmd_interpreter(sctp_event_t ev new_obj = sctp_make_cookie_echo(asoc, chunk); if (!new_obj) { if (cmd->obj.ptr) - sctp_free_chunk(cmd->obj.ptr); + sctp_chunk_free(cmd->obj.ptr); goto nomem; } sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, @@ -957,7 +1025,7 @@ int sctp_cmd_interpreter(sctp_event_t ev asoc->overall_error_count = 0; /* Generate a SHUTDOWN chunk. */ - new_obj = sctp_make_shutdown(asoc); + new_obj = sctp_make_shutdown(asoc, chunk); if (!new_obj) goto nomem; sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, @@ -982,9 +1050,13 @@ int sctp_cmd_interpreter(sctp_event_t ev break; case SCTP_CMD_REPLY: + /* If an caller has not already corked, do cork. */ + if (!asoc->outqueue.cork) { + sctp_outq_cork(&asoc->outqueue); + local_cork = 1; + } /* Send a chunk to our peer. */ - error = sctp_outq_tail(&asoc->outqueue, - cmd->obj.ptr); + error = sctp_outq_tail(&asoc->outqueue, cmd->obj.ptr); break; case SCTP_CMD_SEND_PKT: @@ -1002,7 +1074,8 @@ int sctp_cmd_interpreter(sctp_event_t ev case SCTP_CMD_TRANSMIT: /* Kick start transmission. */ - error = sctp_outq_flush(&asoc->outqueue, 0); + error = sctp_outq_uncork(&asoc->outqueue); + local_cork = 0; break; case SCTP_CMD_ECN_CE: @@ -1167,19 +1240,28 @@ int sctp_cmd_interpreter(sctp_event_t ev GFP_ATOMIC); break; + case SCTP_CMD_SETUP_T4: + sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr); + break; + + case SCTP_CMD_PROCESS_OPERR: + sctp_cmd_process_operr(commands, asoc, chunk); + break; default: printk(KERN_WARNING "Impossible command: %u, %p\n", cmd->verb, cmd->obj.ptr); break; }; if (error) - return error; + break; } +out: + if (local_cork) + sctp_outq_uncork(&asoc->outqueue); return error; - nomem: error = -ENOMEM; - return error; + goto out; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_statefuns.c linux-2.4.26-pre1/net/sctp/sm_statefuns.c --- linux-2.4.25/net/sctp/sm_statefuns.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/sm_statefuns.c 2004-02-25 15:43:00.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001-2002 Intel Corp. * Copyright (c) 2002 Nokia Corp. * @@ -45,6 +45,8 @@ * Dajiang Zhang * Daisy Chang * Ardelle Fan + * Ryan Layer + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -101,7 +103,7 @@ sctp_disposition_t sctp_sf_do_4_C(const void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; struct sctp_ulpevent *ev; /* RFC 2960 6.10 Bundling @@ -185,10 +187,10 @@ sctp_disposition_t sctp_sf_do_5_1B_init( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; - sctp_chunk_t *repl; + struct sctp_chunk *chunk = arg; + struct sctp_chunk *repl; struct sctp_association *new_asoc; - sctp_chunk_t *err_chunk; + struct sctp_chunk *err_chunk; struct sctp_packet *packet; sctp_unrecognized_param_t *unk_param; struct sock *sk; @@ -212,9 +214,9 @@ sctp_disposition_t sctp_sf_do_5_1B_init( * on the TCP-style socket exceed the max backlog, respond with an * ABORT. */ - if ((SCTP_SS_LISTENING != sk->state) || - ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) && - (sk->ack_backlog >= sk->max_ack_backlog))) + if (!sctp_sstate(sk, LISTENING) || + (sctp_style(sk, TCP) && + (sk->sk_ack_backlog >= sk->sk_max_ack_backlog))) return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); /* Verify the INIT chunk before processing it. */ @@ -232,7 +234,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init( ntohs(err_chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); - sctp_free_chunk(err_chunk); + sctp_chunk_free(err_chunk); if (packet) { sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, @@ -303,7 +305,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init( * parameter type. */ sctp_addto_chunk(repl, len, unk_param); - sctp_free_chunk(err_chunk); + sctp_chunk_free(err_chunk); } sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); @@ -320,7 +322,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init( nomem_ack: if (err_chunk) - sctp_free_chunk(err_chunk); + sctp_chunk_free(err_chunk); nomem_init: sctp_association_free(new_asoc); nomem: @@ -361,10 +363,10 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_init_chunk_t *initchunk; __u32 init_tag; - sctp_chunk_t *err_chunk; + struct sctp_chunk *err_chunk; struct sctp_packet *packet; sctp_disposition_t ret; @@ -386,7 +388,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c * error and close the association by transmitting an ABORT. */ if (!init_tag) { - sctp_chunk_t *reply = sctp_make_abort(asoc, chunk, 0); + struct sctp_chunk *reply = sctp_make_abort(asoc, chunk, 0); if (!reply) goto nomem; @@ -416,7 +418,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c ntohs(err_chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); - sctp_free_chunk(err_chunk); + sctp_chunk_free(err_chunk); if (packet) { sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, @@ -519,13 +521,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(co const sctp_subtype_t type, void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; struct sctp_association *new_asoc; sctp_init_chunk_t *peer_init; - sctp_chunk_t *repl; + struct sctp_chunk *repl; struct sctp_ulpevent *ev; int error = 0; - sctp_chunk_t *err_chk_p; + struct sctp_chunk *err_chk_p; /* If the packet is an OOTB packet which is temporarily on the * control endpoint, respond with an ABORT. @@ -537,7 +539,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(co * are in good shape. */ chunk->subh.cookie_hdr = - (sctp_signed_cookie_t *)chunk->skb->data; + (struct sctp_signed_cookie *)chunk->skb->data; skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); @@ -623,7 +625,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(co return SCTP_DISPOSITION_CONSUME; nomem_ev: - sctp_free_chunk(repl); + sctp_chunk_free(repl); nomem_repl: nomem_init: sctp_association_free(new_asoc); @@ -704,7 +706,7 @@ sctp_disposition_t sctp_sf_heartbeat(con sctp_cmd_seq_t *commands) { struct sctp_transport *transport = (struct sctp_transport *) arg; - sctp_chunk_t *reply; + struct sctp_chunk *reply; sctp_sender_hb_info_t hbinfo; size_t paylen = 0; @@ -738,7 +740,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3( { struct sctp_transport *transport = (struct sctp_transport *) arg; - if (asoc->overall_error_count >= asoc->overall_error_threshold) { + if (asoc->overall_error_count > asoc->max_retrans) { /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -801,8 +803,8 @@ sctp_disposition_t sctp_sf_beat_8_3(cons void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; - sctp_chunk_t *reply; + struct sctp_chunk *chunk = arg; + struct sctp_chunk *reply; size_t paylen = 0; /* 8.5 When receiving an SCTP packet, the endpoint MUST ensure @@ -868,7 +870,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; union sctp_addr from_addr; struct sctp_transport *link; sctp_sender_hb_info_t *hbinfo; @@ -919,24 +921,25 @@ sctp_disposition_t sctp_sf_backbeat_8_3( * condition. */ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, - sctp_chunk_t *init, + struct sctp_chunk *init, sctp_cmd_seq_t *commands) { int len; struct sctp_packet *pkt; - sctp_addr_param_t *addrparm; - sctp_errhdr_t *errhdr; + union sctp_addr_param *addrparm; + struct sctp_errhdr *errhdr; struct sctp_endpoint *ep; - char buffer[sizeof(sctp_errhdr_t) + sizeof(sctp_addr_param_t)]; + char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)]; + struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family); /* Build the error on the stack. We are way to malloc crazy * throughout the code today. */ - errhdr = (sctp_errhdr_t *)buffer; - addrparm = (sctp_addr_param_t *)errhdr->variable; + errhdr = (struct sctp_errhdr *)buffer; + addrparm = (union sctp_addr_param *)errhdr->variable; /* Copy into a parm format. */ - len = sockaddr2sctp_addr(ssa, addrparm); + len = af->to_addr_param(ssa, addrparm); len += sizeof(sctp_errhdr_t); errhdr->cause = SCTP_ERROR_RESTART; @@ -971,7 +974,7 @@ out: */ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, const struct sctp_association *asoc, - sctp_chunk_t *init, + struct sctp_chunk *init, sctp_cmd_seq_t *commands) { struct sctp_transport *new_addr, *addr; @@ -1112,10 +1115,10 @@ static sctp_disposition_t sctp_sf_do_une void *arg, sctp_cmd_seq_t *commands) { sctp_disposition_t retval; - sctp_chunk_t *chunk = arg; - sctp_chunk_t *repl; + struct sctp_chunk *chunk = arg; + struct sctp_chunk *repl; struct sctp_association *new_asoc; - sctp_chunk_t *err_chunk; + struct sctp_chunk *err_chunk; struct sctp_packet *packet; sctp_unrecognized_param_t *unk_param; int len; @@ -1191,7 +1194,7 @@ static sctp_disposition_t sctp_sf_do_une * since there are no peer addresses to check against. * Upon return an ABORT will have been sent if needed. */ - if (asoc->state != SCTP_STATE_COOKIE_WAIT) { + if (!sctp_state(asoc, COOKIE_WAIT)) { if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) { retval = SCTP_DISPOSITION_CONSUME; @@ -1238,7 +1241,6 @@ static sctp_disposition_t sctp_sf_do_une * parameter type. */ sctp_addto_chunk(repl, len, unk_param); - sctp_free_chunk(err_chunk); } sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); @@ -1254,7 +1256,7 @@ static sctp_disposition_t sctp_sf_do_une cleanup: if (err_chunk) - sctp_free_chunk(err_chunk); + sctp_chunk_free(err_chunk); return retval; nomem: retval = SCTP_DISPOSITION_NOMEM; @@ -1377,13 +1379,13 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupi */ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, const struct sctp_association *asoc, - sctp_chunk_t *chunk, + struct sctp_chunk *chunk, sctp_cmd_seq_t *commands, struct sctp_association *new_asoc) { sctp_init_chunk_t *peer_init; struct sctp_ulpevent *ev; - sctp_chunk_t *repl; + struct sctp_chunk *repl; /* new_asoc is a brand-new association, so these are not yet * side effects--it is safe to run them here. @@ -1429,7 +1431,7 @@ static sctp_disposition_t sctp_sf_do_dup return SCTP_DISPOSITION_CONSUME; nomem_ev: - sctp_free_chunk(repl); + sctp_chunk_free(repl); nomem: return SCTP_DISPOSITION_NOMEM; } @@ -1444,13 +1446,13 @@ nomem: /* This case represents an initialization collision. */ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, const struct sctp_association *asoc, - sctp_chunk_t *chunk, + struct sctp_chunk *chunk, sctp_cmd_seq_t *commands, struct sctp_association *new_asoc) { sctp_init_chunk_t *peer_init; struct sctp_ulpevent *ev; - sctp_chunk_t *repl; + struct sctp_chunk *repl; /* new_asoc is a brand-new association, so these are not yet * side effects--it is safe to run them here. @@ -1492,7 +1494,7 @@ static sctp_disposition_t sctp_sf_do_dup return SCTP_DISPOSITION_CONSUME; nomem_ev: - sctp_free_chunk(repl); + sctp_chunk_free(repl); nomem: return SCTP_DISPOSITION_NOMEM; } @@ -1507,10 +1509,10 @@ nomem: */ /* This case represents an initialization collision. */ static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - sctp_chunk_t *chunk, - sctp_cmd_seq_t *commands, - struct sctp_association *new_asoc) + const struct sctp_association *asoc, + struct sctp_chunk *chunk, + sctp_cmd_seq_t *commands, + struct sctp_association *new_asoc) { /* The cookie should be silently discarded. * The endpoint SHOULD NOT change states and should leave @@ -1528,13 +1530,13 @@ static sctp_disposition_t sctp_sf_do_dup */ /* This case represents an initialization collision. */ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - sctp_chunk_t *chunk, - sctp_cmd_seq_t *commands, - struct sctp_association *new_asoc) + const struct sctp_association *asoc, + struct sctp_chunk *chunk, + sctp_cmd_seq_t *commands, + struct sctp_association *new_asoc) { struct sctp_ulpevent *ev = NULL; - sctp_chunk_t *repl; + struct sctp_chunk *repl; /* Clarification from Implementor's Guide: * D) When both local and remote tags match the endpoint should @@ -1610,16 +1612,16 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupc sctp_cmd_seq_t *commands) { sctp_disposition_t retval; - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; struct sctp_association *new_asoc; int error = 0; char action; - sctp_chunk_t *err_chk_p; + struct sctp_chunk *err_chk_p; /* "Decode" the chunk. We have no optional parameters so we * are in good shape. */ - chunk->subh.cookie_hdr = (sctp_signed_cookie_t *)chunk->skb->data; + chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); @@ -1708,7 +1710,7 @@ sctp_disposition_t sctp_sf_shutdown_pend void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; if (!sctp_vtag_verify_either(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -1731,7 +1733,7 @@ sctp_disposition_t sctp_sf_shutdown_sent void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; if (!sctp_vtag_verify_either(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -1785,27 +1787,20 @@ sctp_disposition_t sctp_sf_cookie_echoed void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_errhdr_t *err; - err = (sctp_errhdr_t *)(chunk->skb->data); - - /* If we have gotten too many failures, give up. */ - if (1 + asoc->counters[SCTP_COUNTER_INIT_ERROR] > - asoc->max_init_attempts) { - /* INIT_FAILED will issue an ulpevent. */ - sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(err->cause)); - return SCTP_DISPOSITION_DELETE_TCB; - } - /* Process the error here */ - switch (err->cause) { - case SCTP_ERROR_STALE_COOKIE: - return sctp_sf_do_5_2_6_stale(ep, asoc, type, arg, commands); - default: - return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + /* FUTURE FIXME: When PR-SCTP related and other optional + * parms are emitted, this will have to change to handle multiple + * errors. + */ + sctp_walk_errors(err, chunk->chunk_hdr) { + if (SCTP_ERROR_STALE_COOKIE == err->cause) + return sctp_sf_do_5_2_6_stale(ep, asoc, type, + arg, commands); } + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); } /* @@ -1839,14 +1834,14 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; time_t stale; sctp_cookie_preserve_param_t bht; sctp_errhdr_t *err; struct list_head *pos; struct sctp_transport *t; - sctp_chunk_t *reply; - sctp_bind_addr_t *bp; + struct sctp_chunk *reply; + struct sctp_bind_addr *bp; int attempts; attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; @@ -1874,14 +1869,14 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal * yield a higher probability of success on the reattempt. */ stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t))); - stale = stale << 1 / 1000; + stale = (stale * 2) / 1000; bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE; bht.param_hdr.length = htons(sizeof(bht)); bht.lifespan_increment = htonl(stale); /* Build that new INIT chunk. */ - bp = (sctp_bind_addr_t *) &asoc->base.bind_addr; + bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht)); if (!reply) goto nomem; @@ -1954,23 +1949,24 @@ sctp_disposition_t sctp_sf_do_9_1_abort( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; + unsigned len; __u16 error = SCTP_ERROR_NO_ERROR; if (!sctp_vtag_verify_either(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); - if (chunk && (ntohs(chunk->chunk_hdr->length) >= - (sizeof(struct sctp_chunkhdr) + - sizeof(struct sctp_errhdr)))) + /* Check that chunk header looks valid. */ + len = ntohs(chunk->chunk_hdr->length); + if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) error = ((sctp_errhdr_t *)chunk->skb->data)->cause; + /* ASSOC_FAILED will DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); SCTP_INC_STATS(SctpAborteds); SCTP_DEC_STATS(SctpCurrEstab); - /* BUG? This does not look complete... */ return SCTP_DISPOSITION_ABORT; } @@ -1985,7 +1981,8 @@ sctp_disposition_t sctp_sf_cookie_wait_a void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; + unsigned len; __u16 error = SCTP_ERROR_NO_ERROR; if (!sctp_vtag_verify_either(chunk, asoc)) @@ -1997,9 +1994,9 @@ sctp_disposition_t sctp_sf_cookie_wait_a sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); - if (chunk && (ntohs(chunk->chunk_hdr->length) >= - (sizeof(struct sctp_chunkhdr) + - sizeof(struct sctp_errhdr)))) + /* Check that chunk header looks valid. */ + len = ntohs(chunk->chunk_hdr->length); + if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) error = ((sctp_errhdr_t *)chunk->skb->data)->cause; /* CMD_INIT_FAILED will DELETE_TCB. */ @@ -2064,9 +2061,10 @@ sctp_disposition_t sctp_sf_do_9_2_shutdo void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_shutdownhdr_t *sdh; sctp_disposition_t disposition; + struct sctp_ulpevent *ev; /* Convert the elaborate header. */ sdh = (sctp_shutdownhdr_t *)chunk->skb->data; @@ -2097,12 +2095,28 @@ sctp_disposition_t sctp_sf_do_9_2_shutdo arg, commands); } + if (SCTP_DISPOSITION_NOMEM == disposition) + goto out; + /* - verify, by checking the Cumulative TSN Ack field of the * chunk, that all its outstanding DATA chunks have been * received by the SHUTDOWN sender. */ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack)); + + /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT + * When a peer sends a SHUTDOWN, SCTP delivers this notification to + * inform the application that it should cease sending data. + */ + ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC); + if (!ev) { + disposition = SCTP_DISPOSITION_NOMEM; + goto out; + } + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + +out: return disposition; } @@ -2119,8 +2133,8 @@ sctp_disposition_t sctp_sf_do_9_2_reshut void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = (sctp_chunk_t *) arg; - sctp_chunk_t *reply; + struct sctp_chunk *chunk = (struct sctp_chunk *) arg; + struct sctp_chunk *reply; reply = sctp_make_shutdown_ack(asoc, chunk); if (NULL == reply) @@ -2174,7 +2188,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(co sctp_cmd_seq_t *commands) { sctp_cwrhdr_t *cwr; - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; /* 8.5 When receiving an SCTP packet, the endpoint MUST ensure * that the value in the Verification Tag field of the @@ -2230,7 +2244,7 @@ sctp_disposition_t sctp_sf_do_ecne(const sctp_cmd_seq_t *commands) { sctp_ecnehdr_t *ecne; - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; /* 8.5 When receiving an SCTP packet, the endpoint MUST ensure * that the value in the Verification Tag field of the @@ -2287,9 +2301,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_datahdr_t *data_hdr; - sctp_chunk_t *err; + struct sctp_chunk *err; size_t datalen; sctp_verb_t deliver; int tmp; @@ -2311,9 +2325,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2( skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); tsn = ntohl(data_hdr->tsn); - SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn); - SCTP_DEBUG_PRINTK("eat_data: skb->head %p.\n", chunk->skb->head); /* ASSERT: Now skb->data is really the user data. */ @@ -2328,9 +2340,13 @@ sctp_disposition_t sctp_sf_eat_data_6_2( */ if (!chunk->ecn_ce_done) { + struct sctp_af *af; chunk->ecn_ce_done = 1; - if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) && - asoc->peer.ecn_capable) { + + af = sctp_get_af_specific( + ipver2af(chunk->skb->nh.iph->version)); + + if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { /* Do real work as sideffect. */ sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, SCTP_U32(tsn)); @@ -2373,7 +2389,8 @@ sctp_disposition_t sctp_sf_eat_data_6_2( * PMTU. In cases, such as loopback, this might be a rather * large spill over. */ - if (asoc->rwnd_over || (datalen > asoc->rwnd + asoc->frag_point)) { + if (!asoc->rwnd || asoc->rwnd_over || + (datalen > asoc->rwnd + asoc->frag_point)) { /* If this is the next TSN, consider reneging to make * room. Note: Playing nice with a confused sender. A @@ -2545,9 +2562,9 @@ sctp_disposition_t sctp_sf_eat_data_fast void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_datahdr_t *data_hdr; - sctp_chunk_t *err; + struct sctp_chunk *err; size_t datalen; int tmp; __u32 tsn; @@ -2583,9 +2600,13 @@ sctp_disposition_t sctp_sf_eat_data_fast * chunk later. */ if (!chunk->ecn_ce_done) { + struct sctp_af *af; chunk->ecn_ce_done = 1; - if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) && - asoc->peer.ecn_capable) { + + af = sctp_get_af_specific( + ipver2af(chunk->skb->nh.iph->version)); + + if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { /* Do real work as sideffect. */ sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, SCTP_U32(tsn)); @@ -2720,7 +2741,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_sackhdr_t *sackh; __u32 ctsn; @@ -2733,6 +2754,9 @@ sctp_disposition_t sctp_sf_eat_sack_6_2( /* Pull the SACK chunk from the data buffer */ sackh = sctp_sm_pull_sack(chunk); + /* Was this a bogus SACK? */ + if (!sackh) + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); chunk->subh.sack_hdr = sackh; ctsn = ntohl(sackh->cum_tsn_ack); @@ -2782,8 +2806,8 @@ sctp_disposition_t sctp_sf_tabort_8_4_8( sctp_cmd_seq_t *commands) { struct sctp_packet *packet = NULL; - sctp_chunk_t *chunk = arg; - sctp_chunk_t *abort; + struct sctp_chunk *chunk = arg; + struct sctp_chunk *abort; packet = sctp_ootb_pkt_new(asoc, chunk); @@ -2827,7 +2851,7 @@ sctp_disposition_t sctp_sf_operr_notify( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; struct sctp_ulpevent *ev; while (chunk->chunk_end > chunk->skb->data) { @@ -2841,6 +2865,9 @@ sctp_disposition_t sctp_sf_operr_notify( sctp_ulpevent_free(ev); goto nomem; } + + sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, + SCTP_CHUNK(chunk)); } return SCTP_DISPOSITION_CONSUME; @@ -2864,8 +2891,8 @@ sctp_disposition_t sctp_sf_do_9_2_final( void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; - sctp_chunk_t *reply; + struct sctp_chunk *chunk = arg; + struct sctp_chunk *reply; struct sctp_ulpevent *ev; /* 10.2 H) SHUTDOWN COMPLETE notification @@ -2932,7 +2959,7 @@ sctp_disposition_t sctp_sf_ootb(const st void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; struct sk_buff *skb = chunk->skb; sctp_chunkhdr_t *ch; __u8 *ch_end; @@ -2984,8 +3011,8 @@ sctp_disposition_t sctp_sf_shut_8_4_5(co sctp_cmd_seq_t *commands) { struct sctp_packet *packet = NULL; - sctp_chunk_t *chunk = arg; - sctp_chunk_t *shut; + struct sctp_chunk *chunk = arg; + struct sctp_chunk *shut; packet = sctp_ootb_pkt_new(asoc, chunk); @@ -3040,6 +3067,143 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); } +/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */ +sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, void *arg, + sctp_cmd_seq_t *commands) +{ + struct sctp_chunk *chunk = arg; + struct sctp_chunk *asconf_ack = NULL; + sctp_addiphdr_t *hdr; + __u32 serial; + + hdr = (sctp_addiphdr_t *)chunk->skb->data; + serial = ntohl(hdr->serial); + + /* ADDIP 4.2 C1) Compare the value of the serial number to the value + * the endpoint stored in a new association variable + * 'Peer-Serial-Number'. + */ + if (serial == asoc->peer.addip_serial + 1) { + /* ADDIP 4.2 C2) If the value found in the serial number is + * equal to the ('Peer-Serial-Number' + 1), the endpoint MUST + * do V1-V5. + */ + asconf_ack = sctp_process_asconf((struct sctp_association *) + asoc, chunk); + if (!asconf_ack) + return SCTP_DISPOSITION_NOMEM; + } else if (serial == asoc->peer.addip_serial) { + /* ADDIP 4.2 C3) If the value found in the serial number is + * equal to the value stored in the 'Peer-Serial-Number' + * IMPLEMENTATION NOTE: As an optimization a receiver may wish + * to save the last ASCONF-ACK for some predetermined period of * time and instead of re-processing the ASCONF (with the same + * serial number) it may just re-transmit the ASCONF-ACK. + */ + if (asoc->addip_last_asconf_ack) + asconf_ack = asoc->addip_last_asconf_ack; + else + return SCTP_DISPOSITION_DISCARD; + } else { + /* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since + * it must be either a stale packet or from an attacker. + */ + return SCTP_DISPOSITION_DISCARD; + } + + /* ADDIP 4.2 C5) In both cases C2 and C3 the ASCONF-ACK MUST be sent + * back to the source address contained in the IP header of the ASCONF + * being responded to. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack)); + + return SCTP_DISPOSITION_CONSUME; +} + +/* + * ADDIP Section 4.3 General rules for address manipulation + * When building TLV parameters for the ASCONF Chunk that will add or + * delete IP addresses the D0 to D13 rules should be applied: + */ +sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, void *arg, + sctp_cmd_seq_t *commands) +{ + struct sctp_chunk *asconf_ack = arg; + struct sctp_chunk *last_asconf = asoc->addip_last_asconf; + struct sctp_chunk *abort; + sctp_addiphdr_t *addip_hdr; + __u32 sent_serial, rcvd_serial; + + addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data; + rcvd_serial = ntohl(addip_hdr->serial); + + if (last_asconf) { + addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; + sent_serial = ntohl(addip_hdr->serial); + } else { + sent_serial = asoc->addip_serial - 1; + } + + /* D0) If an endpoint receives an ASCONF-ACK that is greater than or + * equal to the next serial number to be used but no ASCONF chunk is + * outstanding the endpoint MUST ABORT the association. Note that a + * sequence number is greater than if it is no more than 2^^31-1 + * larger than the current sequence number (using serial arithmetic). + */ + if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) && + !(asoc->addip_last_asconf)) { + abort = sctp_make_abort(asoc, asconf_ack, + sizeof(sctp_errhdr_t)); + if (abort) { + sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, NULL, 0); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(abort)); + } + /* We are going to ABORT, so we might as well stop + * processing the rest of the chunks in the packet. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_U32(SCTP_ERROR_ASCONF_ACK)); + SCTP_INC_STATS(SctpAborteds); + SCTP_DEC_STATS(SctpCurrEstab); + return SCTP_DISPOSITION_ABORT; + } + + if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) { + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + + if (!sctp_process_asconf_ack((struct sctp_association *)asoc, + asconf_ack)) + return SCTP_DISPOSITION_CONSUME; + + abort = sctp_make_abort(asoc, asconf_ack, + sizeof(sctp_errhdr_t)); + if (abort) { + sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, NULL, 0); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(abort)); + } + /* We are going to ABORT, so we might as well stop + * processing the rest of the chunks in the packet. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_U32(SCTP_ERROR_ASCONF_ACK)); + SCTP_INC_STATS(SctpAborteds); + SCTP_DEC_STATS(SctpCurrEstab); + return SCTP_DISPOSITION_ABORT; + } + + return SCTP_DISPOSITION_DISCARD; +} + /* * Process an unknown chunk. * @@ -3069,8 +3233,8 @@ sctp_disposition_t sctp_sf_unk_chunk(con void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *unk_chunk = arg; - sctp_chunk_t *err_chunk; + struct sctp_chunk *unk_chunk = arg; + struct sctp_chunk *err_chunk; sctp_chunkhdr_t *hdr; SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk); @@ -3182,82 +3346,6 @@ sctp_disposition_t sctp_sf_pdiscard(cons return SCTP_DISPOSITION_CONSUME; } -#if 0 -/* - * We did something stupid but got lucky. Namely, we sent a HEARTBEAT - * before the association was all the way up and we did NOT get an - * ABORT. - * - * Log the fact and then process normally. - * - * Section: Not specified - * Verification Tag: 8.5 Verification Tag [Normal verification] - * Inputs - * (endpoint, asoc, chunk) - * - * Outputs - * (asoc, reply_msg, msg_up, timers, counters) - * - * The return value is the disposition of the chunk. - */ -sctp_disposition_t lucky(const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands) -{ - sctp_chunk_t *chunk = arg; - - /* 8.5 When receiving an SCTP packet, the endpoint MUST ensure - * that the value in the Verification Tag field of the - * received SCTP packet matches its own Tag. ... - */ - if (chunk->sctp_hdr->vtag != asoc->c.my_vtag) - return sctp_sf_pdiscard(ep, asoc, type, arg, commands); - - return SCTP_DISPOSITION_CONSUME; - -nomem: - return SCTP_DISPOSITION_NOMEM; -} -#endif /* 0 */ - -#if 0 -/* - * The other end is doing something very stupid. We'll ignore them - * after logging their idiocy. :-) - * - * Section: Not specified - * Verification Tag: 8.5 Verification Tag [Normal verification] - * Inputs - * (endpoint, asoc, chunk) - * - * Outputs - * (asoc, reply_msg, msg_up, timers, counters) - * - * The return value is the disposition of the chunk. - */ -sctp_disposition_t other_stupid(const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands) -{ - sctp_chunk_t *chunk = arg; - - /* 8.5 When receiving an SCTP packet, the endpoint MUST ensure - * that the value in the Verification Tag field of the - * received SCTP packet matches its own Tag. ... - */ - if (chunk->sctp_hdr->vtag != asoc->c.my_vtag) - return sctp_sf_pdiscard(ep, asoc, type, arg, commands); - - return SCTP_DISPOSITION_CONSUME; - -nomem: - return SCTP_DISPOSITION_NOMEM; -} -#endif /* 0 */ /* * The other end is violating protocol. @@ -3348,7 +3436,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(c void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *repl; + struct sctp_chunk *repl; /* The comment below says that we enter COOKIE-WAIT AFTER * sending the INIT, but that doesn't actually work in our @@ -3454,7 +3542,7 @@ sctp_disposition_t sctp_sf_do_prm_send(c void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = arg; + struct sctp_chunk *chunk = arg; sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); return SCTP_DISPOSITION_CONSUME; @@ -3564,7 +3652,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_ab * if necessary to fill gaps. */ struct msghdr *msg = arg; - sctp_chunk_t *abort; + struct sctp_chunk *abort; sctp_disposition_t retval; retval = SCTP_DISPOSITION_CONSUME; @@ -3697,7 +3785,7 @@ sctp_disposition_t sctp_sf_cookie_wait_p sctp_cmd_seq_t *commands) { struct msghdr *msg = arg; - sctp_chunk_t *abort; + struct sctp_chunk *abort; sctp_disposition_t retval; /* Stop T1-init timer */ @@ -3870,6 +3958,26 @@ sctp_disposition_t sctp_sf_do_prm_reques } /* + * ADDIP Section 4.1 ASCONF Chunk Procedures + * When an endpoint has an ASCONF signaled change to be sent to the + * remote endpoint it should do A1 to A9 + */ +sctp_disposition_t sctp_sf_do_prm_asconf(const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + struct sctp_chunk *chunk = arg; + + sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); + return SCTP_DISPOSITION_CONSUME; +} + +/* * Ignore the primitive event * * The return value is the disposition of the primitive. @@ -3909,14 +4017,14 @@ sctp_disposition_t sctp_sf_do_9_2_start_ void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *reply; + struct sctp_chunk *reply; /* Once all its outstanding data has been acknowledged, the * endpoint shall send a SHUTDOWN chunk to its peer including * in the Cumulative TSN Ack field the last sequential TSN it * has received from the peer. */ - reply = sctp_make_shutdown(asoc); + reply = sctp_make_shutdown(asoc, NULL); if (!reply) goto nomem; @@ -3971,8 +4079,8 @@ sctp_disposition_t sctp_sf_do_9_2_shutdo void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *chunk = (sctp_chunk_t *) arg; - sctp_chunk_t *reply; + struct sctp_chunk *chunk = (struct sctp_chunk *) arg; + struct sctp_chunk *reply; /* If it has no more outstanding DATA chunks, the SHUTDOWN receiver * shall send a SHUTDOWN ACK ... @@ -4051,7 +4159,7 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx( { struct sctp_transport *transport = arg; - if (asoc->overall_error_count >= asoc->overall_error_threshold) { + if (asoc->overall_error_count >= asoc->max_retrans) { /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -4152,8 +4260,8 @@ sctp_disposition_t sctp_sf_t1_timer_expi void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *repl; - sctp_bind_addr_t *bp; + struct sctp_chunk *repl; + struct sctp_bind_addr *bp; sctp_event_timeout_t timer = (sctp_event_timeout_t) arg; int timeout; int attempts; @@ -4168,7 +4276,7 @@ sctp_disposition_t sctp_sf_t1_timer_expi (attempts < asoc->max_init_attempts)) { switch (timer) { case SCTP_EVENT_TIMEOUT_T1_INIT: - bp = (sctp_bind_addr_t *) &asoc->base.bind_addr; + bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); break; @@ -4219,10 +4327,10 @@ sctp_disposition_t sctp_sf_t2_timer_expi void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *reply = NULL; + struct sctp_chunk *reply = NULL; SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); - if (asoc->overall_error_count >= asoc->overall_error_threshold) { + if (asoc->overall_error_count >= asoc->max_retrans) { /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -4233,7 +4341,7 @@ sctp_disposition_t sctp_sf_t2_timer_expi switch (asoc->state) { case SCTP_STATE_SHUTDOWN_SENT: - reply = sctp_make_shutdown(asoc); + reply = sctp_make_shutdown(asoc, NULL); break; case SCTP_STATE_SHUTDOWN_ACK_SENT: @@ -4267,6 +4375,69 @@ nomem: return SCTP_DISPOSITION_NOMEM; } +/* + * ADDIP Section 4.1 ASCONF CHunk Procedures + * If the T4 RTO timer expires the endpoint should do B1 to B5 + */ +sctp_disposition_t sctp_sf_t4_timer_expire( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + struct sctp_chunk *chunk = asoc->addip_last_asconf; + struct sctp_transport *transport = chunk->transport; + + /* ADDIP 4.1 B1) Increment the error counters and perform path failure + * detection on the appropriate destination address as defined in + * RFC2960 [5] section 8.1 and 8.2. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); + + /* Reconfig T4 timer and transport. */ + sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); + + /* ADDIP 4.1 B2) Increment the association error counters and perform + * endpoint failure detection on the association as defined in + * RFC2960 [5] section 8.1 and 8.2. + * association error counter is incremented in SCTP_CMD_STRIKE. + */ + if (asoc->overall_error_count >= asoc->max_retrans) { + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_INC_STATS(SctpAborteds); + SCTP_INC_STATS(SctpCurrEstab); + return SCTP_DISPOSITION_ABORT; + } + + /* ADDIP 4.1 B3) Back-off the destination address RTO value to which + * the ASCONF chunk was sent by doubling the RTO timer value. + * This is done in SCTP_CMD_STRIKE. + */ + + /* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible + * choose an alternate destination address (please refer to RFC2960 + * [5] section 6.4.1). An endpoint MUST NOT add new parameters to this + * chunk, it MUST be the same (including its serial number) as the last + * ASCONF sent. + */ + sctp_chunk_hold(asoc->addip_last_asconf); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(asoc->addip_last_asconf)); + + /* ADDIP 4.1 B5) Restart the T-4 RTO timer. Note that if a different + * destination is selected, then the RTO used will be that of the new + * destination address. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + + return SCTP_DISPOSITION_CONSUME; +} + /* sctpimpguide-05 Section 2.12.2 * The sender of the SHUTDOWN MAY also start an overall guard timer * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. @@ -4279,7 +4450,7 @@ sctp_disposition_t sctp_sf_t5_timer_expi void *arg, sctp_cmd_seq_t *commands) { - sctp_chunk_t *reply = NULL; + struct sctp_chunk *reply = NULL; SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); @@ -4399,22 +4570,27 @@ sctp_disposition_t sctp_sf_timer_ignore( ********************************************************************/ /* Pull the SACK chunk based on the SACK header. */ -sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *chunk) +struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk) { - sctp_sackhdr_t *sack; + struct sctp_sackhdr *sack; + unsigned int len; __u16 num_blocks; __u16 num_dup_tsns; - /* FIXME: Protect ourselves from reading too far into + /* Protect ourselves from reading too far into * the skb from a bogus sender. */ - sack = (sctp_sackhdr_t *) chunk->skb->data; - skb_pull(chunk->skb, sizeof(sctp_sackhdr_t)); + sack = (struct sctp_sackhdr *) chunk->skb->data; num_blocks = ntohs(sack->num_gap_ack_blocks); num_dup_tsns = ntohs(sack->num_dup_tsns); + len = sizeof(struct sctp_sackhdr); + len = (num_blocks + num_dup_tsns) * sizeof(__u32); + if (len > chunk->skb->len) + return NULL; + + skb_pull(chunk->skb, len); - skb_pull(chunk->skb, (num_blocks + num_dup_tsns) * sizeof(__u32)); return sack; } @@ -4423,12 +4599,12 @@ sctp_sackhdr_t *sctp_sm_pull_sack(sctp_c */ struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, const struct sctp_association *asoc, - sctp_chunk_t *chunk, + struct sctp_chunk *chunk, const void *payload, size_t paylen) { struct sctp_packet *packet; - sctp_chunk_t *abort; + struct sctp_chunk *abort; packet = sctp_ootb_pkt_new(asoc, chunk); @@ -4458,7 +4634,7 @@ struct sctp_packet *sctp_abort_pkt_new(c /* Allocate a packet for responding in the OOTB conditions. */ struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc, - const sctp_chunk_t *chunk) + const struct sctp_chunk *chunk) { struct sctp_packet *packet; struct sctp_transport *transport; @@ -4476,13 +4652,21 @@ struct sctp_packet *sctp_ootb_pkt_new(co if (asoc) { vtag = asoc->peer.i.init_tag; } else { - /* Special case the INIT as there is no vtag yet. */ - if (SCTP_CID_INIT == chunk->chunk_hdr->type) { + /* Special case the INIT and stale COOKIE_ECHO as there is no + * vtag yet. + */ + switch(chunk->chunk_hdr->type) { + case SCTP_CID_INIT: + { sctp_init_chunk_t *init; + init = (sctp_init_chunk_t *)chunk->chunk_hdr; vtag = ntohl(init->init_hdr.init_tag); - } else { + break; + } + default: vtag = ntohl(chunk->sctp_hdr->vtag); + break; } } @@ -4524,15 +4708,21 @@ void sctp_ootb_pkt_free(struct sctp_pack /* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, const struct sctp_association *asoc, - const sctp_chunk_t *chunk, + const struct sctp_chunk *chunk, sctp_cmd_seq_t *commands, - sctp_chunk_t *err_chunk) + struct sctp_chunk *err_chunk) { struct sctp_packet *packet; if (err_chunk) { packet = sctp_ootb_pkt_new(asoc, chunk); if (packet) { + struct sctp_signed_cookie *cookie; + + /* Override the OOTB vtag from the cookie. */ + cookie = chunk->subh.cookie_hdr; + packet->vtag = cookie->c.peer_vtag; + /* Set the skb to the belonging sock for accounting. */ err_chunk->skb->sk = ep->base.sk; sctp_packet_append_chunk(packet, err_chunk); @@ -4540,6 +4730,6 @@ void sctp_send_stale_cookie_err(const st SCTP_PACKET(packet)); SCTP_INC_STATS(SctpOutCtrlChunks); } else - sctp_free_chunk (err_chunk); + sctp_chunk_free (err_chunk); } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sm_statetable.c linux-2.4.26-pre1/net/sctp/sm_statetable.c --- linux-2.4.25/net/sctp/sm_statetable.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/sm_statetable.c 2004-02-25 15:43:56.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * @@ -49,7 +49,7 @@ #include #include -static sctp_sm_table_entry_t bug = { +static const sctp_sm_table_entry_t bug = { .fn = sctp_sf_bug, .name = "sctp_sf_bug" }; @@ -64,9 +64,9 @@ static sctp_sm_table_entry_t bug = { } \ return &_table[event_subtype._type][(int)state]; -sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, - sctp_state_t state, - sctp_subtype_t event_subtype) +const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, + sctp_state_t state, + sctp_subtype_t event_subtype) { switch (event_type) { case SCTP_EVENT_T_CHUNK: @@ -418,7 +418,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_ev * * For base protocol (RFC 2960). */ -sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = { +const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = { TYPE_SCTP_DATA, TYPE_SCTP_INIT, TYPE_SCTP_INIT_ACK, @@ -436,53 +436,57 @@ sctp_sm_table_entry_t chunk_event_table[ TYPE_SCTP_SHUTDOWN_COMPLETE, }; /* state_fn_t chunk_event_table[][] */ -static sctp_sm_table_entry_t -chunk_event_table_asconf[SCTP_STATE_NUM_STATES] = { - /* SCTP_STATE_EMPTY */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_CLOSED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_WAIT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_ECHOED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_ESTABLISHED */ - {.fn = sctp_sf_discard_chunk, - .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"}, - /* SCTP_STATE_SHUTDOWN_PENDING */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_RECEIVED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_ACK_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, -}; /* chunk asconf */ +#define TYPE_SCTP_ASCONF { \ + /* SCTP_STATE_EMPTY */ \ + {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + /* SCTP_STATE_CLOSED */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_COOKIE_WAIT */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_ESTABLISHED */ \ + {.fn = sctp_sf_do_asconf, .name = "sctp_sf_do_asconf"}, \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ +} /* TYPE_SCTP_ASCONF */ -static sctp_sm_table_entry_t -chunk_event_table_asconf_ack[SCTP_STATE_NUM_STATES] = { - /* SCTP_STATE_EMPTY */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_CLOSED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_WAIT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_ECHOED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_ESTABLISHED */ - {.fn = sctp_sf_discard_chunk, - .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"}, - /* SCTP_STATE_SHUTDOWN_PENDING */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_RECEIVED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_ACK_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, -}; /* chunk asconf_ack */ +#define TYPE_SCTP_ASCONF_ACK { \ + /* SCTP_STATE_EMPTY */ \ + {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + /* SCTP_STATE_CLOSED */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_COOKIE_WAIT */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_ESTABLISHED */ \ + {.fn = sctp_sf_do_asconf_ack, .name = "sctp_sf_do_asconf_ack"}, \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ +} /* TYPE_SCTP_ASCONF_ACK */ + +/* The primary index for this table is the chunk type. + * The secondary index for this table is the state. + */ +const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = { + TYPE_SCTP_ASCONF, + TYPE_SCTP_ASCONF_ACK, +}; /*state_fn_t addip_chunk_event_table[][] */ -static sctp_sm_table_entry_t +static const sctp_sm_table_entry_t chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { /* SCTP_STATE_EMPTY */ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, @@ -627,16 +631,37 @@ chunk_event_table_unknown[SCTP_STATE_NUM .name = "sctp_sf_do_prm_requestheartbeat"}, \ } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ +#define TYPE_SCTP_PRIMITIVE_ASCONF { \ + /* SCTP_STATE_EMPTY */ \ + {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + /* SCTP_STATE_CLOSED */ \ + {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + /* SCTP_STATE_COOKIE_WAIT */ \ + {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + /* SCTP_STATE_ESTABLISHED */ \ + {.fn = sctp_sf_do_prm_asconf, .name = "sctp_sf_do_prm_asconf"}, \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ +} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ /* The primary index for this table is the primitive type. * The secondary index for this table is the state. */ -sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = { +const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = { TYPE_SCTP_PRIMITIVE_ASSOCIATE, TYPE_SCTP_PRIMITIVE_SHUTDOWN, TYPE_SCTP_PRIMITIVE_ABORT, TYPE_SCTP_PRIMITIVE_SEND, TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT, + TYPE_SCTP_PRIMITIVE_ASCONF, }; #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \ @@ -662,7 +687,7 @@ sctp_sm_table_entry_t primitive_event_ta {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ } -sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = { +const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = { TYPE_SCTP_OTHER_NO_PENDING_TSN, }; @@ -771,6 +796,27 @@ sctp_sm_table_entry_t other_event_table[ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ } +#define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \ + /* SCTP_STATE_EMPTY */ \ + {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + /* SCTP_STATE_CLOSED */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + /* SCTP_STATE_COOKIE_WAIT */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + /* SCTP_STATE_ESTABLISHED */ \ + {.fn = sctp_sf_t4_timer_expire, .name = "sctp_sf_t4_timer_expire"}, \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ +} + #define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \ /* SCTP_STATE_EMPTY */ \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ @@ -783,7 +829,7 @@ sctp_sm_table_entry_t other_event_table[ /* SCTP_STATE_ESTABLISHED */ \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \ /* SCTP_STATE_SHUTDOWN_SENT */ \ {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ @@ -856,34 +902,35 @@ sctp_sm_table_entry_t other_event_table[ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ } -sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = { +const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = { TYPE_SCTP_EVENT_TIMEOUT_NONE, TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE, TYPE_SCTP_EVENT_TIMEOUT_T1_INIT, TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN, TYPE_SCTP_EVENT_TIMEOUT_T3_RTX, + TYPE_SCTP_EVENT_TIMEOUT_T4_RTO, TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD, TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT, TYPE_SCTP_EVENT_TIMEOUT_SACK, TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE, }; -sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, sctp_state_t state) +const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, + sctp_state_t state) { if (state > SCTP_STATE_MAX) return &bug; - if (cid >= 0 && cid <= SCTP_CID_BASE_MAX) { + if (cid >= 0 && cid <= SCTP_CID_BASE_MAX) return &chunk_event_table[cid][state]; - } - switch (cid) { - case SCTP_CID_ASCONF: - return &chunk_event_table_asconf[state]; + if (sctp_addip_enable) { + if (cid == SCTP_CID_ASCONF) + return &addip_chunk_event_table[0][state]; - case SCTP_CID_ASCONF_ACK: - return &chunk_event_table_asconf_ack[state]; - default: - return &chunk_event_table_unknown[state]; + if (cid == SCTP_CID_ASCONF_ACK) + return &addip_chunk_event_table[1][state]; } + + return &chunk_event_table_unknown[state]; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/socket.c linux-2.4.26-pre1/net/sctp/socket.c --- linux-2.4.25/net/sctp/socket.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/socket.c 2004-02-25 15:41:41.000000000 +0000 @@ -1,6 +1,7 @@ -/* Copyright (c) 1999-2000 Cisco, Inc. +/* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2004 + * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * Copyright (c) 2001-2002 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -48,6 +49,9 @@ * Sridhar Samudrala * Inaky Perez-Gonzalez * Ardelle Fan + * Ryan Layer + * Anup Pemmaiah + * Kevin Gao * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -62,6 +66,7 @@ #include #include #include +#include #include #include @@ -82,22 +87,30 @@ /* Forward declarations for internal helper functions. */ static int sctp_writeable(struct sock *sk); static inline int sctp_wspace(struct sctp_association *asoc); -static inline void sctp_set_owner_w(sctp_chunk_t *chunk); +static inline void sctp_set_owner_w(struct sctp_chunk *chunk); static void sctp_wfree(struct sk_buff *skb); static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p, - int msg_len); + size_t msg_len); static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); +static void sctp_wait_for_close(struct sock *sk, long timeo); static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int); -static int sctp_bindx_add(struct sock *, struct sockaddr_storage *, int); -static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int); +static int sctp_bindx_add(struct sock *, struct sockaddr *, int); +static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); +static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int); +static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int); +static int sctp_send_asconf(struct sctp_association *asoc, + struct sctp_chunk *chunk); static int sctp_do_bind(struct sock *, union sctp_addr *, int); static int sctp_autobind(struct sock *sk); static void sctp_sock_migrate(struct sock *, struct sock *, struct sctp_association *, sctp_socket_type_t); static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; +extern kmem_cache_t *sctp_bucket_cachep; +extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc); + /* Look up the association by its id. If this is not a UDP-style * socket, the ID field is always ignored. */ @@ -105,32 +118,61 @@ struct sctp_association *sctp_id2assoc(s { struct sctp_association *asoc = NULL; - /* If this is not a UDP-style socket, assoc id should be - * ignored. - */ - if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) { + /* If this is not a UDP-style socket, assoc id should be ignored. */ + if (!sctp_style(sk, UDP)) { + /* Return NULL if the socket state is not ESTABLISHED. It + * could be a TCP-style listening socket or a socket which + * hasn't yet called connect() to establish an association. + */ + if (!sctp_sstate(sk, ESTABLISHED)) + return NULL; + + /* Get the first and the only association from the list. */ if (!list_empty(&sctp_sk(sk)->ep->asocs)) asoc = list_entry(sctp_sk(sk)->ep->asocs.next, struct sctp_association, asocs); return asoc; } - /* First, verify that this is a kernel address. */ - if (sctp_is_valid_kaddr((unsigned long) id)) { - struct sctp_association *temp; - - /* Verify that this _is_ an sctp_association - * data structure and if so, that the socket matches. - */ - temp = (struct sctp_association *)id; - if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) && - (temp->base.sk == sk)) - asoc = temp; - } + /* Otherwise this is a UDP-style socket. */ + asoc = (struct sctp_association *)id; + if (!sctp_assoc_valid(sk, asoc)) + return NULL; return asoc; } +/* Look up the transport from an address and an assoc id. If both address and + * id are specified, the associations matching the address and the id should be + * the same. + */ +struct sctp_transport *sctp_addr_id2transport(struct sock *sk, + struct sockaddr_storage *addr, + sctp_assoc_t id) +{ + struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; + struct sctp_transport *transport; + union sctp_addr *laddr = (union sctp_addr *)addr; + + laddr->v4.sin_port = ntohs(laddr->v4.sin_port); + addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, + (union sctp_addr *)addr, + &transport); + laddr->v4.sin_port = htons(laddr->v4.sin_port); + + if (!addr_asoc) + return NULL; + + id_asoc = sctp_id2assoc(sk, id); + if (id_asoc && (id_asoc != addr_asoc)) + return NULL; + + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), + (union sctp_addr *)addr); + + return transport; +} + /* API 3.1.2 bind() - UDP Style Syntax * The syntax of bind() is, * @@ -139,10 +181,7 @@ struct sctp_association *sctp_id2assoc(s * sd - the socket descriptor returned by socket(). * addr - the address structure (struct sockaddr_in or struct * sockaddr_in6 [RFC 2553]), - * addrlen - the size of the address structure. - * - * The caller should use struct sockaddr_storage described in RFC 2553 - * to represent addr for portability reason. + * addr_len - the size of the address structure. */ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { @@ -178,7 +217,7 @@ static struct sctp_af *sctp_sockaddr_af( return NULL; /* Does this PF support this AF? */ - if (!opt->pf->af_supported(addr->sa.sa_family)) + if (!opt->pf->af_supported(addr->sa.sa_family, opt)) return NULL; /* If we get this far, af is valid. */ @@ -195,7 +234,7 @@ SCTP_STATIC int sctp_do_bind(struct sock { struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; - sctp_bind_addr_t *bp = &ep->base.bind_addr; + struct sctp_bind_addr *bp = &ep->base.bind_addr; struct sctp_af *af; unsigned short snum; int ret = 0; @@ -243,7 +282,7 @@ SCTP_STATIC int sctp_do_bind(struct sock /* Refresh ephemeral port. */ if (!snum) - snum = (sk)->num; + snum = sk->num; /* Add the address to the bind address list. */ sctp_local_bh_disable(); @@ -260,116 +299,45 @@ SCTP_STATIC int sctp_do_bind(struct sock /* Copy back into socket for getsockname() use. */ if (!ret) { - (sk)->sport = htons((sk)->num); + sk->sport = htons(sk->num); af->to_sk_saddr(addr, sk); } return ret; } -/* API 8.1 sctp_bindx() - * - * The syntax of sctp_bindx() is, - * - * ret = sctp_bindx(int sd, - * struct sockaddr_storage *addrs, - * int addrcnt, - * int flags); - * - * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. - * If the sd is an IPv6 socket, the addresses passed can either be IPv4 - * or IPv6 addresses. - * - * A single address may be specified as INADDR_ANY or IPV6_ADDR_ANY, see - * section 3.1.2 for this usage. - * - * addrs is a pointer to an array of one or more socket addresses. Each - * address is contained in a struct sockaddr_storage, so each address is - * fixed length. The caller specifies the number of addresses in the - * array with addrcnt. - * - * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns -1, - * and sets errno to the appropriate error code. [ Editor's note: need - * to fill in all error code? ] - * - * For SCTP, the port given in each socket address must be the same, or - * sctp_bindx() will fail, setting errno to EINVAL . - * - * The flags parameter is formed from the bitwise OR of zero or - * more of the following currently defined flags: - * - * SCTP_BINDX_ADD_ADDR - * SCTP_BINDX_REM_ADDR - * - * SCTP_BIND_ADD_ADDR directs SCTP to add the given addresses to the - * association, and SCTP_BIND_REM_ADDR directs SCTP to remove the given - * addresses from the association. The two flags are mutually exclusive; - * if both are given, sctp_bindx() will fail with EINVAL. A caller may not - * remove all addresses from an association; sctp_bindx() will reject such - * an attempt with EINVAL. - * - * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate - * additional addresses with an endpoint after calling bind(). Or use - * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening - * socket is associated with so that no new association accepted will be - * associated with those addresses. - * - * SCTP_BIND_ADD_ADDR is defined as 0, so that it becomes the default - * behavior for sctp_bindx() when no flags are given. - * - * Adding and removing addresses from a connected association is optional - * functionality. Implementations that do not support this functionality - * should return EOPNOTSUPP. - * - * NOTE: This could be integrated into sctp_setsockopt_bindx(), - * but keeping it this way makes it easier if sometime sys_bindx is - * added. - */ - -/* Unprotected by locks. Call only with socket lock sk->lock held! See - * sctp_bindx() for a lock-protected call. - */ - -static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, - int addrcnt, int flags) -{ - int retval = 0; - - SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, " - "flags: %s)\n", sk, addrs, addrcnt, - (BINDX_ADD_ADDR == flags) ? "ADD" : - ((BINDX_REM_ADDR == flags) ? "REM" : "BOGUS")); - - switch (flags) { - case BINDX_ADD_ADDR: - retval = sctp_bindx_add(sk, addrs, addrcnt); - break; - - case BINDX_REM_ADDR: - retval = sctp_bindx_rem(sk, addrs, addrcnt); - break; - - default: - retval = -EINVAL; - break; - }; - - return retval; -} - -/* BINDX with locks. + /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks * - * NOTE: Currently unused at all ... - */ -int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, - int flags) -{ - int retval; - - sctp_lock_sock(sk); - retval = __sctp_bindx(sk, addrs, addrcnt, flags); - sctp_release_sock(sk); + * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged + * at any one time. If a sender, after sending an ASCONF chunk, decides + * it needs to transfer another ASCONF Chunk, it MUST wait until the + * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a + * subsequent ASCONF. Note this restriction binds each side, so at any + * time two ASCONF may be in-transit on any given association (one sent + * from each endpoint). + */ +static int sctp_send_asconf(struct sctp_association *asoc, + struct sctp_chunk *chunk) +{ + int retval = 0; + + /* If there is an outstanding ASCONF chunk, queue it for later + * transmission. + */ + if (asoc->addip_last_asconf) { + __skb_queue_tail(&asoc->addip_chunks, (struct sk_buff *)chunk); + goto out; + } + + /* Hold the chunk until an ASCONF_ACK is received. */ + sctp_chunk_hold(chunk); + retval = sctp_primitive_ASCONF(asoc, chunk); + if (retval) + sctp_chunk_free(chunk); + else + asoc->addip_last_asconf = chunk; +out: return retval; } @@ -383,88 +351,147 @@ int sctp_bindx(struct sock *sk, struct s * If any of them fails, then the operation will be reversed and the * ones that were added will be removed. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) { int cnt; int retval = 0; - int addr_len; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { /* The list may contain either IPv4 or IPv6 address; * determine the address length for walking thru the list. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - addr_len = sizeof(struct sockaddr_in); - break; - - case AF_INET6: - addr_len = sizeof(struct sockaddr_in6); - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_add; - }; + } - retval = sctp_do_bind(sk, (union sctp_addr *)&addrs[cnt], - addr_len); + retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, + af->sockaddr_len); + + addr_buf += af->sockaddr_len; err_bindx_add: if (retval < 0) { - /* Failed. Cleanup the ones that has been added */ + /* Failed. Cleanup the ones that have been added */ if (cnt > 0) sctp_bindx_rem(sk, addrs, cnt); return retval; } } - /* Notify the peer(s), assuming we have (an) association(s). - * FIXME: for UDP, we have a 1-1-many mapping amongst sk, ep and asoc, - * so we don't have to do much work on locating associations. - * - * However, when the separation of ep and asoc kicks in, especially - * for TCP style connection, it becomes n-1-n mapping. We will need - * to do more fine work. Until then, hold my peace. - * --xguo - * - * Really, I don't think that will be a problem. The bind() - * call on a socket will either know the endpoint - * (e.g. TCP-style listen()ing socket, or UDP-style socket), - * or exactly one association. The former case is EXACTLY - * what we have now. In the former case we know the - * association already. --piggy - * - * This code will be working on either a UDP style or a TCP style - * socket, or say either an endpoint or an association. The socket - * type verification code need to be added later before calling the - * ADDIP code. - * --daisy - */ + return retval; +} -#if CONFIG_IP_SCTP_ADDIP - /* Add these addresses to all associations on this endpoint. */ - if (retval >= 0) { - struct list_head *pos; - struct sctp_endpoint *ep; - struct sctp_association *asoc; - ep = sctp_sk(sk)->ep; +/* Send an ASCONF chunk with Add IP address parameters to all the peers of the + * associations that are part of the endpoint indicating that a list of local + * addresses are added to the endpoint. + * + * If any of the addresses is already in the bind address list of the + * association, we do not send the chunk for that association. But it will not + * affect other associations. + * + * Only sctp_setsockopt_bindx() is supposed to call this function. + */ +static int sctp_send_asconf_add_ip(struct sock *sk, + struct sockaddr *addrs, + int addrcnt) +{ + struct sctp_opt *sp; + struct sctp_endpoint *ep; + struct sctp_association *asoc; + struct sctp_bind_addr *bp; + struct sctp_chunk *chunk; + struct sctp_sockaddr_entry *laddr; + union sctp_addr *addr; + void *addr_buf; + struct sctp_af *af; + struct list_head *pos; + struct list_head *p; + int i; + int retval = 0; + + if (!sctp_addip_enable) + return retval; + + sp = sctp_sk(sk); + ep = sp->ep; + + SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n", + __FUNCTION__, sk, addrs, addrcnt); + + list_for_each(pos, &ep->asocs) { + asoc = list_entry(pos, struct sctp_association, asocs); - list_for_each(pos, &ep->asocs) { - asoc = list_entry(pos, struct sctp_association, asocs); + if (!asoc->peer.asconf_capable) + continue; + + if (asoc->peer.addip_disabled_mask & SCTP_PARAM_ADD_IP) + continue; - sctp_addip_addr_config(asoc, - SCTP_PARAM_ADD_IP, - addrs, addrcnt); + if (!sctp_state(asoc, ESTABLISHED)) + continue; + + /* Check if any address in the packed array of addresses is + * in the bind address list of the association. If so, + * do not send the asconf chunk to its peer, but continue with + * other associations. + */ + addr_buf = addrs; + for (i = 0; i < addrcnt; i++) { + addr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(addr->v4.sin_family); + if (!af) { + retval = -EINVAL; + goto out; + } + + if (sctp_assoc_lookup_laddr(asoc, addr)) + break; + + addr_buf += af->sockaddr_len; } + if (i < addrcnt) + continue; + + /* Use the first address in bind addr list of association as + * Address Parameter of ASCONF CHUNK. + */ + sctp_read_lock(&asoc->base.addr_lock); + bp = &asoc->base.bind_addr; + p = bp->address_list.next; + laddr = list_entry(p, struct sctp_sockaddr_entry, list); + sctp_read_unlock(&asoc->base.addr_lock); + + chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs, + addrcnt, SCTP_PARAM_ADD_IP); + if (!chunk) { + retval = -ENOMEM; + goto out; + } + + retval = sctp_send_asconf(asoc, chunk); + + /* FIXME: After sending the add address ASCONF chunk, we + * cannot append the address to the association's binding + * address list, because the new address may be used as the + * source of a message sent to the peer before the ASCONF + * chunk is received by the peer. So we should wait until + * ASCONF_ACK is received. + */ } -#endif +out: return retval; } @@ -481,63 +508,54 @@ err_bindx_add: * At least one address has to be left; if only one address is * available, the operation will return -EBUSY. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) { struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; int cnt; - sctp_bind_addr_t *bp = &ep->base.bind_addr; + struct sctp_bind_addr *bp = &ep->base.bind_addr; int retval = 0; union sctp_addr saveaddr; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { - /* If there is only one bind address, there is nothing more - * to be removed (we need at least one address here). + /* If the bind address list is empty or if there is only one + * bind address, there is nothing more to be removed (we need + * at least one address here). */ - if (list_empty(&bp->address_list)) { + if (list_empty(&bp->address_list) || + (sctp_list_single_entry(&bp->address_list))) { retval = -EBUSY; goto err_bindx_rem; } /* The list may contain either IPv4 or IPv6 address; - * determine the address length for walking thru the list. + * determine the address length to copy the address to + * saveaddr. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); - /* Verify the port. */ - if (saveaddr.v4.sin_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - case AF_INET6: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v6.sin6_port = - ntohs(saveaddr.v6.sin6_port); - /* verify the port */ - if (saveaddr.v6.sin6_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_rem; - }; + } + memcpy(&saveaddr, sa_addr, af->sockaddr_len); + saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); + if (saveaddr.v4.sin_port != bp->port) { + retval = -EINVAL; + goto err_bindx_rem; + } - /* FIXME - There is probably a need to check if sk->saddr and - * sk->rcv_addr are currently set to one of the addresses to + /* FIXME - There is probably a need to check if sk->sk_saddr and + * sk->sk_rcv_addr are currently set to one of the addresses to * be removed. This is something which needs to be looked into * when we are fixing the outstanding issues with multi-homing * socket routing and failover schemes. Refer to comments in @@ -551,6 +569,7 @@ int sctp_bindx_rem(struct sock *sk, stru sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); + addr_buf += af->sockaddr_len; err_bindx_rem: if (retval < 0) { /* Failed. Add the ones that has been removed back */ @@ -560,43 +579,167 @@ err_bindx_rem: } } - /* - * This code will be working on either a UDP style or a TCP style - * socket, * or say either an endpoint or an association. The socket - * type verification code need to be added later before calling the - * ADDIP code. - * --daisy - */ -#if CONFIG_IP_SCTP_ADDIP - /* Remove these addresses from all associations on this endpoint. */ - if (retval >= 0) { - struct list_head *pos; - struct sctp_endpoint *ep; - struct sctp_association *asoc; + return retval; +} - ep = sctp_sk(sk)->ep; - list_for_each(pos, &ep->asocs) { - asoc = list_entry(pos, struct sctp_association, asocs); - sctp_addip_addr_config(asoc, SCTP_PARAM_DEL_IP, - addrs, addrcnt); +/* Send an ASCONF chunk with Delete IP address parameters to all the peers of + * the associations that are part of the endpoint indicating that a list of + * local addresses are removed from the endpoint. + * + * If any of the addresses is already in the bind address list of the + * association, we do not send the chunk for that association. But it will not + * affect other associations. + * + * Only sctp_setsockopt_bindx() is supposed to call this function. + */ +static int sctp_send_asconf_del_ip(struct sock *sk, + struct sockaddr *addrs, + int addrcnt) +{ + struct sctp_opt *sp; + struct sctp_endpoint *ep; + struct sctp_association *asoc; + struct sctp_bind_addr *bp; + struct sctp_chunk *chunk; + union sctp_addr *laddr; + void *addr_buf; + struct sctp_af *af; + struct list_head *pos; + int i; + int retval = 0; + + if (!sctp_addip_enable) + return retval; + + sp = sctp_sk(sk); + ep = sp->ep; + + SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n", + __FUNCTION__, sk, addrs, addrcnt); + + list_for_each(pos, &ep->asocs) { + asoc = list_entry(pos, struct sctp_association, asocs); + + if (!asoc->peer.asconf_capable) + continue; + + if (asoc->peer.addip_disabled_mask & SCTP_PARAM_DEL_IP) + continue; + + if (!sctp_state(asoc, ESTABLISHED)) + continue; + + /* Check if any address in the packed array of addresses is + * not present in the bind address list of the association. + * If so, do not send the asconf chunk to its peer, but + * continue with other associations. + */ + addr_buf = addrs; + for (i = 0; i < addrcnt; i++) { + laddr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(laddr->v4.sin_family); + if (!af) { + retval = -EINVAL; + goto out; + } + + if (!sctp_assoc_lookup_laddr(asoc, laddr)) + break; + + addr_buf += af->sockaddr_len; } + if (i < addrcnt) + continue; + + /* Find one address in the association's bind address list + * that is not in the packed array of addresses. This is to + * make sure that we do not delete all the addresses in the + * association. + */ + sctp_read_lock(&asoc->base.addr_lock); + bp = &asoc->base.bind_addr; + laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs, + addrcnt, sp); + sctp_read_unlock(&asoc->base.addr_lock); + if (!laddr) + continue; + + chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt, + SCTP_PARAM_DEL_IP); + if (!chunk) { + retval = -ENOMEM; + goto out; + } + + retval = sctp_send_asconf(asoc, chunk); + + /* FIXME: After sending the delete address ASCONF chunk, we + * cannot remove the addresses from the association's bind + * address list, because there maybe some packet send to + * the delete addresses, so we should wait until ASCONF_ACK + * packet is received. + */ } -#endif +out: return retval; } -/* Helper for tunneling sys_bindx() requests through sctp_setsockopt() +/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt() + * + * API 8.1 + * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, + * int flags); + * + * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. + * If the sd is an IPv6 socket, the addresses passed can either be IPv4 + * or IPv6 addresses. + * + * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see + * Section 3.1.2 for this usage. + * + * addrs is a pointer to an array of one or more socket addresses. Each + * address is contained in its appropriate structure (i.e. struct + * sockaddr_in or struct sockaddr_in6) the family of the address type + * must be used to distengish the address length (note that this + * representation is termed a "packed array" of addresses). The caller + * specifies the number of addresses in the array with addrcnt. + * + * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns + * -1, and sets errno to the appropriate error code. + * + * For SCTP, the port given in each socket address must be the same, or + * sctp_bindx() will fail, setting errno to EINVAL. + * + * The flags parameter is formed from the bitwise OR of zero or more of + * the following currently defined flags: + * + * SCTP_BINDX_ADD_ADDR + * + * SCTP_BINDX_REM_ADDR + * + * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the + * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given + * addresses from the association. The two flags are mutually exclusive; + * if both are given, sctp_bindx() will fail with EINVAL. A caller may + * not remove all addresses from an association; sctp_bindx() will + * reject such an attempt with EINVAL. + * + * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate + * additional addresses with an endpoint after calling bind(). Or use + * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening + * socket is associated with so that no new association accepted will be + * associated with those addresses. If the endpoint supports dynamic + * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a + * endpoint to send the appropriate message to the peer to change the + * peers address lists. + * + * Adding and removing addresses from a connected association is + * optional functionality. Implementations that do not support this + * functionality should return EOPNOTSUPP. * * Basically do nothing but copying the addresses from user to kernel - * land and invoking sctp_bindx on the sk. This is used for tunneling - * the sctp_bindx() [sys_bindx()] request through sctp_setsockopt() - * from userspace. - * - * Note I don't use move_addr_to_kernel(): the reason is we would be - * iterating over an array of struct sockaddr_storage passing always - * what we know is a good size (sizeof (struct sock...)), so it is - * pointless. Instead check the whole area for read access and copy - * it. + * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. + * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. * * We don't use copy_from_user() for optimization: we first do the * sanity checks (buffer size -fast- and access check-healthy @@ -616,38 +759,77 @@ err_bindx_rem: * * Returns 0 if ok, <0 errno code on error. */ -SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, - struct sockaddr_storage *addrs, - int addrssize, int op) +SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs, + int addrs_size, int op) { - struct sockaddr_storage *kaddrs; + struct sockaddr *kaddrs; int err; - size_t addrcnt; + int addrcnt = 0; + int walk_size = 0; + struct sockaddr *sa_addr; + void *addr_buf; + struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p" - " addrssize %d opt %d\n", sk, addrs, addrssize, op); + SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" + " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); - /* Do we have an integer number of structs sockaddr_storage? */ - if (unlikely(addrssize <= 0 || - addrssize % sizeof(struct sockaddr_storage) != 0)) + if (unlikely(addrs_size <= 0)) return -EINVAL; /* Check the user passed a healthy pointer. */ - if (unlikely(!access_ok(VERIFY_READ, addrs, addrssize))) + if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) return -EFAULT; /* Alloc space for the address array in kernel memory. */ - kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL); + kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); if (unlikely(!kaddrs)) return -ENOMEM; - if (copy_from_user(kaddrs, addrs, addrssize)) { + if (__copy_from_user(kaddrs, addrs, addrs_size)) { kfree(kaddrs); return -EFAULT; } - addrcnt = addrssize / sizeof(struct sockaddr_storage); - err = __sctp_bindx(sk, kaddrs, addrcnt, op); /* Do the work. */ + /* Walk through the addrs buffer and count the number of addresses. */ + addr_buf = kaddrs; + while (walk_size < addrs_size) { + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + + /* If the address family is not supported or if this address + * causes the address buffer to overflow return EINVAL. + */ + if (!af || (walk_size + af->sockaddr_len) > addrs_size) { + kfree(kaddrs); + return -EINVAL; + } + addrcnt++; + addr_buf += af->sockaddr_len; + walk_size += af->sockaddr_len; + } + + /* Do the work. */ + switch (op) { + case SCTP_BINDX_ADD_ADDR: + err = sctp_bindx_add(sk, kaddrs, addrcnt); + if (err) + goto out; + err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt); + break; + + case SCTP_BINDX_REM_ADDR: + err = sctp_bindx_rem(sk, kaddrs, addrcnt); + if (err) + goto out; + err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt); + break; + + default: + err = -EINVAL; + break; + }; + +out: kfree(kaddrs); return err; @@ -671,6 +853,37 @@ SCTP_STATIC int sctp_setsockopt_bindx(st * * If sd in the close() call is a branched-off socket representing only * one association, the shutdown is performed on that association only. + * + * 4.1.6 close() - TCP Style Syntax + * + * Applications use close() to gracefully close down an association. + * + * The syntax is: + * + * int close(int sd); + * + * sd - the socket descriptor of the association to be closed. + * + * After an application calls close() on a socket descriptor, no further + * socket operations will succeed on that descriptor. + * + * API 7.1.4 SO_LINGER + * + * An application using the TCP-style socket can use this option to + * perform the SCTP ABORT primitive. The linger option structure is: + * + * struct linger { + * int l_onoff; // option on/off + * int l_linger; // linger time + * }; + * + * To enable the option, set l_onoff to 1. If the l_linger value is set + * to 0, calling close() is the same as the ABORT primitive. If the + * value is set to a negative value, the setsockopt() call will return + * an error. If the value is set to a positive value linger_time, the + * close() can be blocked for at most linger_time ms. If the graceful + * shutdown phase does not finish during this period, close() will + * return but the graceful shutdown phase continues in the system. */ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) { @@ -678,10 +891,10 @@ SCTP_STATIC void sctp_close(struct sock struct sctp_association *asoc; struct list_head *pos, *temp; - SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p...)\n", sk); + SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); sctp_lock_sock(sk); - sk->shutdown = SHUTDOWN_MASK; + sk->sk_shutdown = SHUTDOWN_MASK; ep = sctp_sk(sk)->ep; @@ -689,21 +902,31 @@ SCTP_STATIC void sctp_close(struct sock list_for_each_safe(pos, temp, &ep->asocs) { asoc = list_entry(pos, struct sctp_association, asocs); - /* A closed association can still be in the list if it - * belongs to a TCP-style listening socket that is not - * yet accepted. - */ - if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) && - (SCTP_STATE_CLOSED == asoc->state)) { - sctp_unhash_established(asoc); - sctp_association_free(asoc); + if (sctp_style(sk, TCP)) { + /* A closed association can still be in the list if + * it belongs to a TCP-style listening socket that is + * not yet accepted. If so, free it. If not, send an + * ABORT or SHUTDOWN based on the linger options. + */ + if (sctp_state(asoc, CLOSED)) { + sctp_unhash_established(asoc); + sctp_association_free(asoc); + + } else if (sk->linger && !sk->sk_lingertime) + sctp_primitive_ABORT(asoc, NULL); + else + sctp_primitive_SHUTDOWN(asoc, NULL); } else sctp_primitive_SHUTDOWN(asoc, NULL); } /* Clean up any skbs sitting on the receive queue. */ - skb_queue_purge(&sk->receive_queue); - skb_queue_purge(&sctp_sk(sk)->pd_lobby); + sctp_queue_purge_ulpevents(&sk->sk_receive_queue); + sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby); + + /* On a TCP-style socket, block for at most linger_time if set. */ + if (sctp_style(sk, TCP) && timeout) + sctp_wait_for_close(sk, timeout); /* This will run the backlog queue. */ sctp_release_sock(sk); @@ -768,8 +991,8 @@ SCTP_STATIC int sctp_sendmsg(struct sock struct sctp_opt *sp; struct sctp_endpoint *ep; struct sctp_association *new_asoc=NULL, *asoc=NULL; - struct sctp_transport *transport; - sctp_chunk_t *chunk = NULL; + struct sctp_transport *transport, *chunk_tp; + struct sctp_chunk *chunk; union sctp_addr to; struct sockaddr *msg_name = NULL; struct sctp_sndrcvinfo default_sinfo = { 0 }; @@ -781,10 +1004,11 @@ SCTP_STATIC int sctp_sendmsg(struct sock sctp_scope_t scope; long timeo; __u16 sinfo_flags = 0; - struct sk_buff_head chunks; + struct sctp_datamsg *datamsg; + struct list_head *pos; int msg_flags = msg->msg_flags; - SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %d)\n", + SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %u)\n", sk, msg, msg_len); err = 0; @@ -793,8 +1017,8 @@ SCTP_STATIC int sctp_sendmsg(struct sock SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name); - if ((SCTP_SOCKET_TCP == sp->type) && - (SCTP_SS_ESTABLISHED != sk->state)) { + /* We cannot send a message over a TCP-style listening socket. */ + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { err = -EPIPE; goto out_nounlock; } @@ -812,7 +1036,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock * the address we will send to. * For a peeled-off socket, msg_name is ignored. */ - if ((SCTP_SOCKET_UDP_HIGH_BANDWIDTH != sp->type) && msg->msg_name) { + if (!sctp_style(sk, UDP_HIGH_BANDWIDTH) && msg->msg_name) { int msg_namelen = msg->msg_namelen; err = sctp_verify_addr(sk, (union sctp_addr *)msg->msg_name, @@ -840,9 +1064,15 @@ SCTP_STATIC int sctp_sendmsg(struct sock associd = sinfo->sinfo_assoc_id; } - SCTP_DEBUG_PRINTK("msg_len: %Zd, sinfo_flags: 0x%x\n", + SCTP_DEBUG_PRINTK("msg_len: %u, sinfo_flags: 0x%x\n", msg_len, sinfo_flags); + /* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */ + if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) { + err = -EINVAL; + goto out_nounlock; + } + /* If MSG_EOF is set, no data can be sent. Disallow sending zero * length messages when MSG_EOF|MSG_ABORT is not set. * If MSG_ABORT is set, the message length could be non zero with @@ -854,22 +1084,33 @@ SCTP_STATIC int sctp_sendmsg(struct sock goto out_nounlock; } - sctp_lock_sock(sk); + /* If MSG_ADDR_OVER is set, there must be an address + * specified in msg_name. + */ + if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) { + err = -EINVAL; + goto out_nounlock; + } transport = NULL; SCTP_DEBUG_PRINTK("About to look up association.\n"); + sctp_lock_sock(sk); + /* If a msg_name has been specified, assume this is to be used. */ if (msg_name) { /* Look for a matching association on the endpoint. */ asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); if (!asoc) { /* If we could not find a matching association on the - * endpoint, make sure that there is no peeled-off - * association on another socket. + * endpoint, make sure that it is not a TCP-style + * socket that already has an association or there is + * no peeled-off association on another socket. */ - if (sctp_endpoint_is_peeled_off(ep, &to)) { + if ((sctp_style(sk, TCP) && + sctp_sstate(sk, ESTABLISHED)) || + sctp_endpoint_is_peeled_off(ep, &to)) { err = -EADDRNOTAVAIL; goto out_unlock; } @@ -877,22 +1118,20 @@ SCTP_STATIC int sctp_sendmsg(struct sock } else { asoc = sctp_id2assoc(sk, associd); if (!asoc) { - err = -EINVAL; + err = -EPIPE; goto out_unlock; } } if (asoc) { - SCTP_DEBUG_PRINTK("Just looked up association: " - "%s. \n", asoc->debug_name); + SCTP_DEBUG_PRINTK("Just looked up association: %p.\n", asoc); - /* We cannot send a message on a TCP-style SCTP_SS_ESTABLISHED + /* We cannot send a message on a TCP-style SCTP_SS_ESTABLISHED * socket that has an association in CLOSED state. This can * happen when an accepted socket has an association that is - * already CLOSED. + * already CLOSED. */ - if ((SCTP_STATE_CLOSED == asoc->state) && - (SCTP_SOCKET_TCP == sp->type)) { + if (sctp_state(asoc, CLOSED) && sctp_style(sk, TCP)) { err = -EPIPE; goto out_unlock; } @@ -976,8 +1215,8 @@ SCTP_STATIC int sctp_sendmsg(struct sock = sinit->sinit_max_attempts; } if (sinit->sinit_max_init_timeo) { - asoc->max_init_timeo - = sinit->sinit_max_init_timeo * HZ; + asoc->max_init_timeo = + MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo); } } @@ -1001,11 +1240,11 @@ SCTP_STATIC int sctp_sendmsg(struct sock /* If the user didn't specify SNDRCVINFO, make up one with * some defaults. */ - default_sinfo.sinfo_stream = asoc->defaults.stream; - default_sinfo.sinfo_flags = asoc->defaults.flags; - default_sinfo.sinfo_ppid = asoc->defaults.ppid; - default_sinfo.sinfo_context = asoc->defaults.context; - default_sinfo.sinfo_timetolive = asoc->defaults.timetolive; + default_sinfo.sinfo_stream = asoc->default_stream; + default_sinfo.sinfo_flags = asoc->default_flags; + default_sinfo.sinfo_ppid = asoc->default_ppid; + default_sinfo.sinfo_context = asoc->default_context; + default_sinfo.sinfo_timetolive = asoc->default_timetolive; default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc); sinfo = &default_sinfo; } @@ -1013,7 +1252,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock /* API 7.1.7, the sndbuf size per association bounds the * maximum size of data that can be sent in a single send call. */ - if (msg_len > sk->sndbuf) { + if (msg_len > sk->sk_sndbuf) { err = -EMSGSIZE; goto out_free; } @@ -1043,64 +1282,71 @@ SCTP_STATIC int sctp_sendmsg(struct sock goto out_free; } - /* Break the message into multiple chunks of maximum size. */ - skb_queue_head_init(&chunks); - err = sctp_datachunks_from_user(asoc, sinfo, msg, msg_len, &chunks); - if (err) - goto out_free; + /* If an address is passed with the sendto/sendmsg call, it is used + * to override the primary destination address in the TCP model, or + * when MSG_ADDR_OVER flag is set in the UDP model. + */ + if ((sctp_style(sk, TCP) && msg_name) || + (sinfo_flags & MSG_ADDR_OVER)) { + chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); + if (!chunk_tp) { + err = -EINVAL; + goto out_free; + } + } else + chunk_tp = NULL; /* Auto-connect, if we aren't connected already. */ - if (SCTP_STATE_CLOSED == asoc->state) { + if (sctp_state(asoc, CLOSED)) { err = sctp_primitive_ASSOCIATE(asoc, NULL); if (err < 0) goto out_free; SCTP_DEBUG_PRINTK("We associated primitively.\n"); } + /* Break the message into multiple chunks of maximum size. */ + datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len); + if (!datamsg) { + err = -ENOMEM; + goto out_free; + } + /* Now send the (possibly) fragmented message. */ - while ((chunk = (sctp_chunk_t *)__skb_dequeue(&chunks))) { + list_for_each(pos, &datamsg->chunks) { + chunk = list_entry(pos, struct sctp_chunk, frag_list); + sctp_datamsg_track(chunk); /* Do accounting for the write space. */ sctp_set_owner_w(chunk); - /* This flag, in the UDP model, requests the SCTP stack to - * override the primary destination address with the - * address found with the sendto/sendmsg call. - */ - if (sinfo_flags & MSG_ADDR_OVER) { - if (!msg->msg_name) { - err = -EINVAL; - goto out_free; - } - chunk->transport = sctp_assoc_lookup_paddr(asoc, &to); - if (!chunk->transport) { - err = -EINVAL; - goto out_free; - } - } + chunk->transport = chunk_tp; - /* Send it to the lower layers. */ - sctp_primitive_SEND(asoc, chunk); + /* Send it to the lower layers. Note: all chunks + * must either fail or succeed. The lower layer + * works that way today. Keep it that way or this + * breaks. + */ + err = sctp_primitive_SEND(asoc, chunk); + /* Did the lower layer accept the chunk? */ + if (err) + sctp_chunk_free(chunk); SCTP_DEBUG_PRINTK("We sent primitively.\n"); } - if (!err) { + sctp_datamsg_free(datamsg); + if (err) + goto out_free; + else err = msg_len; - goto out_unlock; - } + /* If we are already past ASSOCIATE, the lower * layers are responsible for association cleanup. */ - goto out_free_chunk; + goto out_unlock; out_free: if (new_asoc) sctp_association_free(asoc); - -out_free_chunk: - if (chunk) - sctp_free_chunk(chunk); - out_unlock: sctp_release_sock(sk); @@ -1190,8 +1436,7 @@ SCTP_STATIC int sctp_recvmsg(struct sock sctp_lock_sock(sk); - if ((SCTP_SOCKET_TCP == sp->type) && - (SCTP_SS_ESTABLISHED != sk->state)) { + if (sctp_style(sk, TCP) && !sctp_sstate(sk, ESTABLISHED)) { err = -ENOTCONN; goto out; } @@ -1229,7 +1474,7 @@ SCTP_STATIC int sctp_recvmsg(struct sock sctp_ulpevent_read_sndrcvinfo(event, msg); #if 0 /* FIXME: we should be calling IP/IPv6 layers. */ - if (sk->protinfo.af_inet.cmsg_flags) + if (sk->sk_protinfo.af_inet.cmsg_flags) ip_cmsg_recv(msg, skb); #endif @@ -1244,14 +1489,14 @@ SCTP_STATIC int sctp_recvmsg(struct sock if (flags & MSG_PEEK) goto out_free; sctp_skb_pull(skb, copied); - skb_queue_head(&sk->receive_queue, skb); + skb_queue_head(&sk->sk_receive_queue, skb); /* When only partial message is copied to the user, increase * rwnd by that amount. If all the data in the skb is read, - * rwnd is updated when the skb's destructor is called via - * sctp_ulpevent_free(). + * rwnd is updated when the event is freed. */ - sctp_assoc_rwnd_increase(event->event_asoc, copied); + sctp_assoc_rwnd_increase(event->sndrcvinfo.sinfo_assoc_id, + copied); goto out; } else if ((event->msg_flags & MSG_NOTIFICATION) || (event->msg_flags & MSG_EOR)) @@ -1260,12 +1505,30 @@ SCTP_STATIC int sctp_recvmsg(struct sock msg->msg_flags &= ~MSG_EOR; out_free: - sctp_ulpevent_free(event); /* Free the skb. */ + if (flags & MSG_PEEK) { + /* Release the skb reference acquired after peeking the skb in + * sctp_skb_recv_datagram(). + */ + kfree_skb(skb); + } else { + /* Free the event which includes releasing the reference to + * the owner of the skb, freeing the skb and updating the + * rwnd. + */ + sctp_ulpevent_free(event); + } out: sctp_release_sock(sk); return err; } +/* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS) + * + * This option is a on/off flag. If enabled no SCTP message + * fragmentation will be performed. Instead if a message being sent + * exceeds the current PMTU size, the message will NOT be sent and + * instead a error will be indicated to the user. + */ static int sctp_setsockopt_disable_fragments(struct sock *sk, char *optval, int optlen) { @@ -1292,13 +1555,24 @@ static int sctp_setsockopt_events(struct return 0; } +/* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE) + * + * This socket option is applicable to the UDP-style socket only. When + * set it will cause associations that are idle for more than the + * specified number of seconds to automatically close. An association + * being idle is defined an association that has NOT sent or received + * user data. The special value of '0' indicates that no automatic + * close of any associations should be performed. The option expects an + * integer defining the number of seconds of idle time before an + * association is closed. + */ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval, int optlen) { struct sctp_opt *sp = sctp_sk(sk); /* Applicable to UDP-style socket only */ - if (SCTP_SOCKET_TCP == sp->type) + if (sctp_style(sk, TCP)) return -EOPNOTSUPP; if (optlen != sizeof(int)) return -EINVAL; @@ -1309,12 +1583,41 @@ static int sctp_setsockopt_autoclose(str return 0; } +/* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS) + * + * Applications can enable or disable heartbeats for any peer address of + * an association, modify an address's heartbeat interval, force a + * heartbeat to be sent immediately, and adjust the address's maximum + * number of retransmissions sent before an address is considered + * unreachable. The following structure is used to access and modify an + * address's parameters: + * + * struct sctp_paddrparams { + * sctp_assoc_t spp_assoc_id; + * struct sockaddr_storage spp_address; + * uint32_t spp_hbinterval; + * uint16_t spp_pathmaxrxt; + * }; + * + * spp_assoc_id - (UDP style socket) This is filled in the application, + * and identifies the association for this query. + * spp_address - This specifies which address is of interest. + * spp_hbinterval - This contains the value of the heartbeat interval, + * in milliseconds. A value of 0, when modifying the + * parameter, specifies that the heartbeat on this + * address should be disabled. A value of UINT32_MAX + * (4294967295), when modifying the parameter, + * specifies that a heartbeat should be sent + * immediately to the peer address, and the current + * interval should remain unchanged. + * spp_pathmaxrxt - This contains the maximum number of + * retransmissions before this address shall be + * considered unreachable. + */ static int sctp_setsockopt_peer_addr_params(struct sock *sk, char *optval, int optlen) { struct sctp_paddrparams params; - struct sctp_association *asoc; - union sctp_addr *addr; struct sctp_transport *trans; int error; @@ -1323,15 +1626,10 @@ static int sctp_setsockopt_peer_addr_par if (copy_from_user(¶ms, optval, optlen)) return -EFAULT; - asoc = sctp_id2assoc(sk, params.spp_assoc_id); - if (!asoc) - return -EINVAL; - - addr = (union sctp_addr *) &(params.spp_address); - - trans = sctp_assoc_lookup_paddr(asoc, addr); + trans = sctp_addr_id2transport(sk, ¶ms.spp_address, + params.spp_assoc_id); if (!trans) - return -ENOENT; + return -EINVAL; /* Applications can enable or disable heartbeats for any peer address * of an association, modify an address's heartbeat interval, force a @@ -1345,7 +1643,7 @@ static int sctp_setsockopt_peer_addr_par * and the current interval should remain unchanged. */ if (0xffffffff == params.spp_hbinterval) { - error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans); + error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans); if (error) return error; } else { @@ -1355,7 +1653,8 @@ static int sctp_setsockopt_peer_addr_par */ if (params.spp_hbinterval) { trans->hb_allowed = 1; - trans->hb_interval = params.spp_hbinterval * HZ / 1000; + trans->hb_interval = + MSECS_TO_JIFFIES(params.spp_hbinterval); } else trans->hb_allowed = 0; } @@ -1368,17 +1667,41 @@ static int sctp_setsockopt_peer_addr_par return 0; } +/* 7.1.3 Initialization Parameters (SCTP_INITMSG) + * + * Applications can specify protocol parameters for the default association + * initialization. The option name argument to setsockopt() and getsockopt() + * is SCTP_INITMSG. + * + * Setting initialization parameters is effective only on an unconnected + * socket (for UDP-style sockets only future associations are effected + * by the change). With TCP-style sockets, this option is inherited by + * sockets derived from a listener socket. + */ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen) { + struct sctp_initmsg sinit; + struct sctp_opt *sp = sctp_sk(sk); + if (optlen != sizeof(struct sctp_initmsg)) return -EINVAL; - if (copy_from_user(&sctp_sk(sk)->initmsg, optval, optlen)) + if (copy_from_user(&sinit, optval, optlen)) return -EFAULT; + + if (sinit.sinit_num_ostreams) + sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams; + if (sinit.sinit_max_instreams) + sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams; + if (sinit.sinit_max_attempts) + sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts; + if (sinit.sinit_max_init_timeo) + sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo; + return 0; } /* - * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -1396,6 +1719,7 @@ static int sctp_setsockopt_default_send_ { struct sctp_sndrcvinfo info; struct sctp_association *asoc; + struct sctp_opt *sp = sctp_sk(sk); if (optlen != sizeof(struct sctp_sndrcvinfo)) return -EINVAL; @@ -1403,54 +1727,54 @@ static int sctp_setsockopt_default_send_ return -EFAULT; asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); - if (!asoc) + if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - asoc->defaults.stream = info.sinfo_stream; - asoc->defaults.flags = info.sinfo_flags; - asoc->defaults.ppid = info.sinfo_ppid; - asoc->defaults.context = info.sinfo_context; - asoc->defaults.timetolive = info.sinfo_timetolive; + if (asoc) { + asoc->default_stream = info.sinfo_stream; + asoc->default_flags = info.sinfo_flags; + asoc->default_ppid = info.sinfo_ppid; + asoc->default_context = info.sinfo_context; + asoc->default_timetolive = info.sinfo_timetolive; + } else { + sp->default_stream = info.sinfo_stream; + sp->default_flags = info.sinfo_flags; + sp->default_ppid = info.sinfo_ppid; + sp->default_context = info.sinfo_context; + sp->default_timetolive = info.sinfo_timetolive; + } + return 0; } -/* 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) +/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary. The enclosed address must be one of the * association peer's addresses. */ -static int sctp_setsockopt_peer_prim(struct sock *sk, char *optval, int optlen) +static int sctp_setsockopt_primary_addr(struct sock *sk, char *optval, + int optlen) { - struct sctp_setpeerprim prim; - struct sctp_association *asoc; - union sctp_addr *addr; + struct sctp_prim prim; struct sctp_transport *trans; - if (optlen != sizeof(struct sctp_setpeerprim)) + if (optlen != sizeof(struct sctp_prim)) return -EINVAL; - if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim))) + if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) return -EFAULT; - asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); - if (!asoc) - return -EINVAL; - - /* Find the requested address. */ - addr = (union sctp_addr *) &(prim.sspp_addr); - - trans = sctp_assoc_lookup_paddr(asoc, addr); + trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); if (!trans) - return -ENOENT; + return -EINVAL; - sctp_assoc_set_primary(asoc, trans); + sctp_assoc_set_primary(trans->asoc, trans); return 0; } /* - * * 7.1.5 SCTP_NODELAY * * Turn on/off any Nagle-like algorithm. This means that packets are @@ -1461,17 +1785,235 @@ static int sctp_setsockopt_peer_prim(str static int sctp_setsockopt_nodelay(struct sock *sk, char *optval, int optlen) { - __u8 val; + int val; - if (optlen < sizeof(__u8)) + if (optlen < sizeof(int)) return -EINVAL; - if (get_user(val, (__u8 *)optval)) + if (get_user(val, (int *)optval)) return -EFAULT; sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1; return 0; } +/* + * + * 7.1.1 SCTP_RTOINFO + * + * The protocol parameters used to initialize and bound retransmission + * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access + * and modify these parameters. + * All parameters are time values, in milliseconds. A value of 0, when + * modifying the parameters, indicates that the current value should not + * be changed. + * + */ +static int sctp_setsockopt_rtoinfo(struct sock *sk, char *optval, int optlen) { + struct sctp_rtoinfo rtoinfo; + struct sctp_association *asoc; + + if (optlen != sizeof (struct sctp_rtoinfo)) + return -EINVAL; + + if (copy_from_user(&rtoinfo, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); + + /* Set the values to the specific association */ + if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) + return -EINVAL; + + if (asoc) { + if (rtoinfo.srto_initial != 0) + asoc->rto_initial = + MSECS_TO_JIFFIES(rtoinfo.srto_initial); + if (rtoinfo.srto_max != 0) + asoc->rto_max = MSECS_TO_JIFFIES(rtoinfo.srto_max); + if (rtoinfo.srto_min != 0) + asoc->rto_min = MSECS_TO_JIFFIES(rtoinfo.srto_min); + } else { + /* If there is no association or the association-id = 0 + * set the values to the endpoint. + */ + struct sctp_opt *sp = sctp_sk(sk); + + if (rtoinfo.srto_initial != 0) + sp->rtoinfo.srto_initial = rtoinfo.srto_initial; + if (rtoinfo.srto_max != 0) + sp->rtoinfo.srto_max = rtoinfo.srto_max; + if (rtoinfo.srto_min != 0) + sp->rtoinfo.srto_min = rtoinfo.srto_min; + } + + return 0; +} + +/* + * + * 7.1.2 SCTP_ASSOCINFO + * + * This option is used to tune the the maximum retransmission attempts + * of the association. + * Returns an error if the new association retransmission value is + * greater than the sum of the retransmission value of the peer. + * See [SCTP] for more information. + * + */ +static int sctp_setsockopt_associnfo(struct sock *sk, char *optval, int optlen) +{ + + struct sctp_assocparams assocparams; + struct sctp_association *asoc; + + if (optlen != sizeof(struct sctp_assocparams)) + return -EINVAL; + if (copy_from_user(&assocparams, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); + + if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP)) + return -EINVAL; + + /* Set the values to the specific association */ + if (asoc) { + if (assocparams.sasoc_asocmaxrxt != 0) + asoc->max_retrans = assocparams.sasoc_asocmaxrxt; + if (assocparams.sasoc_cookie_life != 0) { + asoc->cookie_life.tv_sec = + assocparams.sasoc_cookie_life / 1000; + asoc->cookie_life.tv_usec = + (assocparams.sasoc_cookie_life % 1000) + * 1000; + } + } else { + /* Set the values to the endpoint */ + struct sctp_opt *sp = sctp_sk(sk); + + if (assocparams.sasoc_asocmaxrxt != 0) + sp->assocparams.sasoc_asocmaxrxt = + assocparams.sasoc_asocmaxrxt; + if (assocparams.sasoc_cookie_life != 0) + sp->assocparams.sasoc_cookie_life = + assocparams.sasoc_cookie_life; + } + return 0; +} + +/* + * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR) + * + * This socket option is a boolean flag which turns on or off mapped V4 + * addresses. If this option is turned on and the socket is type + * PF_INET6, then IPv4 addresses will be mapped to V6 representation. + * If this option is turned off, then no mapping will be done of V4 + * addresses and a user will receive both PF_INET6 and PF_INET type + * addresses on the socket. + */ +static int sctp_setsockopt_mappedv4(struct sock *sk, char *optval, int optlen) +{ + int val; + struct sctp_opt *sp = sctp_sk(sk); + + if (optlen < sizeof(int)) + return -EINVAL; + if (get_user(val, (int *)optval)) + return -EFAULT; + if (val) + sp->v4mapped = 1; + else + sp->v4mapped = 0; + + return 0; +} + +/* + * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) + * + * This socket option specifies the maximum size to put in any outgoing + * SCTP chunk. If a message is larger than this size it will be + * fragmented by SCTP into the specified size. Note that the underlying + * SCTP implementation may fragment into smaller sized chunks when the + * PMTU of the underlying association is smaller than the value set by + * the user. + */ +static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen) +{ + int val; + + if (optlen < sizeof(int)) + return -EINVAL; + if (get_user(val, (int *)optval)) + return -EFAULT; + if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)) + return -EINVAL; + sctp_sk(sk)->user_frag = val; + + return 0; +} + + +/* + * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) + * + * Requests that the peer mark the enclosed address as the association + * primary. The enclosed address must be one of the association's + * locally bound addresses. The following structure is used to make a + * set primary request: + */ +static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval, + int optlen) +{ + struct sctp_opt *sp; + struct sctp_endpoint *ep; + struct sctp_association *asoc = NULL; + struct sctp_setpeerprim prim; + struct sctp_chunk *chunk; + int err; + + sp = sctp_sk(sk); + ep = sp->ep; + + if (!sctp_addip_enable) + return -EPERM; + + if (optlen != sizeof(struct sctp_setpeerprim)) + return -EINVAL; + + if (copy_from_user(&prim, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); + if (!asoc) + return -EINVAL; + + if (!asoc->peer.asconf_capable) + return -EPERM; + + if (asoc->peer.addip_disabled_mask & SCTP_PARAM_SET_PRIMARY) + return -EPERM; + + if (!sctp_state(asoc, ESTABLISHED)) + return -ENOTCONN; + + if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) + return -EADDRNOTAVAIL; + + /* Create an ASCONF chunk with SET_PRIMARY parameter */ + chunk = sctp_make_asconf_set_prim(asoc, + (union sctp_addr *)&prim.sspp_addr); + if (!chunk) + return -ENOMEM; + + err = sctp_send_asconf(asoc, chunk); + + SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); + + return err; +} + + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -1495,7 +2037,6 @@ SCTP_STATIC int sctp_setsockopt(struct s char *optval, int optlen) { int retval = 0; - char *tmp; SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p... optname: %d)\n", sk, optname); @@ -1512,41 +2053,26 @@ SCTP_STATIC int sctp_setsockopt(struct s goto out_nounlock; } - sctp_lock_sock(sk); - - switch (optname) { - case SCTP_SOCKOPT_DEBUG_NAME: - /* BUG! we don't ever seem to free this memory. --jgrimm */ - if (NULL == (tmp = kmalloc(optlen + 1, GFP_KERNEL))) { - retval = -ENOMEM; - goto out_unlock; - } - - if (copy_from_user(tmp, optval, optlen)) { - retval = -EFAULT; - goto out_unlock; - } - tmp[optlen] = '\000'; - sctp_sk(sk)->ep->debug_name = tmp; - break; + sctp_lock_sock(sk); + switch (optname) { case SCTP_SOCKOPT_BINDX_ADD: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, BINDX_ADD_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_ADD_ADDR); break; case SCTP_SOCKOPT_BINDX_REM: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, BINDX_REM_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_REM_ADDR); break; case SCTP_DISABLE_FRAGMENTS: retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); break; - case SCTP_SET_EVENTS: + case SCTP_EVENTS: retval = sctp_setsockopt_events(sk, optval, optlen); break; @@ -1554,33 +2080,43 @@ SCTP_STATIC int sctp_setsockopt(struct s retval = sctp_setsockopt_autoclose(sk, optval, optlen); break; - case SCTP_SET_PEER_ADDR_PARAMS: + case SCTP_PEER_ADDR_PARAMS: retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); break; case SCTP_INITMSG: retval = sctp_setsockopt_initmsg(sk, optval, optlen); break; - - case SCTP_SET_DEFAULT_SEND_PARAM: + case SCTP_DEFAULT_SEND_PARAM: retval = sctp_setsockopt_default_send_param(sk, optval, optlen); break; - + case SCTP_PRIMARY_ADDR: + retval = sctp_setsockopt_primary_addr(sk, optval, optlen); + break; case SCTP_SET_PEER_PRIMARY_ADDR: - retval = sctp_setsockopt_peer_prim(sk, optval, optlen); + retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen); break; - case SCTP_NODELAY: retval = sctp_setsockopt_nodelay(sk, optval, optlen); break; - + case SCTP_RTOINFO: + retval = sctp_setsockopt_rtoinfo(sk, optval, optlen); + break; + case SCTP_ASSOCINFO: + retval = sctp_setsockopt_associnfo(sk, optval, optlen); + break; + case SCTP_I_WANT_MAPPED_V4_ADDR: + retval = sctp_setsockopt_mappedv4(sk, optval, optlen); + break; + case SCTP_MAXSEG: + retval = sctp_setsockopt_maxseg(sk, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; }; -out_unlock: sctp_release_sock(sk); out_nounlock: @@ -1629,9 +2165,8 @@ SCTP_STATIC int sctp_connect(struct sock * is already connected. * It cannot be done even on a TCP-style listening socket. */ - if ((SCTP_SS_ESTABLISHED == sk->state) || - ((SCTP_SOCKET_TCP == sp->type) && - (SCTP_SS_LISTENING == sk->state))) { + if (sctp_sstate(sk, ESTABLISHED) || + (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { err = -EISCONN; goto out_unlock; } @@ -1700,11 +2235,11 @@ SCTP_STATIC int sctp_connect(struct sock } /* Initialize sk's dport and daddr for getpeername() */ - (sk)->dport = htons(asoc->peer.port); + sk->dport = htons(asoc->peer.port); af = sctp_get_af_specific(to.sa.sa_family); - af->to_sk_daddr(&to, sk); + af->to_sk_daddr(&to, sk); - timeo = sock_sndtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK); + timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); err = sctp_wait_for_connect(asoc, &timeo); out_unlock: @@ -1740,17 +2275,17 @@ SCTP_STATIC struct sock *sctp_accept(str sp = sctp_sk(sk); ep = sp->ep; - if (SCTP_SOCKET_TCP != sp->type) { + if (!sctp_style(sk, TCP)) { error = -EOPNOTSUPP; goto out; } - if (SCTP_SS_LISTENING != sk->state) { + if (!sctp_sstate(sk, LISTENING)) { error = -EINVAL; goto out; } - timeo = sock_rcvtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK); + timeo = sock_rcvtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); error = sctp_wait_for_accept(sk, timeo); if (error) @@ -1791,17 +2326,14 @@ SCTP_STATIC int sctp_ioctl(struct sock * SCTP_STATIC int sctp_init_sock(struct sock *sk) { struct sctp_endpoint *ep; - struct sctp_protocol *proto; struct sctp_opt *sp; SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk); - proto = sctp_get_protocol(); - sp = sctp_sk(sk); /* Initialize the SCTP per socket area. */ - switch (sk->type) { + switch (sk->sk_type) { case SOCK_SEQPACKET: sp->type = SCTP_SOCKET_UDP; break; @@ -1812,45 +2344,51 @@ SCTP_STATIC int sctp_init_sock(struct so return -ESOCKTNOSUPPORT; } - /* FIXME: The next draft (04) of the SCTP Sockets Extensions - * should include a socket option for manipulating these - * message parameters (and a few others). + /* Initialize default send parameters. These parameters can be + * modified with the SCTP_DEFAULT_SEND_PARAM socket option. */ sp->default_stream = 0; sp->default_ppid = 0; + sp->default_flags = 0; + sp->default_context = 0; + sp->default_timetolive = 0; /* Initialize default setup parameters. These parameters * can be modified with the SCTP_INITMSG socket option or * overridden by the SCTP_INIT CMSG. */ - sp->initmsg.sinit_num_ostreams = proto->max_outstreams; - sp->initmsg.sinit_max_instreams = proto->max_instreams; - sp->initmsg.sinit_max_attempts = proto->max_retrans_init; - sp->initmsg.sinit_max_init_timeo = proto->rto_max / HZ; + sp->initmsg.sinit_num_ostreams = sctp_max_outstreams; + sp->initmsg.sinit_max_instreams = sctp_max_instreams; + sp->initmsg.sinit_max_attempts = sctp_max_retrans_init; + sp->initmsg.sinit_max_init_timeo = JIFFIES_TO_MSECS(sctp_rto_max); /* Initialize default RTO related parameters. These parameters can * be modified for with the SCTP_RTOINFO socket option. - * FIXME: These are not used yet. */ - sp->rtoinfo.srto_initial = proto->rto_initial; - sp->rtoinfo.srto_max = proto->rto_max; - sp->rtoinfo.srto_min = proto->rto_min; - - /* Initialize default event subscriptions. - * the struct sock is initialized to zero, so only - * enable the events needed. By default, UDP-style - * sockets enable io and association change notifications. - */ - if (SCTP_SOCKET_UDP == sp->type) { - sp->subscribe.sctp_data_io_event = 1; - sp->subscribe.sctp_association_event = 1; - } + sp->rtoinfo.srto_initial = JIFFIES_TO_MSECS(sctp_rto_initial); + sp->rtoinfo.srto_max = JIFFIES_TO_MSECS(sctp_rto_max); + sp->rtoinfo.srto_min = JIFFIES_TO_MSECS(sctp_rto_min); + + /* Initialize default association related parameters. These parameters + * can be modified with the SCTP_ASSOCINFO socket option. + */ + sp->assocparams.sasoc_asocmaxrxt = sctp_max_retrans_association; + sp->assocparams.sasoc_number_peer_destinations = 0; + sp->assocparams.sasoc_peer_rwnd = 0; + sp->assocparams.sasoc_local_rwnd = 0; + sp->assocparams.sasoc_cookie_life = + JIFFIES_TO_MSECS(sctp_valid_cookie_life); + + /* Initialize default event subscriptions. By default, all the + * options are off. + */ + memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe)); /* Default Peer Address Parameters. These defaults can - * be modified via SCTP_SET_PEER_ADDR_PARAMS + * be modified via SCTP_PEER_ADDR_PARAMS */ - sp->paddrparam.spp_hbinterval = proto->hb_interval / HZ; - sp->paddrparam.spp_pathmaxrxt = proto->max_retrans_path; + sp->paddrparam.spp_hbinterval = JIFFIES_TO_MSECS(sctp_hb_interval); + sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path; /* If enabled no SCTP message fragmentation will be performed. * Configure through SCTP_DISABLE_FRAGMENTS socket option. @@ -1860,13 +2398,20 @@ SCTP_STATIC int sctp_init_sock(struct so /* Turn on/off any Nagle-like algorithm. */ sp->nodelay = 1; + /* Enable by default. */ + sp->v4mapped = 1; + /* Auto-close idle associations after the configured * number of seconds. A value of 0 disables this * feature. Configure through the SCTP_AUTOCLOSE socket option, * for UDP-style sockets only. */ sp->autoclose = 0; - sp->pf = sctp_get_pf_specific(sk->family); + + /* User specified fragmentation limit. */ + sp->user_frag = 0; + + sp->pf = sctp_get_pf_specific(sk->sk_family); /* Control variables for partial data delivery. */ sp->pd_mode = 0; @@ -1922,7 +2467,7 @@ SCTP_STATIC void sctp_shutdown(struct so struct sctp_endpoint *ep; struct sctp_association *asoc; - if (SCTP_SOCKET_TCP != sctp_sk(sk)->type) + if (!sctp_style(sk, TCP)) return; if (how & SEND_SHUTDOWN) { @@ -1974,17 +2519,25 @@ static int sctp_getsockopt_sctp_status(s status.sstat_state = asoc->state; status.sstat_rwnd = asoc->peer.rwnd; status.sstat_unackdata = asoc->unack_data; - status.sstat_penddata = asoc->peer.tsn_map.pending_data; + + status.sstat_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map); status.sstat_instrms = asoc->c.sinit_max_instreams; status.sstat_outstrms = asoc->c.sinit_num_ostreams; + /* Just in time frag_point update. */ + if (sctp_sk(sk)->user_frag) + asoc->frag_point + = min_t(int, asoc->frag_point, sctp_sk(sk)->user_frag); status.sstat_fragmentation_point = asoc->frag_point; status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); memcpy(&status.sstat_primary.spinfo_address, &(transport->ipaddr), sizeof(union sctp_addr)); + /* Map ipv4 address into v4-mapped-on-v6 address. */ + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), + (union sctp_addr *)&status.sstat_primary.spinfo_address); status.sstat_primary.spinfo_state = transport->active; status.sstat_primary.spinfo_cwnd = transport->cwnd; status.sstat_primary.spinfo_srtt = transport->srtt; - status.sstat_primary.spinfo_rto = transport->rto; + status.sstat_primary.spinfo_rto = JIFFIES_TO_MSECS(transport->rto); status.sstat_primary.spinfo_mtu = transport->pmtu; if (put_user(len, optlen)) { @@ -2005,6 +2558,64 @@ out: return (retval); } + +/* 7.2.2 Peer Address Information (SCTP_GET_PEER_ADDR_INFO) + * + * Applications can retrieve information about a specific peer address + * of an association, including its reachability state, congestion + * window, and retransmission timer values. This information is + * read-only. + */ +static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, + char *optval, int *optlen) +{ + struct sctp_paddrinfo pinfo; + struct sctp_transport *transport; + int retval = 0; + + if (len != sizeof(pinfo)) { + retval = -EINVAL; + goto out; + } + + if (copy_from_user(&pinfo, optval, sizeof(pinfo))) { + retval = -EFAULT; + goto out; + } + + transport = sctp_addr_id2transport(sk, &pinfo.spinfo_address, + pinfo.spinfo_assoc_id); + if (!transport) + return -EINVAL; + + pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); + pinfo.spinfo_state = transport->active; + pinfo.spinfo_cwnd = transport->cwnd; + pinfo.spinfo_srtt = transport->srtt; + pinfo.spinfo_rto = JIFFIES_TO_MSECS(transport->rto); + pinfo.spinfo_mtu = transport->pmtu; + + if (put_user(len, optlen)) { + retval = -EFAULT; + goto out; + } + + if (copy_to_user(optval, &pinfo, len)) { + retval = -EFAULT; + goto out; + } + +out: + return (retval); +} + +/* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS) + * + * This option is a on/off flag. If enabled no SCTP message + * fragmentation will be performed. Instead if a message being sent + * exceeds the current PMTU size, the message will NOT be sent and + * instead a error will be indicated to the user. + */ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, char *optval, int *optlen) { @@ -2022,7 +2633,13 @@ static int sctp_getsockopt_disable_fragm return 0; } -static int sctp_getsockopt_set_events(struct sock *sk, int len, char *optval, int *optlen) +/* 7.1.15 Set notification and ancillary events (SCTP_EVENTS) + * + * This socket option is used to specify various notifications and + * ancillary data the user wishes to receive. + */ +static int sctp_getsockopt_events(struct sock *sk, int len, char *optval, + int *optlen) { if (len != sizeof(struct sctp_event_subscribe)) return -EINVAL; @@ -2031,10 +2648,21 @@ static int sctp_getsockopt_set_events(st return 0; } +/* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE) + * + * This socket option is applicable to the UDP-style socket only. When + * set it will cause associations that are idle for more than the + * specified number of seconds to automatically close. An association + * being idle is defined an association that has NOT sent or received + * user data. The special value of '0' indicates that no automatic + * close of any associations should be performed. The option expects an + * integer defining the number of seconds of idle time before an + * association is closed. + */ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int *optlen) { /* Applicable to UDP-style socket only */ - if (SCTP_SOCKET_TCP == sctp_sk(sk)->type) + if (sctp_style(sk, TCP)) return -EOPNOTSUPP; if (len != sizeof(int)) return -EINVAL; @@ -2054,11 +2682,11 @@ SCTP_STATIC int sctp_do_peeloff(struct s /* An association cannot be branched off from an already peeled-off * socket, nor is this supported for tcp style sockets. */ - if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) + if (!sctp_style(sk, UDP)) return -EINVAL; /* Create a new socket. */ - err = sock_create(sk->family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock); + err = sock_create(sk->sk_family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock); if (err < 0) return err; @@ -2114,12 +2742,41 @@ out: return retval; } +/* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS) + * + * Applications can enable or disable heartbeats for any peer address of + * an association, modify an address's heartbeat interval, force a + * heartbeat to be sent immediately, and adjust the address's maximum + * number of retransmissions sent before an address is considered + * unreachable. The following structure is used to access and modify an + * address's parameters: + * + * struct sctp_paddrparams { + * sctp_assoc_t spp_assoc_id; + * struct sockaddr_storage spp_address; + * uint32_t spp_hbinterval; + * uint16_t spp_pathmaxrxt; + * }; + * + * spp_assoc_id - (UDP style socket) This is filled in the application, + * and identifies the association for this query. + * spp_address - This specifies which address is of interest. + * spp_hbinterval - This contains the value of the heartbeat interval, + * in milliseconds. A value of 0, when modifying the + * parameter, specifies that the heartbeat on this + * address should be disabled. A value of UINT32_MAX + * (4294967295), when modifying the parameter, + * specifies that a heartbeat should be sent + * immediately to the peer address, and the current + * interval should remain unchanged. + * spp_pathmaxrxt - This contains the maximum number of + * retransmissions before this address shall be + * considered unreachable. + */ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, char *optval, int *optlen) { struct sctp_paddrparams params; - struct sctp_association *asoc; - union sctp_addr *addr; struct sctp_transport *trans; if (len != sizeof(struct sctp_paddrparams)) @@ -2127,15 +2784,10 @@ static int sctp_getsockopt_peer_addr_par if (copy_from_user(¶ms, optval, *optlen)) return -EFAULT; - asoc = sctp_id2assoc(sk, params.spp_assoc_id); - if (!asoc) - return -EINVAL; - - addr = (union sctp_addr *) &(params.spp_address); - - trans = sctp_assoc_lookup_paddr(asoc, addr); + trans = sctp_addr_id2transport(sk, ¶ms.spp_address, + params.spp_assoc_id); if (!trans) - return -ENOENT; + return -EINVAL; /* The value of the heartbeat interval, in milliseconds. A value of 0, * when modifying the parameter, specifies that the heartbeat on this @@ -2144,7 +2796,7 @@ static int sctp_getsockopt_peer_addr_par if (!trans->hb_allowed) params.spp_hbinterval = 0; else - params.spp_hbinterval = trans->hb_interval * 1000 / HZ; + params.spp_hbinterval = JIFFIES_TO_MSECS(trans->hb_interval); /* spp_pathmaxrxt contains the maximum number of retransmissions * before this address shall be considered unreachable. @@ -2153,11 +2805,24 @@ static int sctp_getsockopt_peer_addr_par if (copy_to_user(optval, ¶ms, len)) return -EFAULT; - *optlen = len; + + if (put_user(len, optlen)) + return -EFAULT; return 0; } +/* 7.1.3 Initialization Parameters (SCTP_INITMSG) + * + * Applications can specify protocol parameters for the default association + * initialization. The option name argument to setsockopt() and getsockopt() + * is SCTP_INITMSG. + * + * Setting initialization parameters is effective only on an unconnected + * socket (for UDP-style sockets only future associations are effected + * by the change). With TCP-style sockets, this option is inherited by + * sockets derived from a listener socket. + */ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *optlen) { if (len != sizeof(struct sctp_initmsg)) @@ -2168,7 +2833,7 @@ static int sctp_getsockopt_initmsg(struc } static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { sctp_assoc_t id; struct sctp_association *asoc; @@ -2181,9 +2846,7 @@ static int sctp_getsockopt_peer_addrs_nu if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) return -EFAULT; - /* - * For UDP-style sockets, id specifies the association to query. - */ + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, id); if (!asoc) return -EINVAL; @@ -2191,21 +2854,22 @@ static int sctp_getsockopt_peer_addrs_nu list_for_each(pos, &asoc->peer.transport_addr_list) { cnt ++; } - if (copy_to_user(optval, &cnt, sizeof(int))) - return -EFAULT; - return 0; + return cnt; } static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { struct sctp_association *asoc; struct list_head *pos; int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_transport *from; - struct sockaddr_storage *to; + void *to; + union sctp_addr temp; + struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2214,19 +2878,22 @@ static int sctp_getsockopt_peer_addrs(st return -EFAULT; if (getaddrs.addr_num <= 0) return -EINVAL; - /* - * For UDP-style sockets, id specifies the association to query. - */ + + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, getaddrs.assoc_id); if (!asoc) return -EINVAL; - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); - if (copy_to_user(to, &from->ipaddr, sizeof(from->ipaddr))) + memcpy(&temp, &from->ipaddr, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; + temp.v4.sin_port = htons(temp.v4.sin_port); + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen ; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2241,7 +2908,7 @@ static int sctp_getsockopt_local_addrs_n char *optval, int *optlen) { sctp_assoc_t id; - sctp_bind_addr_t *bp; + struct sctp_bind_addr *bp; struct sctp_association *asoc; struct list_head *pos; int cnt = 0; @@ -2270,22 +2937,23 @@ static int sctp_getsockopt_local_addrs_n list_for_each(pos, &bp->address_list) { cnt ++; } - if (copy_to_user(optval, &cnt, sizeof(int))) - return -EFAULT; - return 0; + return cnt; } static int sctp_getsockopt_local_addrs(struct sock *sk, int len, char *optval, int *optlen) { - sctp_bind_addr_t *bp; + struct sctp_bind_addr *bp; struct sctp_association *asoc; struct list_head *pos; int cnt = 0; struct sctp_getaddrs getaddrs; - struct sockaddr_storage_list *from; - struct sockaddr_storage *to; + struct sctp_sockaddr_entry *from; + void *to; + union sctp_addr temp; + struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2309,14 +2977,18 @@ static int sctp_getsockopt_local_addrs(s bp = &asoc->base.bind_addr; } - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &bp->address_list) { from = list_entry(pos, - struct sockaddr_storage_list, + struct sctp_sockaddr_entry, list); - if (copy_to_user(to, &from->a, sizeof(from->a))) + memcpy(&temp, &from->a, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + temp.v4.sin_port = htons(temp.v4.sin_port); + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2327,35 +2999,43 @@ static int sctp_getsockopt_local_addrs(s return 0; } -/* 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) +/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary. The enclosed address must be one of the * association peer's addresses. */ -static int sctp_getsockopt_peer_prim(struct sock *sk, int len, - char *optval, int *optlen) +static int sctp_getsockopt_primary_addr(struct sock *sk, int len, + char *optval, int *optlen) { - struct sctp_setpeerprim prim; + struct sctp_prim prim; struct sctp_association *asoc; + struct sctp_opt *sp = sctp_sk(sk); - if (len != sizeof(struct sctp_setpeerprim)) + if (len != sizeof(struct sctp_prim)) return -EINVAL; - if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim))) + if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) return -EFAULT; - asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); + asoc = sctp_id2assoc(sk, prim.ssp_assoc_id); if (!asoc) return -EINVAL; if (!asoc->peer.primary_path) return -ENOTCONN; - - memcpy(&prim.sspp_addr, &asoc->peer.primary_path->ipaddr, + + asoc->peer.primary_path->ipaddr.v4.sin_port = + htons(asoc->peer.primary_path->ipaddr.v4.sin_port); + memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, sizeof(union sctp_addr)); + asoc->peer.primary_path->ipaddr.v4.sin_port = + ntohs(asoc->peer.primary_path->ipaddr.v4.sin_port); + + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, + (union sctp_addr *)&prim.ssp_addr); - if (copy_to_user(optval, &prim, sizeof(struct sctp_setpeerprim))) + if (copy_to_user(optval, &prim, sizeof(struct sctp_prim))) return -EFAULT; return 0; @@ -2363,12 +3043,14 @@ static int sctp_getsockopt_peer_prim(str /* * - * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied * through the inclusion of ancillary data. This socket option allows * such an application to set the default sctp_sndrcvinfo structure. + + * The application that wishes to use this socket option simply passes * in to this call the sctp_sndrcvinfo structure defined in Section * 5.2.2) The input parameters accepted by this call include @@ -2383,6 +3065,7 @@ static int sctp_getsockopt_default_send_ { struct sctp_sndrcvinfo info; struct sctp_association *asoc; + struct sctp_opt *sp = sctp_sk(sk); if (len != sizeof(struct sctp_sndrcvinfo)) return -EINVAL; @@ -2390,14 +3073,22 @@ static int sctp_getsockopt_default_send_ return -EFAULT; asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); - if (!asoc) + if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - info.sinfo_stream = asoc->defaults.stream; - info.sinfo_flags = asoc->defaults.flags; - info.sinfo_ppid = asoc->defaults.ppid; - info.sinfo_context = asoc->defaults.context; - info.sinfo_timetolive = asoc->defaults.timetolive; + if (asoc) { + info.sinfo_stream = asoc->default_stream; + info.sinfo_flags = asoc->default_flags; + info.sinfo_ppid = asoc->default_ppid; + info.sinfo_context = asoc->default_context; + info.sinfo_timetolive = asoc->default_timetolive; + } else { + info.sinfo_stream = sp->default_stream; + info.sinfo_flags = sp->default_flags; + info.sinfo_ppid = sp->default_ppid; + info.sinfo_context = sp->default_context; + info.sinfo_timetolive = sp->default_timetolive; + } if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo))) return -EFAULT; @@ -2416,14 +3107,14 @@ static int sctp_getsockopt_default_send_ */ static int sctp_getsockopt_nodelay(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { - __u8 val; + int val; - if (len < sizeof(__u8)) + if (len < sizeof(int)) return -EINVAL; - len = sizeof(__u8); + len = sizeof(int); val = (sctp_sk(sk)->nodelay == 1); if (put_user(len, optlen)) return -EFAULT; @@ -2432,6 +3123,185 @@ static int sctp_getsockopt_nodelay(struc return 0; } +/* + * + * 7.1.1 SCTP_RTOINFO + * + * The protocol parameters used to initialize and bound retransmission + * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access + * and modify these parameters. + * All parameters are time values, in milliseconds. A value of 0, when + * modifying the parameters, indicates that the current value should not + * be changed. + * + */ +static int sctp_getsockopt_rtoinfo(struct sock *sk, int len, char *optval, + int *optlen) { + struct sctp_rtoinfo rtoinfo; + struct sctp_association *asoc; + + if (len != sizeof (struct sctp_rtoinfo)) + return -EINVAL; + + if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo))) + return -EFAULT; + + asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); + + if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) + return -EINVAL; + + /* Values corresponding to the specific association. */ + if (asoc) { + rtoinfo.srto_initial = JIFFIES_TO_MSECS(asoc->rto_initial); + rtoinfo.srto_max = JIFFIES_TO_MSECS(asoc->rto_max); + rtoinfo.srto_min = JIFFIES_TO_MSECS(asoc->rto_min); + } else { + /* Values corresponding to the endpoint. */ + struct sctp_opt *sp = sctp_sk(sk); + + rtoinfo.srto_initial = sp->rtoinfo.srto_initial; + rtoinfo.srto_max = sp->rtoinfo.srto_max; + rtoinfo.srto_min = sp->rtoinfo.srto_min; + } + + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, &rtoinfo, len)) + return -EFAULT; + + return 0; +} + +/* + * + * 7.1.2 SCTP_ASSOCINFO + * + * This option is used to tune the the maximum retransmission attempts + * of the association. + * Returns an error if the new association retransmission value is + * greater than the sum of the retransmission value of the peer. + * See [SCTP] for more information. + * + */ +static int sctp_getsockopt_associnfo(struct sock *sk, int len, char *optval, + int *optlen) +{ + + struct sctp_assocparams assocparams; + struct sctp_association *asoc; + struct list_head *pos; + int cnt = 0; + + if (len != sizeof (struct sctp_assocparams)) + return -EINVAL; + + if (copy_from_user(&assocparams, optval, + sizeof (struct sctp_assocparams))) + return -EFAULT; + + asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); + + if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP)) + return -EINVAL; + + /* Values correspoinding to the specific association */ + if (assocparams.sasoc_assoc_id != 0) { + assocparams.sasoc_asocmaxrxt = asoc->max_retrans; + assocparams.sasoc_peer_rwnd = asoc->peer.rwnd; + assocparams.sasoc_local_rwnd = asoc->a_rwnd; + assocparams.sasoc_cookie_life = (asoc->cookie_life.tv_sec + * 1000) + + (asoc->cookie_life.tv_usec + / 1000); + + list_for_each(pos, &asoc->peer.transport_addr_list) { + cnt ++; + } + + assocparams.sasoc_number_peer_destinations = cnt; + } else { + /* Values corresponding to the endpoint */ + struct sctp_opt *sp = sctp_sk(sk); + + assocparams.sasoc_asocmaxrxt = sp->assocparams.sasoc_asocmaxrxt; + assocparams.sasoc_peer_rwnd = sp->assocparams.sasoc_peer_rwnd; + assocparams.sasoc_local_rwnd = sp->assocparams.sasoc_local_rwnd; + assocparams.sasoc_cookie_life = + sp->assocparams.sasoc_cookie_life; + assocparams.sasoc_number_peer_destinations = + sp->assocparams. + sasoc_number_peer_destinations; + } + + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, &assocparams, len)) + return -EFAULT; + + return 0; +} + +/* + * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR) + * + * This socket option is a boolean flag which turns on or off mapped V4 + * addresses. If this option is turned on and the socket is type + * PF_INET6, then IPv4 addresses will be mapped to V6 representation. + * If this option is turned off, then no mapping will be done of V4 + * addresses and a user will receive both PF_INET6 and PF_INET type + * addresses on the socket. + */ +static int sctp_getsockopt_mappedv4(struct sock *sk, int len, + char *optval, int *optlen) +{ + int val; + struct sctp_opt *sp = sctp_sk(sk); + + if (len < sizeof(int)) + return -EINVAL; + + len = sizeof(int); + val = sp->v4mapped; + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + + return 0; +} + +/* + * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) + * + * This socket option specifies the maximum size to put in any outgoing + * SCTP chunk. If a message is larger than this size it will be + * fragmented by SCTP into the specified size. Note that the underlying + * SCTP implementation may fragment into smaller sized chunks when the + * PMTU of the underlying association is smaller than the value set by + * the user. + */ +static int sctp_getsockopt_maxseg(struct sock *sk, int len, + char *optval, int *optlen) +{ + int val; + + if (len < sizeof(int)) + return -EINVAL; + + len = sizeof(int); + + val = sctp_sk(sk)->user_frag; + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + + return 0; +} + SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { @@ -2466,8 +3336,8 @@ SCTP_STATIC int sctp_getsockopt(struct s retval = sctp_getsockopt_disable_fragments(sk, len, optval, optlen); break; - case SCTP_SET_EVENTS: - retval = sctp_getsockopt_set_events(sk, len, optval, optlen); + case SCTP_EVENTS: + retval = sctp_getsockopt_events(sk, len, optval, optlen); break; case SCTP_AUTOCLOSE: retval = sctp_getsockopt_autoclose(sk, len, optval, optlen); @@ -2475,7 +3345,7 @@ SCTP_STATIC int sctp_getsockopt(struct s case SCTP_SOCKOPT_PEELOFF: retval = sctp_getsockopt_peeloff(sk, len, optval, optlen); break; - case SCTP_GET_PEER_ADDR_PARAMS: + case SCTP_PEER_ADDR_PARAMS: retval = sctp_getsockopt_peer_addr_params(sk, len, optval, optlen); break; @@ -2498,16 +3368,32 @@ SCTP_STATIC int sctp_getsockopt(struct s retval = sctp_getsockopt_local_addrs(sk, len, optval, optlen); break; - case SCTP_SET_DEFAULT_SEND_PARAM: + case SCTP_DEFAULT_SEND_PARAM: retval = sctp_getsockopt_default_send_param(sk, len, optval, optlen); break; - case SCTP_SET_PEER_PRIMARY_ADDR: - retval = sctp_getsockopt_peer_prim(sk, len, optval, optlen); + case SCTP_PRIMARY_ADDR: + retval = sctp_getsockopt_primary_addr(sk, len, optval, optlen); break; case SCTP_NODELAY: retval = sctp_getsockopt_nodelay(sk, len, optval, optlen); break; + case SCTP_RTOINFO: + retval = sctp_getsockopt_rtoinfo(sk, len, optval, optlen); + break; + case SCTP_ASSOCINFO: + retval = sctp_getsockopt_associnfo(sk, len, optval, optlen); + break; + case SCTP_I_WANT_MAPPED_V4_ADDR: + retval = sctp_getsockopt_mappedv4(sk, len, optval, optlen); + break; + case SCTP_MAXSEG: + retval = sctp_getsockopt_maxseg(sk, len, optval, optlen); + break; + case SCTP_GET_PEER_ADDR_INFO: + retval = sctp_getsockopt_peer_addr_info(sk, len, optval, + optlen); + break; default: retval = -ENOPROTOOPT; break; @@ -2531,7 +3417,7 @@ static void sctp_unhash(struct sock *sk) * * The port hash table (contained in the 'global' SCTP protocol storage * returned by struct sctp_protocol *sctp_get_protocol()). The hash - * table is an array of 4096 lists (sctp_bind_hashbucket_t). Each + * table is an array of 4096 lists (sctp_bind_hashbucket). Each * list (the list number is the port number hashed out, so as you * would expect from a hash function, all the ports in a given list have * such a number that hashes out to the same list number; you were @@ -2539,13 +3425,13 @@ static void sctp_unhash(struct sock *sk) * link to the socket (struct sock) that uses it, the port number and * a fastreuse flag (FIXME: NPI ipg). */ -static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, - unsigned short snum); +static struct sctp_bind_bucket *sctp_bucket_create( + struct sctp_bind_hashbucket *head, unsigned short snum); + static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) { - sctp_bind_hashbucket_t *head; /* hash list */ - sctp_bind_bucket_t *pp; /* hash list port iterator */ - struct sctp_protocol *sctp = sctp_get_protocol(); + struct sctp_bind_hashbucket *head; /* hash list */ + struct sctp_bind_bucket *pp; /* hash list port iterator */ unsigned short snum; int ret; @@ -2554,14 +3440,13 @@ static long sctp_get_port_local(struct s snum = addr->v4.sin_port; SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum); - sctp_local_bh_disable(); if (snum == 0) { /* Search for an available port. * - * 'sctp->port_rover' was the last port assigned, so - * we start to search from 'sctp->port_rover + + * 'sctp_port_rover' was the last port assigned, so + * we start to search from 'sctp_port_rover + * 1'. What we do is first check if port 'rover' is * already in the hash table; if not, we use that; if * it is, we try next. @@ -2572,14 +3457,14 @@ static long sctp_get_port_local(struct s int rover; int index; - sctp_spin_lock(&sctp->port_alloc_lock); - rover = sctp->port_rover; + sctp_spin_lock(&sctp_port_alloc_lock); + rover = sctp_port_rover; do { rover++; if ((rover < low) || (rover > high)) rover = low; index = sctp_phashfn(rover); - head = &sctp->port_hashtable[index]; + head = &sctp_port_hashtable[index]; sctp_spin_lock(&head->lock); for (pp = head->chain; pp; pp = pp->next) if (pp->port == rover) @@ -2588,8 +3473,8 @@ static long sctp_get_port_local(struct s next: sctp_spin_unlock(&head->lock); } while (--remaining > 0); - sctp->port_rover = rover; - sctp_spin_unlock(&sctp->port_alloc_lock); + sctp_port_rover = rover; + sctp_spin_unlock(&sctp_port_alloc_lock); /* Exhausted local port range during search? */ ret = 1; @@ -2609,7 +3494,7 @@ static long sctp_get_port_local(struct s * to the port number (snum) - we detect that with the * port iterator, pp being NULL. */ - head = &sctp->port_hashtable[sctp_phashfn(snum)]; + head = &sctp_port_hashtable[sctp_phashfn(snum)]; sctp_spin_lock(&head->lock); for (pp = head->chain; pp; pp = pp->next) { if (pp->port == snum) @@ -2624,12 +3509,12 @@ static long sctp_get_port_local(struct s * used by other socket (pp->sk != NULL); that other * socket is going to be sk2. */ - int sk_reuse = sk->reuse; + int sk_reuse = sk->sk_reuse; struct sock *sk2 = pp->sk; SCTP_DEBUG_PRINTK("sctp_get_port() found a " "possible match\n"); - if (pp->fastreuse != 0 && sk->reuse != 0) + if (pp->fastreuse != 0 && sk->sk_reuse != 0) goto success; /* Run through the list of sockets bound to the port @@ -2646,7 +3531,7 @@ static long sctp_get_port_local(struct s struct sctp_endpoint *ep2; ep2 = sctp_sk(sk2)->ep; - if (sk_reuse && sk2->reuse) + if (sk_reuse && sk2->sk_reuse) continue; if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, @@ -2670,12 +3555,12 @@ static long sctp_get_port_local(struct s goto fail_unlock; /* In either case (hit or miss), make sure fastreuse is 1 only - * if sk->reuse is too (that is, if the caller requested + * if sk->sk_reuse is too (that is, if the caller requested * SO_REUSEADDR on this socket -sk-). */ if (!pp->sk) - pp->fastreuse = sk->reuse ? 1 : 0; - else if (pp->fastreuse && sk->reuse == 0) + pp->fastreuse = sk->sk_reuse ? 1 : 0; + else if (pp->fastreuse && sk->sk_reuse == 0) pp->fastreuse = 0; /* We are set, so fill up all the data in the hash table @@ -2717,7 +3602,7 @@ static int sctp_get_port(struct sock *sk af->from_sk(&addr, sk); addr.v4.sin_port = htons(snum); - /* Note: sk->num gets filled in if ephemeral port request. */ + /* Note: sk->sk_num gets filled in if ephemeral port request. */ ret = sctp_get_port_local(sk, &addr); return (ret ? 1 : 0); @@ -2738,12 +3623,22 @@ SCTP_STATIC int sctp_seqpacket_listen(st /* Only UDP style sockets that are not peeled off are allowed to * listen(). */ - if (SCTP_SOCKET_UDP != sp->type) + if (!sctp_style(sk, UDP)) return -EINVAL; - if (sk->state == SCTP_SS_LISTENING) - return 0; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + /* Return if we are already listening. */ + if (sctp_sstate(sk, LISTENING)) + return 0; + /* * If a bind() or sctp_bindx() is not called prior to a listen() * call that allows new associations to be accepted, the system @@ -2758,7 +3653,7 @@ SCTP_STATIC int sctp_seqpacket_listen(st if (sctp_autobind(sk)) return -EAGAIN; } - sk->state = SCTP_SS_LISTENING; + sk->sk_state = SCTP_SS_LISTENING; sctp_hash_endpoint(ep); return 0; } @@ -2774,7 +3669,16 @@ SCTP_STATIC int sctp_stream_listen(struc struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; - if (sk->state == SCTP_SS_LISTENING) + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + + if (sctp_sstate(sk, LISTENING)) return 0; /* @@ -2791,8 +3695,8 @@ SCTP_STATIC int sctp_stream_listen(struc if (sctp_autobind(sk)) return -EAGAIN; } - sk->state = SCTP_SS_LISTENING; - sk->max_ack_backlog = backlog; + sk->sk_state = SCTP_SS_LISTENING; + sk->sk_max_ack_backlog = backlog; sctp_hash_endpoint(ep); return 0; } @@ -2863,41 +3767,40 @@ cleanup: unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; + struct sctp_opt *sp = sctp_sk(sk); unsigned int mask; - poll_wait(file, sk->sleep, wait); + poll_wait(file, sk->sk_sleep, wait); + + /* A TCP-style listening socket becomes readable when the accept queue + * is not empty. + */ + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) + return (!list_empty(&sp->ep->asocs)) ? + (POLLIN | POLLRDNORM) : 0; + mask = 0; /* Is there any exceptional events? */ - if (sk->err || !skb_queue_empty(&sk->error_queue)) + if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) mask |= POLLERR; - if (sk->shutdown == SHUTDOWN_MASK) + if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; /* Is it readable? Reconsider this code with TCP-style support. */ - if (!skb_queue_empty(&sk->receive_queue) || - (sk->shutdown & RCV_SHUTDOWN)) + if (!skb_queue_empty(&sk->sk_receive_queue) || + (sk->sk_shutdown & RCV_SHUTDOWN)) mask |= POLLIN | POLLRDNORM; - /* - * FIXME: We need to set SCTP_SS_DISCONNECTING for TCP-style and - * peeled off sockets. Additionally, TCP-style needs to consider - * other establishment conditions. - */ - if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) { - /* The association is going away. */ - if (SCTP_SS_DISCONNECTING == sk->state) - mask |= POLLHUP; - /* The association is either gone or not ready. */ - if (SCTP_SS_CLOSED == sk->state) - return mask; - } + /* The association is either gone or not ready. */ + if (!sctp_style(sk, UDP) && sctp_sstate(sk, CLOSED)) + return mask; /* Is it writable? */ if (sctp_writeable(sk)) { mask |= POLLOUT | POLLWRNORM; } else { - set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); + set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); /* * Since the socket is not locked, the buffer * might be made available after the writeable check and @@ -2916,12 +3819,13 @@ unsigned int sctp_poll(struct file *file * 2nd Level Abstractions ********************************************************************/ -static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsigned short snum) +static struct sctp_bind_bucket *sctp_bucket_create( + struct sctp_bind_hashbucket *head, unsigned short snum) { - sctp_bind_bucket_t *pp; + struct sctp_bind_bucket *pp; SCTP_DEBUG_PRINTK( "sctp_bucket_create() begins, snum=%d\n", snum); - pp = kmalloc(sizeof(sctp_bind_bucket_t), GFP_ATOMIC); + pp = kmalloc(sizeof(struct sctp_bind_bucket), GFP_ATOMIC); if (pp) { pp->port = snum; pp->fastreuse = 0; @@ -2935,16 +3839,15 @@ static sctp_bind_bucket_t *sctp_bucket_c return pp; } -/* FIXME: Comments! */ +/* Release this socket's reference to a local port. */ static __inline__ void __sctp_put_port(struct sock *sk) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); - sctp_bind_hashbucket_t *head = - &sctp_proto->port_hashtable[sctp_phashfn((sk)->num)]; - sctp_bind_bucket_t *pp; + struct sctp_bind_hashbucket *head = + &sctp_port_hashtable[sctp_phashfn((sk)->num)]; + struct sctp_bind_bucket *pp; sctp_spin_lock(&head->lock); - pp = (sctp_bind_bucket_t *) sk->prev; + pp = (struct sctp_bind_bucket *) sk->prev; if (sk->bind_next) sk->bind_next->bind_pprev = sk->bind_pprev; *(sk->bind_pprev) = sk->bind_next; @@ -2981,7 +3884,7 @@ static int sctp_autobind(struct sock *sk /* Initialize a local sockaddr structure to INADDR_ANY. */ af = sctp_sk(sk)->pf->af; - port = htons((sk)->num); + port = htons(sk->num); af->inaddr_any(&autoaddr, port); return sctp_do_bind(sk, &autoaddr, af->sockaddr_len); @@ -3110,19 +4013,19 @@ static int sctp_wait_for_packet(struct s int error; DECLARE_WAITQUEUE(wait, current); + add_wait_queue_exclusive(sk->sk_sleep, &wait); __set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue_exclusive(sk->sleep, &wait); /* Socket errors? */ error = sock_error(sk); if (error) goto out; - if (!skb_queue_empty(&sk->receive_queue)) + if (!skb_queue_empty(&sk->sk_receive_queue)) goto ready; /* Socket shut down? */ - if (sk->shutdown & RCV_SHUTDOWN) + if (sk->sk_shutdown & RCV_SHUTDOWN) goto out; /* Sequenced packets can come disconnected. If so we report the @@ -3131,8 +4034,7 @@ static int sctp_wait_for_packet(struct s error = -ENOTCONN; /* Is there a good reason to think that we may receive some data? */ - if ((list_empty(&sctp_sk(sk)->ep->asocs)) && - (sk->state != SCTP_SS_LISTENING)) + if (list_empty(&sctp_sk(sk)->ep->asocs) && !sctp_sstate(sk, LISTENING)) goto out; /* Handle signals. */ @@ -3149,7 +4051,7 @@ static int sctp_wait_for_packet(struct s sctp_lock_sock(sk); ready: - remove_wait_queue(sk->sleep, &wait); + remove_wait_queue(sk->sk_sleep, &wait); __set_current_state(TASK_RUNNING); return 0; @@ -3157,7 +4059,7 @@ interrupted: error = sock_intr_errno(*timeo_p); out: - remove_wait_queue(sk->sleep, &wait); + remove_wait_queue(sk->sk_sleep, &wait); __set_current_state(TASK_RUNNING); *err = error; return error; @@ -3174,7 +4076,7 @@ static struct sk_buff *sctp_skb_recv_dat struct sk_buff *skb; long timeo; - /* Caller is allowed not to check sk->err before calling. */ + /* Caller is allowed not to check sk->sk_err before calling. */ error = sock_error(sk); if (error) goto no_packet; @@ -3195,21 +4097,21 @@ static struct sk_buff *sctp_skb_recv_dat if (flags & MSG_PEEK) { unsigned long cpu_flags; - sctp_spin_lock_irqsave(&sk->receive_queue.lock, + sctp_spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags); - skb = skb_peek(&sk->receive_queue); + skb = skb_peek(&sk->sk_receive_queue); if (skb) atomic_inc(&skb->users); - sctp_spin_unlock_irqrestore(&sk->receive_queue.lock, + sctp_spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags); } else { - skb = skb_dequeue(&sk->receive_queue); + skb = skb_dequeue(&sk->sk_receive_queue); } if (skb) return skb; - if (sk->shutdown & RCV_SHUTDOWN) + if (sk->sk_shutdown & RCV_SHUTDOWN) break; /* User doesn't want to wait. */ @@ -3237,7 +4139,7 @@ static inline int sctp_verify_addr(struc return -EINVAL; /* Is this a valid SCTP address? */ - if (!af->addr_valid(addr)) + if (!af->addr_valid(addr, sctp_sk(sk))) return -EINVAL; if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr))) @@ -3252,7 +4154,7 @@ static inline int sctp_wspace(struct sct struct sock *sk = asoc->base.sk; int amt = 0; - amt = sk->sndbuf - asoc->sndbuf_used; + amt = sk->sk_sndbuf - asoc->sndbuf_used; if (amt < 0) amt = 0; return amt; @@ -3267,7 +4169,7 @@ static inline int sctp_wspace(struct sct * destructor in the data chunk skb for the purpose of the sndbuf space * tracking. */ -static inline void sctp_set_owner_w(sctp_chunk_t *chunk) +static inline void sctp_set_owner_w(struct sctp_chunk *chunk) { struct sctp_association *asoc = chunk->asoc; struct sock *sk = asoc->base.sk; @@ -3277,32 +4179,32 @@ static inline void sctp_set_owner_w(sctp chunk->skb->destructor = sctp_wfree; /* Save the chunk pointer in skb for sctp_wfree to use later. */ - *((sctp_chunk_t **)(chunk->skb->cb)) = chunk; + *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); - sk->wmem_queued += SCTP_DATA_SNDSIZE(chunk); + sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk); } /* If sndbuf has changed, wake up per association sndbuf waiters. */ static void __sctp_write_space(struct sctp_association *asoc) { struct sock *sk = asoc->base.sk; - struct socket *sock = sk->socket; + struct socket *sock = sk->sk_socket; if ((sctp_wspace(asoc) > 0) && sock) { if (waitqueue_active(&asoc->wait)) wake_up_interruptible(&asoc->wait); if (sctp_writeable(sk)) { - if (sk->sleep && waitqueue_active(sk->sleep)) - wake_up_interruptible(sk->sleep); + if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + wake_up_interruptible(sk->sk_sleep); /* Note that we try to include the Async I/O support * here by modeling from the current TCP/UDP code. * We have not tested with it yet. */ if (sock->fasync_list && - !(sk->shutdown & SEND_SHUTDOWN)) + !(sk->sk_shutdown & SEND_SHUTDOWN)) sock_wake_async(sock, 2, POLL_OUT); } } @@ -3315,15 +4217,15 @@ static void __sctp_write_space(struct sc static void sctp_wfree(struct sk_buff *skb) { struct sctp_association *asoc; - sctp_chunk_t *chunk; + struct sctp_chunk *chunk; struct sock *sk; /* Get the saved chunk pointer. */ - chunk = *((sctp_chunk_t **)(skb->cb)); + chunk = *((struct sctp_chunk **)(skb->cb)); asoc = chunk->asoc; sk = asoc->base.sk; asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk); - sk->wmem_queued -= SCTP_DATA_SNDSIZE(chunk); + sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk); __sctp_write_space(asoc); sctp_association_put(asoc); @@ -3331,26 +4233,28 @@ static void sctp_wfree(struct sk_buff *s /* Helper function to wait for space in the sndbuf. */ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - int msg_len) + size_t msg_len) { struct sock *sk = asoc->base.sk; int err = 0; long current_timeo = *timeo_p; DECLARE_WAITQUEUE(wait, current); - SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%d\n", + SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%u\n", asoc, (long)(*timeo_p), msg_len); - /* Wait on the association specific sndbuf space. */ - add_wait_queue_exclusive(&asoc->wait, &wait); - /* Increment the association's refcnt. */ sctp_association_hold(asoc); + + /* Wait on the association specific sndbuf space. */ + add_wait_queue_exclusive(&asoc->wait, &wait); + + /* Wait on the association specific sndbuf space. */ for (;;) { - set_current_state(TASK_INTERRUPTIBLE); + __set_current_state(TASK_INTERRUPTIBLE); if (!*timeo_p) goto do_nonblock; - if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || + if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || asoc->base.dead) goto do_error; if (signal_pending(current)) @@ -3370,11 +4274,11 @@ static int sctp_wait_for_sndbuf(struct s out: remove_wait_queue(&asoc->wait, &wait); + __set_current_state(TASK_RUNNING); /* Release the association's refcnt. */ sctp_association_put(asoc); - __set_current_state(TASK_RUNNING); return err; do_error: @@ -3418,7 +4322,7 @@ static int sctp_writeable(struct sock *s { int amt = 0; - amt = sk->sndbuf - sk->wmem_queued; + amt = sk->sk_sndbuf - sk->sk_wmem_queued; if (amt < 0) amt = 0; return amt; @@ -3437,24 +4341,23 @@ static int sctp_wait_for_connect(struct SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc, (long)(*timeo_p)); - add_wait_queue_exclusive(&asoc->wait, &wait); - /* Increment the association's refcnt. */ sctp_association_hold(asoc); + add_wait_queue_exclusive(&asoc->wait, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); if (!*timeo_p) goto do_nonblock; - if (sk->shutdown & RCV_SHUTDOWN) + if (sk->sk_shutdown & RCV_SHUTDOWN) break; - if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || + if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || asoc->base.dead) goto do_error; if (signal_pending(current)) goto do_interrupted; - if (asoc->state == SCTP_STATE_ESTABLISHED) + if (sctp_state(asoc, ESTABLISHED)) break; /* Let another process have a go. Since we are going @@ -3469,12 +4372,11 @@ static int sctp_wait_for_connect(struct out: remove_wait_queue(&asoc->wait, &wait); + __set_current_state(TASK_RUNNING); /* Release the association's refcnt. */ sctp_association_put(asoc); - __set_current_state(TASK_RUNNING); - return err; do_error: @@ -3498,7 +4400,7 @@ static int sctp_wait_for_accept(struct s ep = sctp_sk(sk)->ep; - add_wait_queue_exclusive(sk->sleep, &wait); + add_wait_queue_exclusive(sk->sk_sleep, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); @@ -3509,7 +4411,7 @@ static int sctp_wait_for_accept(struct s } err = -EINVAL; - if (sk->state != SCTP_SS_LISTENING) + if (!sctp_sstate(sk, LISTENING)) break; err = 0; @@ -3525,12 +4427,31 @@ static int sctp_wait_for_accept(struct s break; } - remove_wait_queue(sk->sleep, &wait); - __set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sk_sleep, &wait); + __set_current_state(TASK_RUNNING); return err; } +void sctp_wait_for_close(struct sock *sk, long timeout) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue_exclusive(sk->sk_sleep, &wait); + + do { + __set_current_state(TASK_INTERRUPTIBLE); + if (list_empty(&sctp_sk(sk)->ep->asocs)) + break; + sctp_release_sock(sk); + timeout = schedule_timeout(timeout); + sctp_lock_sock(sk); + } while (!signal_pending(current) && timeout); + + remove_wait_queue(sk->sk_sleep, &wait); + __set_current_state(TASK_RUNNING); +} + /* Populate the fields of the newsk from the oldsk and migrate the assoc * and its messages to the newsk. */ @@ -3547,9 +4468,10 @@ static void sctp_sock_migrate(struct soc /* Migrate socket buffer sizes and all the socket level options to the * new socket. */ - newsk->sndbuf = oldsk->sndbuf; - newsk->rcvbuf = oldsk->rcvbuf; - *newsp = *oldsp; + newsk->sk_sndbuf = oldsk->sk_sndbuf; + newsk->sk_rcvbuf = oldsk->sk_rcvbuf; + /* Brute force copy old sctp opt. */ + memcpy(newsp, oldsp, sizeof(struct sctp_opt)); /* Restore the ep value that was overwritten with the above structure * copy. @@ -3557,14 +4479,16 @@ static void sctp_sock_migrate(struct soc newsp->ep = newep; newsp->hmac = NULL; + newsk->num = oldsk->num; + /* Move any messages in the old socket's receive queue that are for the * peeled off association to the new socket's receive queue. */ - sctp_skb_for_each(skb, &oldsk->receive_queue, tmp) { + sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { event = sctp_skb2event(skb); - if (event->event_asoc == assoc) { + if (event->sndrcvinfo.sinfo_assoc_id == assoc) { __skb_unlink(skb, skb->list); - __skb_queue_tail(&newsk->receive_queue, skb); + __skb_queue_tail(&newsk->sk_receive_queue, skb); } } @@ -3584,14 +4508,14 @@ static void sctp_sock_migrate(struct soc if (assoc->ulpq.pd_mode) { queue = &newsp->pd_lobby; } else - queue = &newsk->receive_queue; + queue = &newsk->sk_receive_queue; /* Walk through the pd_lobby, looking for skbs that * need moved to the new socket. */ sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { event = sctp_skb2event(skb); - if (event->event_asoc == assoc) { + if (event->sndrcvinfo.sinfo_assoc_id == assoc) { __skb_unlink(skb, skb->list); __skb_queue_tail(queue, skb); } @@ -3614,7 +4538,13 @@ static void sctp_sock_migrate(struct soc /* Migrate the association to the new socket. */ sctp_assoc_migrate(assoc, newsk); - newsk->state = SCTP_SS_ESTABLISHED; + /* If the association on the newsk is already closed before accept() + * is called, set RCV_SHUTDOWN flag. + */ + if (sctp_state(assoc, CLOSED) && sctp_style(newsk, TCP)) + newsk->sk_shutdown |= RCV_SHUTDOWN; + + newsk->sk_state = SCTP_SS_ESTABLISHED; } /* This proto struct describes the ULP interface for SCTP. */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ssnmap.c linux-2.4.26-pre1/net/sctp/ssnmap.c --- linux-2.4.25/net/sctp/ssnmap.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/ssnmap.c 2004-02-25 15:44:33.000000000 +0000 @@ -40,6 +40,7 @@ #include #include +#define MAX_KMALLOC_SIZE 131072 /* Storage size needed for map includes 2 headers and then the * specific needs of in or out streams. @@ -56,9 +57,14 @@ static inline size_t sctp_ssnmap_size(__ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp) { struct sctp_ssnmap *retval; + int size; - retval = kmalloc(sctp_ssnmap_size(in, out), gfp); - + size = sctp_ssnmap_size(in, out); + if (size <= MAX_KMALLOC_SIZE) + retval = kmalloc(size, gfp); + else + retval = (struct sctp_ssnmap *) + __get_free_pages(gfp, get_order(size)); if (!retval) goto fail; @@ -71,7 +77,10 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u1 return retval; fail_map: - kfree(retval); + if (size <= MAX_KMALLOC_SIZE) + kfree(retval); + else + free_pages((unsigned long)retval, get_order(size)); fail: return NULL; } @@ -107,7 +116,13 @@ void sctp_ssnmap_clear(struct sctp_ssnma void sctp_ssnmap_free(struct sctp_ssnmap *map) { if (map && map->malloced) { - kfree(map); + int size; + + size = sctp_ssnmap_size(map->in.len, map->out.len); + if (size <= MAX_KMALLOC_SIZE) + kfree(map); + else + free_pages((unsigned long)map, get_order(size)); SCTP_DBG_OBJCNT_DEC(ssnmap); } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/sysctl.c linux-2.4.26-pre1/net/sctp/sysctl.c --- linux-2.4.25/net/sctp/sysctl.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/sysctl.c 2004-02-25 15:41:37.000000000 +0000 @@ -1,39 +1,40 @@ -/* SCTP kernel reference Implementation +/* SCTP kernel reference Implementation * Copyright (c) 2002 International Business Machines Corp. * Copyright (c) 2002 Intel Corp. - * + * * This file is part of the SCTP kernel reference Implementation - * - * Sysctl related interfaces for SCTP. - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * + * Sysctl related interfaces for SCTP. + * + * The SCTP reference implementation is free software; + * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * Mingqin Liu * Jon Grimm * Ardelle Fan + * Ryan Layer * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -42,49 +43,59 @@ #include #include -extern struct sctp_protocol sctp_proto; +static ctl_handler sctp_sysctl_jiffies_ms; +static long rto_timer_min = 1; +static long rto_timer_max = 86400000; /* One day */ static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_RTO_INITIAL, .procname = "rto_initial", - .data = &sctp_proto.rto_initial, - .maxlen = sizeof(int), + .data = &sctp_rto_initial, + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_RTO_MIN, .procname = "rto_min", - .data = &sctp_proto.rto_min, - .maxlen = sizeof(int), + .data = &sctp_rto_min, + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_RTO_MAX, .procname = "rto_max", - .data = &sctp_proto.rto_max, - .maxlen = sizeof(int), + .data = &sctp_rto_max, + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_VALID_COOKIE_LIFE, .procname = "valid_cookie_life", - .data = &sctp_proto.valid_cookie_life, - .maxlen = sizeof(int), + .data = &sctp_valid_cookie_life, + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_MAX_BURST, .procname = "max_burst", - .data = &sctp_proto.max_burst, + .data = &sctp_max_burst, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -92,7 +103,7 @@ static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS, .procname = "association_max_retrans", - .data = &sctp_proto.max_retrans_association, + .data = &sctp_max_retrans_association, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -100,7 +111,7 @@ static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_PATH_MAX_RETRANS, .procname = "path_max_retrans", - .data = &sctp_proto.max_retrans_path, + .data = &sctp_max_retrans_path, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -108,7 +119,7 @@ static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS, .procname = "max_init_retransmits", - .data = &sctp_proto.max_retrans_init, + .data = &sctp_max_retrans_init, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -116,25 +127,29 @@ static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_HB_INTERVAL, .procname = "hb_interval", - .data = &sctp_proto.hb_interval, - .maxlen = sizeof(int), + .data = &sctp_hb_interval, + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_PRESERVE_ENABLE, .procname = "cookie_preserve_enable", - .data = &sctp_proto.cookie_preserve_enable, - .maxlen = sizeof(int), + .data = &sctp_cookie_preserve_enable, + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_RTO_ALPHA, .procname = "rto_alpha_exp_divisor", - .data = &sctp_proto.rto_alpha, + .data = &sctp_rto_alpha, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -142,7 +157,15 @@ static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_RTO_BETA, .procname = "rto_beta_exp_divisor", - .data = &sctp_proto.rto_beta, + .data = &sctp_rto_beta, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec + }, + { + .ctl_name = NET_SCTP_ADDIP_ENABLE, + .procname = "addip_enable", + .data = &sctp_addip_enable, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -154,7 +177,6 @@ static ctl_table sctp_net_table[] = { { .ctl_name = NET_SCTP, .procname = "sctp", - .maxlen = 0, .mode = 0555, .child = sctp_table }, @@ -165,7 +187,6 @@ static ctl_table sctp_root_table[] = { { .ctl_name = CTL_NET, .procname = "net", - .maxlen = 0, .mode = 0555, .child = sctp_net_table }, @@ -185,3 +206,37 @@ void sctp_sysctl_unregister(void) { unregister_sysctl_table(sctp_sysctl_header); } + +/* Strategy function to convert jiffies to milliseconds. */ +static int sctp_sysctl_jiffies_ms(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + if (oldval) { + size_t olen; + + if (oldlenp) { + if (get_user(olen, oldlenp)) + return -EFAULT; + + if (olen != sizeof (int)) + return -EINVAL; + } + if (put_user((*(int *)(table->data) * 1000) / HZ, + (int *)oldval) || + (oldlenp && put_user(sizeof (int), oldlenp))) + return -EFAULT; + } + if (newval && newlen) { + int new; + + if (newlen != sizeof (int)) + return -EINVAL; + + if (get_user(new, (int *)newval)) + return -EFAULT; + + *(int *)(table->data) = (new * HZ) / 1000; + } + return 1; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/transport.c linux-2.4.26-pre1/net/sctp/transport.c --- linux-2.4.25/net/sctp/transport.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/transport.c 2004-02-25 15:43:20.000000000 +0000 @@ -83,8 +83,6 @@ struct sctp_transport *sctp_transport_in const union sctp_addr *addr, int gfp) { - struct sctp_protocol *proto = sctp_get_protocol(); - /* Copy in the address. */ peer->ipaddr = *addr; peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); @@ -100,7 +98,7 @@ struct sctp_transport *sctp_transport_in * parameter 'RTO.Initial'. */ peer->rtt = 0; - peer->rto = proto->rto_initial; + peer->rto = sctp_rto_initial; peer->rttvar = 0; peer->srtt = 0; peer->rto_pending = 0; @@ -109,19 +107,18 @@ struct sctp_transport *sctp_transport_in peer->last_time_used = jiffies; peer->last_time_ecne_reduced = jiffies; - peer->active = 1; + peer->active = SCTP_ACTIVE; peer->hb_allowed = 0; /* Initialize the default path max_retrans. */ - peer->max_retrans = proto->max_retrans_path; + peer->max_retrans = sctp_max_retrans_path; peer->error_threshold = 0; peer->error_count = 0; - peer->debug_name = "unnamedtransport"; - INIT_LIST_HEAD(&peer->transmitted); INIT_LIST_HEAD(&peer->send_ready); INIT_LIST_HEAD(&peer->transports); + sctp_packet_init(&peer->packet, peer, 0, 0); /* Set up the retransmission timer. */ init_timer(&peer->T3_rtx_timer); @@ -138,6 +135,13 @@ struct sctp_transport *sctp_transport_in peer->dead = 0; peer->malloced = 0; + + /* Initialize the state information for SFR-CACC */ + peer->cacc.changeover_active = 0; + peer->cacc.cycling_changeover = 0; + peer->cacc.next_tsn_at_change = 0; + peer->cacc.cacc_saw_newack = 0; + return peer; } @@ -241,7 +245,7 @@ void sctp_transport_route(struct sctp_tr if (dst) { transport->pmtu = dst_pmtu(dst); - /* Initialize sk->rcv_saddr, if the transport is the + /* Initialize sk->sk_rcv_saddr, if the transport is the * association's active path for getsockname(). */ if (asoc && (transport == asoc->peer.active_path)) @@ -268,8 +272,6 @@ void sctp_transport_put(struct sctp_tran /* Update transport's RTO based on the newly calculated RTT. */ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) { - struct sctp_protocol *proto = sctp_get_protocol(); - /* Check for valid transport. */ SCTP_ASSERT(tp, "NULL transport", return); @@ -288,10 +290,10 @@ void sctp_transport_update_rto(struct sc * For example, assuming the default value of RTO.Alpha of * 1/8, rto_alpha would be expressed as 3. */ - tp->rttvar = tp->rttvar - (tp->rttvar >> proto->rto_beta) - + ((abs(tp->srtt - rtt)) >> proto->rto_beta); - tp->srtt = tp->srtt - (tp->srtt >> proto->rto_alpha) - + (rtt >> proto->rto_alpha); + tp->rttvar = tp->rttvar - (tp->rttvar >> sctp_rto_beta) + + ((abs(tp->srtt - rtt)) >> sctp_rto_beta); + tp->srtt = tp->srtt - (tp->srtt >> sctp_rto_alpha) + + (rtt >> sctp_rto_alpha); } else { /* 6.3.1 C2) When the first RTT measurement R is made, set * SRTT <- R, RTTVAR <- R/2. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/tsnmap.c linux-2.4.26-pre1/net/sctp/tsnmap.c --- linux-2.4.25/net/sctp/tsnmap.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/tsnmap.c 2004-02-25 15:41:03.000000000 +0000 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001 International Business Machines, Corp. + * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * * This file is part of the SCTP kernel reference Implementation @@ -46,7 +46,6 @@ #include static void sctp_tsnmap_update(struct sctp_tsnmap *map); -static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map); static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off, __u16 len, __u16 base, int *started, __u16 *start, @@ -92,7 +91,6 @@ struct sctp_tsnmap *sctp_tsnmap_init(str map->cumulative_tsn_ack_point = initial_tsn - 1; map->max_tsn_seen = map->cumulative_tsn_ack_point; map->malloced = 0; - map->pending_data = 0; map->num_dup_tsns = 0; return map; @@ -135,14 +133,6 @@ out: return dup; } -/* Is there a gap in the TSN map? */ -int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map) -{ - int has_gap; - - has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen); - return has_gap; -} /* Mark this TSN as seen. */ void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) @@ -176,21 +166,6 @@ void sctp_tsnmap_mark(struct sctp_tsnmap sctp_tsnmap_update(map); } -void sctp_tsnmap_report_dup(struct sctp_tsnmap *map, __u32 tsn) -{ -} - -/* Retrieve the Cumulative TSN Ack Point. */ -__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map) -{ - return map->cumulative_tsn_ack_point; -} - -/* Retrieve the highest TSN we've seen. */ -__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map) -{ - return map->max_tsn_seen; -} /* Dispose of a tsnmap. */ void sctp_tsnmap_free(struct sctp_tsnmap *map) @@ -219,6 +194,10 @@ int sctp_tsnmap_next_gap_ack(const struc /* We haven't found a gap yet. */ started = ended = 0; + /* If there are no more gap acks possible, get out fast. */ + if (TSN_lte(map->max_tsn_seen, iter->start)) + return 0; + /* Search the first mapping array. */ if (iter->start - map->base_tsn < map->len) { @@ -304,10 +283,11 @@ static void sctp_tsnmap_update(struct sc } while (map->tsn_map[ctsn - map->base_tsn]); map->cumulative_tsn_ack_point = ctsn - 1; /* Back up one. */ - sctp_tsnmap_update_pending_data(map); } -static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map) +/* How many data chunks are we missing from our peer? + */ +__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map) { __u32 cum_tsn = map->cumulative_tsn_ack_point; __u32 max_tsn = map->max_tsn_seen; @@ -339,7 +319,7 @@ static void sctp_tsnmap_update_pending_d } out: - map->pending_data = pending_data; + return pending_data; } /* This is a private helper for finding Gap Ack Blocks. It searches a @@ -359,6 +339,8 @@ static void sctp_tsnmap_find_gap_ack(__u * early if we have found the end of the Gap Ack Block. */ + /* Also, stop looking past the maximum TSN seen. */ + /* Look for the start. */ if (!(*started)) { for (; i < len; i++) { @@ -404,3 +386,26 @@ void sctp_tsnmap_renege(struct sctp_tsnm else map->overflow_map[gap - map->len] = 0; } + +/* How many gap ack blocks do we have recorded? */ +__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map) +{ + struct sctp_tsnmap_iter iter; + int gabs = 0; + + /* Refresh the gap ack information. */ + if (sctp_tsnmap_has_gap(map)) { + sctp_tsnmap_iter_init(map, &iter); + while (sctp_tsnmap_next_gap_ack(map, &iter, + &map->gabs[gabs].start, + &map->gabs[gabs].end)) { + + map->gabs[gabs].start = htons(map->gabs[gabs].start); + map->gabs[gabs].end = htons(map->gabs[gabs].end); + gabs++; + if (gabs >= SCTP_MAX_GABS) + break; + } + } + return gabs; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ulpevent.c linux-2.4.26-pre1/net/sctp/ulpevent.c --- linux-2.4.25/net/sctp/ulpevent.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/ulpevent.c 2004-02-25 15:44:07.000000000 +0000 @@ -35,6 +35,8 @@ * Written or modified by: * Jon Grimm * La Monte H.P. Yarroll + * Ardelle Fan + * Sridhar Samudrala * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -46,10 +48,12 @@ #include #include -static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, - struct sctp_association *asoc); -static void sctp_ulpevent_set_owner(struct sk_buff *skb, - const struct sctp_association *asoc); +static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, + const struct sctp_association *asoc); +static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event); +static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, + struct sctp_association *asoc); +static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); /* Create a new sctp_ulpevent. */ struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp) @@ -62,30 +66,19 @@ struct sctp_ulpevent *sctp_ulpevent_new( goto fail; event = sctp_skb2event(skb); - event = sctp_ulpevent_init(event, msg_flags); - if (!event) - goto fail_init; + sctp_ulpevent_init(event, msg_flags); + return event; -fail_init: - kfree_skb(skb); fail: return NULL; } /* Initialize an ULP event from an given skb. */ -struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *event, - int msg_flags) +void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) { memset(event, sizeof(struct sctp_ulpevent), 0x00); event->msg_flags = msg_flags; - return event; -} - -/* Dispose of an event. */ -void sctp_ulpevent_free(struct sctp_ulpevent *event) -{ - kfree_skb(sctp_event2skb(event)); } /* Is this a MSG_NOTIFICATION? */ @@ -189,7 +182,7 @@ struct sctp_ulpevent *sctp_ulpevent_mak * All notifications for a given association have the same association * identifier. For TCP style socket, this field is ignored. */ - sctp_ulpevent_set_owner(skb, asoc); + sctp_ulpevent_set_owner(event, asoc); sac->sac_assoc_id = sctp_assoc2id(asoc); return event; @@ -281,7 +274,7 @@ struct sctp_ulpevent *sctp_ulpevent_make * All notifications for a given association have the same association * identifier. For TCP style socket, this field is ignored. */ - sctp_ulpevent_set_owner(skb, asoc); + sctp_ulpevent_set_owner(event, asoc); spc->spc_assoc_id = sctp_assoc2id(asoc); /* Sockets API Extensions for SCTP @@ -294,6 +287,11 @@ struct sctp_ulpevent *sctp_ulpevent_make */ memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); + /* Map ipv4 address into v4-mapped-on-v6 address. */ + sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map( + sctp_sk(asoc->base.sk), + (union sctp_addr *)&spc->spc_aaddr); + return event; fail: @@ -316,7 +314,7 @@ fail: * error formats. */ struct sctp_ulpevent *sctp_ulpevent_make_remote_error( - const struct sctp_association *asoc, sctp_chunk_t *chunk, + const struct sctp_association *asoc, struct sctp_chunk *chunk, __u16 flags, int gfp) { struct sctp_ulpevent *event; @@ -328,7 +326,7 @@ struct sctp_ulpevent *sctp_ulpevent_make ch = (sctp_errhdr_t *)(chunk->skb->data); cause = ch->cause; - elen = ntohs(ch->length) - sizeof(sctp_errhdr_t); + elen = WORD_ROUND(ntohs(ch->length)) - sizeof(sctp_errhdr_t); /* Pull off the ERROR header. */ skb_pull(chunk->skb, sizeof(sctp_errhdr_t)); @@ -336,10 +334,8 @@ struct sctp_ulpevent *sctp_ulpevent_make /* Copy the skb to a new skb with room for us to prepend * notification with. */ - skb = skb_copy_expand(chunk->skb, - sizeof(struct sctp_remote_error), /* headroom */ - 0, /* tailroom */ - gfp); + skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_remote_error), + 0, gfp); /* Pull off the rest of the cause TLV from the chunk. */ skb_pull(chunk->skb, elen); @@ -348,10 +344,7 @@ struct sctp_ulpevent *sctp_ulpevent_make /* Embed the event fields inside the cloned skb. */ event = sctp_skb2event(skb); - event = sctp_ulpevent_init(event, MSG_NOTIFICATION); - - if (!event) - goto fail; + sctp_ulpevent_init(event, MSG_NOTIFICATION); sre = (struct sctp_remote_error *) skb_push(skb, sizeof(struct sctp_remote_error)); @@ -404,8 +397,7 @@ struct sctp_ulpevent *sctp_ulpevent_make * All notifications for a given association have the same association * identifier. For TCP style socket, this field is ignored. */ - skb = sctp_event2skb(event); - sctp_ulpevent_set_owner(skb, asoc); + sctp_ulpevent_set_owner(event, asoc); sre->sre_assoc_id = sctp_assoc2id(asoc); return event; @@ -420,13 +412,16 @@ fail: * 5.3.1.4 SCTP_SEND_FAILED */ struct sctp_ulpevent *sctp_ulpevent_make_send_failed( - const struct sctp_association *asoc, sctp_chunk_t *chunk, + const struct sctp_association *asoc, struct sctp_chunk *chunk, __u16 flags, __u32 error, int gfp) { struct sctp_ulpevent *event; struct sctp_send_failed *ssf; struct sk_buff *skb; + /* Pull off any padding. */ + int len = ntohs(chunk->chunk_hdr->length); + /* Make skb with more room so we can prepend notification. */ skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_send_failed), /* headroom */ @@ -436,13 +431,12 @@ struct sctp_ulpevent *sctp_ulpevent_make goto fail; /* Pull off the common chunk header and DATA header. */ - skb_pull(skb, sizeof(sctp_data_chunk_t)); + skb_pull(skb, sizeof(struct sctp_data_chunk)); + len -= sizeof(struct sctp_data_chunk); /* Embed the event fields inside the cloned skb. */ event = sctp_skb2event(skb); - event = sctp_ulpevent_init(event, MSG_NOTIFICATION); - if (!event) - goto fail; + sctp_ulpevent_init(event, MSG_NOTIFICATION); ssf = (struct sctp_send_failed *) skb_push(skb, sizeof(struct sctp_send_failed)); @@ -477,7 +471,8 @@ struct sctp_ulpevent *sctp_ulpevent_make * This field is the total length of the notification data, including * the notification header. */ - ssf->ssf_length = skb->len; + ssf->ssf_length = sizeof(struct sctp_send_failed) + len; + skb_trim(skb, ssf->ssf_length); /* Socket Extensions for SCTP * 5.3.1.4 SCTP_SEND_FAILED @@ -498,6 +493,11 @@ struct sctp_ulpevent *sctp_ulpevent_make */ memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); + /* Per TSVWG discussion with Randy. Allow the application to + * ressemble a fragmented message. + */ + ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; + /* Socket Extensions for SCTP * 5.3.1.4 SCTP_SEND_FAILED * @@ -507,8 +507,7 @@ struct sctp_ulpevent *sctp_ulpevent_make * same association identifier. For TCP style socket, this field is * ignored. */ - skb = sctp_event2skb(event); - sctp_ulpevent_set_owner(skb, asoc); + sctp_ulpevent_set_owner(event, asoc); ssf->ssf_assoc_id = sctp_assoc2id(asoc); return event; @@ -571,7 +570,7 @@ struct sctp_ulpevent *sctp_ulpevent_make * All notifications for a given association have the same association * identifier. For TCP style socket, this field is ignored. */ - sctp_ulpevent_set_owner(skb, asoc); + sctp_ulpevent_set_owner(event, asoc); sse->sse_assoc_id = sctp_assoc2id(asoc); return event; @@ -588,11 +587,12 @@ fail: * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) */ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, - sctp_chunk_t *chunk, int gfp) + struct sctp_chunk *chunk, + int gfp) { struct sctp_ulpevent *event; struct sctp_sndrcvinfo *info; - struct sk_buff *skb, *list; + struct sk_buff *skb; size_t padding, len; /* Clone the original skb, sharing the data. */ @@ -618,24 +618,15 @@ struct sctp_ulpevent *sctp_ulpevent_make /* Fixup cloned skb with just this chunks data. */ skb_trim(skb, chunk->chunk_end - padding - skb->data); - /* Set up a destructor to do rwnd accounting. */ - sctp_ulpevent_set_owner_r(skb, asoc); - /* Embed the event fields inside the cloned skb. */ event = sctp_skb2event(skb); /* Initialize event with flags 0. */ - event = sctp_ulpevent_init(event, 0); - if (!event) - goto fail_init; + sctp_ulpevent_init(event, 0); event->iif = sctp_chunk_iif(chunk); - /* Note: Not clearing the entire event struct as - * this is just a fragment of the real event. However, - * we still need to do rwnd accounting. - */ - for (list = skb_shinfo(skb)->frag_list; list; list = list->next) - sctp_ulpevent_set_owner_r(list, asoc); + + sctp_ulpevent_receive_data(event, asoc); info = (struct sctp_sndrcvinfo *) &event->sndrcvinfo; @@ -726,9 +717,6 @@ struct sctp_ulpevent *sctp_ulpevent_make return event; -fail_init: - kfree_skb(skb); - fail: return NULL; } @@ -745,7 +733,7 @@ struct sctp_ulpevent *sctp_ulpevent_make const struct sctp_association *asoc, __u32 indication, int gfp) { struct sctp_ulpevent *event; - struct sctp_rcv_pdapi_event *pd; + struct sctp_pdapi_event *pd; struct sk_buff *skb; event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), @@ -754,8 +742,8 @@ struct sctp_ulpevent *sctp_ulpevent_make goto fail; skb = sctp_event2skb(event); - pd = (struct sctp_rcv_pdapi_event *) - skb_put(skb, sizeof(struct sctp_rcv_pdapi_event)); + pd = (struct sctp_pdapi_event *) + skb_put(skb, sizeof(struct sctp_pdapi_event)); /* pdapi_type * It should be SCTP_PARTIAL_DELIVERY_EVENT @@ -770,9 +758,9 @@ struct sctp_ulpevent *sctp_ulpevent_make * * This field is the total length of the notification data, including * the notification header. It will generally be sizeof (struct - * sctp_rcv_pdapi_event). + * sctp_pdapi_event). */ - pd->pdapi_length = sizeof(struct sctp_rcv_pdapi_event); + pd->pdapi_length = sizeof(struct sctp_pdapi_event); /* pdapi_indication: 32 bits (unsigned integer) * @@ -784,6 +772,7 @@ struct sctp_ulpevent *sctp_ulpevent_make * * The association id field, holds the identifier for the association. */ + sctp_ulpevent_set_owner(event, asoc); pd->pdapi_assoc_id = sctp_assoc2id(asoc); return event; @@ -801,7 +790,7 @@ __u16 sctp_ulpevent_get_notification_typ skb = sctp_event2skb((struct sctp_ulpevent *)event); notification = (union sctp_notification *) skb->data; - return notification->h.sn_type; + return notification->sn_header.sn_type; } /* Copy out the sndrcvinfo into a msghdr. */ @@ -815,69 +804,115 @@ void sctp_ulpevent_read_sndrcvinfo(const } } -/* Do accounting for bytes just read by user. */ -static void sctp_rcvmsg_rfree(struct sk_buff *skb) +/* Stub skb destructor. */ +static void sctp_stub_rfree(struct sk_buff *skb) { - struct sctp_association *asoc; - struct sctp_ulpevent *event; - - /* Current stack structures assume that the rcv buffer is - * per socket. For UDP style sockets this is not true as - * multiple associations may be on a single UDP-style socket. - * Use the local private area of the skb to track the owning - * association. - */ - event = sctp_skb2event(skb); - asoc = event->event_asoc; - sctp_assoc_rwnd_increase(asoc, skb_headlen(skb)); - sctp_association_put(asoc); +/* WARNING: This function is just a warning not to use the + * skb destructor. If the skb is shared, we may get the destructor + * callback on some processor that does not own the sock_lock. This + * was occuring with PACKET socket applications that were monitoring + * our skbs. We can't take the sock_lock, because we can't risk + * recursing if we do really own the sock lock. Instead, do all + * of our rwnd manipulation while we own the sock_lock outright. + */ } -/* Charge receive window for bytes received. */ -static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, - struct sctp_association *asoc) +/* Hold the association in case the msg_name needs read out of + * the association. + */ +static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, + const struct sctp_association *asoc) { - struct sctp_ulpevent *event; + struct sk_buff *skb; - /* The current stack structures assume that the rcv buffer is - * per socket. For UDP-style sockets this is not true as - * multiple associations may be on a single UDP-style socket. - * We use the local private area of the skb to track the owning - * association. + /* Cast away the const, as we are just wanting to + * bump the reference count. */ - sctp_association_hold(asoc); + sctp_association_hold((struct sctp_association *)asoc); + skb = sctp_event2skb(event); skb->sk = asoc->base.sk; - event = sctp_skb2event(skb); - event->event_asoc = asoc; + event->sndrcvinfo.sinfo_assoc_id = sctp_assoc2id(asoc); + skb->destructor = sctp_stub_rfree; +} + +/* A simple destructor to give up the reference to the association. */ +static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) +{ + sctp_association_put(event->sndrcvinfo.sinfo_assoc_id); +} - skb->destructor = sctp_rcvmsg_rfree; +/* Do accounting for bytes received and hold a reference to the association + * for each skb. + */ +static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, + struct sctp_association *asoc) +{ + struct sk_buff *skb, *frag; + skb = sctp_event2skb(event); + /* Set the owner and charge rwnd for bytes received. */ + sctp_ulpevent_set_owner(event, asoc); sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); + + /* Note: Not clearing the entire event struct as this is just a + * fragment of the real event. However, we still need to do rwnd + * accounting. + * In general, the skb passed from IP can have only 1 level of + * fragments. But we allow multiple levels of fragments. + */ + for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc); + } } -/* A simple destructor to give up the reference to the association. */ -static void sctp_ulpevent_rfree(struct sk_buff *skb) +/* Do accounting for bytes just read by user and release the references to + * the association. + */ +static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) { - struct sctp_ulpevent *event; + struct sk_buff *skb, *frag; - event = sctp_skb2event(skb); - sctp_association_put(event->event_asoc); + /* Current stack structures assume that the rcv buffer is + * per socket. For UDP style sockets this is not true as + * multiple associations may be on a single UDP-style socket. + * Use the local private area of the skb to track the owning + * association. + */ + + skb = sctp_event2skb(event); + sctp_assoc_rwnd_increase(event->sndrcvinfo.sinfo_assoc_id, + skb_headlen(skb)); + + /* Don't forget the fragments. */ + for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + /* NOTE: skb_shinfos are recursive. Although IP returns + * skb's with only 1 level of fragments, SCTP reassembly can + * increase the levels. + */ + sctp_ulpevent_release_data(sctp_skb2event(frag)); + } + sctp_ulpevent_release_owner(event); } -/* Hold the association in case the msg_name needs read out of - * the association. +/* Free a ulpevent that has an owner. It includes releasing the reference + * to the owner, updating the rwnd in case of a DATA event and freeing the + * skb. + * See comments in sctp_stub_rfree(). */ -static void sctp_ulpevent_set_owner(struct sk_buff *skb, - const struct sctp_association *asoc) +void sctp_ulpevent_free(struct sctp_ulpevent *event) { - struct sctp_ulpevent *event; + if (sctp_ulpevent_is_notification(event)) + sctp_ulpevent_release_owner(event); + else + sctp_ulpevent_release_data(event); - /* Cast away the const, as we are just wanting to - * bump the reference count. - */ - sctp_association_hold((struct sctp_association *)asoc); - skb->sk = asoc->base.sk; - event = sctp_skb2event(skb); - event->event_asoc = (struct sctp_association *)asoc; - skb->destructor = sctp_ulpevent_rfree; + kfree_skb(sctp_event2skb(event)); +} + +/* Purge the skb lists holding ulpevents. */ +void sctp_queue_purge_ulpevents(struct sk_buff_head *list) +{ + struct sk_buff *skb; + while ((skb = skb_dequeue(list)) != NULL) + sctp_ulpevent_free(sctp_skb2event(skb)); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.25/net/sctp/ulpqueue.c linux-2.4.26-pre1/net/sctp/ulpqueue.c --- linux-2.4.25/net/sctp/ulpqueue.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.26-pre1/net/sctp/ulpqueue.c 2004-02-25 15:40:27.000000000 +0000 @@ -118,7 +118,7 @@ void sctp_ulpq_free(struct sctp_ulpq *ul } /* Process an incoming DATA chunk. */ -int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, sctp_chunk_t *chunk, +int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, int gfp) { struct sk_buff_head temp; @@ -163,7 +163,7 @@ int sctp_clear_pd(struct sock *sk) sp->pd_mode = 0; if (!skb_queue_empty(&sp->pd_lobby)) { struct list_head *list; - sctp_skb_list_tail(&sp->pd_lobby, &sk->receive_queue); + sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue); list = (struct list_head *)&sctp_sk(sk)->pd_lobby; INIT_LIST_HEAD(list); return 1; @@ -189,7 +189,7 @@ int sctp_ulpq_tail_event(struct sctp_ulp /* If the socket is just going to throw this away, do not * even try to deliver it. */ - if ((sk->dead) || (sk->shutdown & RCV_SHUTDOWN)) + if (sk->dead || (sk->sk_shutdown & RCV_SHUTDOWN)) goto out_free; /* Check if the user wishes to receive this event. */ @@ -202,13 +202,13 @@ int sctp_ulpq_tail_event(struct sctp_ulp */ if (!sctp_sk(sk)->pd_mode) { - queue = &sk->receive_queue; + queue = &sk->sk_receive_queue; } else if (ulpq->pd_mode) { if (event->msg_flags & MSG_NOTIFICATION) queue = &sctp_sk(sk)->pd_lobby; else { clear_pd = event->msg_flags & MSG_EOR; - queue = &sk->receive_queue; + queue = &sk->sk_receive_queue; } } else queue = &sctp_sk(sk)->pd_lobby; @@ -229,15 +229,15 @@ int sctp_ulpq_tail_event(struct sctp_ulp if (clear_pd) sctp_ulpq_clear_pd(ulpq); - if (queue == &sk->receive_queue) - sk->data_ready(sk, 0); + if (queue == &sk->sk_receive_queue) + sk->sk_data_ready(sk, 0); return 1; out_free: if (sctp_event2skb(event)->list) - skb_queue_purge(sctp_event2skb(event)->list); + sctp_queue_purge_ulpevents(sctp_event2skb(event)->list); else - kfree_skb(sctp_event2skb(event)); + sctp_ulpevent_free(event); return 0; } @@ -289,7 +289,7 @@ static inline void sctp_ulpq_store_reasm * payload was fragmented on the way and ip had to reassemble them. * We add the rest of skb's to the first skb's fraglist. */ -static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag) +static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag) { struct sk_buff *pos; struct sctp_ulpevent *event; @@ -325,11 +325,10 @@ static inline struct sctp_ulpevent *sctp /* Remove the fragment from the reassembly queue. */ __skb_unlink(pos, pos->list); - + /* Break if we have reached the last fragment. */ if (pos == l_frag) break; - pos->next = pnext; pos = pnext; }; @@ -570,7 +569,7 @@ static inline void sctp_ulpq_retrieve_or /* We are holding the chunks by stream, by SSN. */ sctp_skb_for_each(pos, &ulpq->lobby, tmp) { - cevent = sctp_skb2event(pos); + cevent = (struct sctp_ulpevent *) pos->cb; csid = cevent->sndrcvinfo.sinfo_stream; cssn = cevent->sndrcvinfo.sinfo_ssn; @@ -613,7 +612,7 @@ static inline void sctp_ulpq_store_order sid = event->sndrcvinfo.sinfo_stream; ssn = event->sndrcvinfo.sinfo_ssn; - cevent = sctp_skb2event(pos); + cevent = (struct sctp_ulpevent *) pos->cb; csid = cevent->sndrcvinfo.sinfo_stream; cssn = cevent->sndrcvinfo.sinfo_ssn; if (sid > csid) { @@ -630,7 +629,7 @@ static inline void sctp_ulpq_store_order * stream ID and then by SSN. */ skb_queue_walk(&ulpq->lobby, pos) { - cevent = sctp_skb2event(pos); + cevent = (struct sctp_ulpevent *) pos->cb; csid = cevent->sndrcvinfo.sinfo_stream; cssn = cevent->sndrcvinfo.sinfo_ssn; @@ -773,7 +772,7 @@ void sctp_ulpq_renege(struct sctp_ulpq * freed = 0; - if (skb_queue_empty(&asoc->base.sk->receive_queue)) { + if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) { freed = sctp_ulpq_renege_order(ulpq, needed); if (freed < needed) { freed += sctp_ulpq_renege_frags(ulpq, needed - freed); @@ -812,9 +811,9 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq SCTP_PARTIAL_DELIVERY_ABORTED, gfp); if (ev) - __skb_queue_tail(&sk->receive_queue, sctp_event2skb(ev)); + __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev)); /* If there is data waiting, send it up the socket now. */ if (sctp_ulpq_clear_pd(ulpq) || ev) - sk->data_ready(sk, 0); + sk->sk_data_ready(sk, 0); }